cvyjojo / Tracker

https://tracker-ygpta.vercel.app
0 stars 0 forks source link

css #4

Open ygpta opened 10 months ago

ygpta commented 10 months ago

To download the PDF based on a button click in a React application using @react-pdf/renderer, you can use the PDFViewer component for previewing and PDFDownloadLink for downloading the PDF when the button is clicked. Here's how you can do it:

Step-by-Step Implementation

  1. Install the Library

Ensure @react-pdf/renderer is installed:

npm install @react-pdf/renderer
  1. Create the PDF Document Component

Define the structure of your PDF document to include multiple tables using @react-pdf/renderer components.

import React from 'react';
import { Page, Text, View, Document, StyleSheet, PDFDownloadLink } from '@react-pdf/renderer';

// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: 'column',
    backgroundColor: '#E4E4E4',
    padding: 10,
  },
  table: {
    display: 'table',
    width: 'auto',
    borderStyle: 'solid',
    borderWidth: 1,
    borderColor: '#bfbfbf',
    marginBottom: 20,
  },
  tableRow: {
    flexDirection: 'row',
  },
  tableCol: {
    width: '25%',
    borderStyle: 'solid',
    borderWidth: 1,
    borderColor: '#bfbfbf',
  },
  tableCell: {
    margin: 5,
    fontSize: 10,
  },
  header: {
    fontSize: 20,
    marginBottom: 10,
  },
});

const Table = ({ data, headers }) => (
  <View style={styles.table}>
    <View style={styles.tableRow}>
      {headers.map((header, index) => (
        <View key={index} style={styles.tableCol}>
          <Text style={styles.tableCell}>{header}</Text>
        </View>
      ))}
    </View>
    {data.map((row, rowIndex) => (
      <View key={rowIndex} style={styles.tableRow}>
        {row.map((cell, cellIndex) => (
          <View key={cellIndex} style={styles.tableCol}>
            <Text style={styles.tableCell}>{cell}</Text>
          </View>
        ))}
      </View>
    ))}
  </View>
);

// Create Document Component
const MyDocument = ({ tables }) => (
  <Document>
    <Page size="A4" style={styles.page}>
      {tables.map((table, index) => (
        <View key={index}>
          <Text style={styles.header}>{table.title}</Text>
          <Table data={table.data} headers={table.headers} />
        </View>
      ))}
    </Page>
  </Document>
);

const ExportToPDF = () => {
  // Example data for multiple tables
  const tables = [
    {
      title: 'Table 1',
      headers: ['Header 1', 'Header 2', 'Header 3', 'Header 4'],
      data: [
        ['Cell 1', 'Cell 2', 'Cell 3', 'Cell 4'],
        ['Cell 5', 'Cell 6', 'Cell 7', 'Cell 8'],
        // Add more rows as needed
      ],
    },
    {
      title: 'Table 2',
      headers: ['Header A', 'Header B', 'Header C', 'Header D'],
      data: [
        ['Cell A1', 'Cell B1', 'Cell C1', 'Cell D1'],
        ['Cell A2', 'Cell B2', 'Cell C2', 'Cell D2'],
        // Add more rows as needed
      ],
    },
    // Add more tables as needed
  ];

  return (
    <div>
      <PDFDownloadLink
        document={<MyDocument tables={tables} />}
        fileName="example.pdf"
      >
        {({ loading }) =>
          loading ? 'Loading document...' : <button>Download PDF</button>
        }
      </PDFDownloadLink>
    </div>
  );
};

export default ExportToPDF;
  1. Use the Export Component in Your App

Import and use the ExportToPDF component in your main application:

import React from 'react';
import ExportToPDF from './ExportToPDF';

const App = () => {
  return (
    <div className="App">
      <h1>My Application</h1>
      <ExportToPDF />
      {/* Other components and content */}
    </div>
  );
};

export default App;

Explanation

Customizing the Tables

You can add as many tables as needed by extending the tables array with more objects. Adjust the table styles and content according to your requirements.

Handling Large Content

@react-pdf/renderer handles pagination automatically, so if your tables span multiple pages, the library will manage the page breaks for you.

This approach ensures that all your tables, including those that might not be visible on the screen, are included in the PDF document, providing a complete and accurate representation of your data. By clicking the button, the user can download the PDF containing all the tables.

ygpta commented 1 month ago

Yes, you can adjust the PDF configuration to handle content that spans multiple pages. Here’s how you can modify the code to fit the content within the PDF pages and handle multiple pages if needed:

  1. Calculate Dimensions for Multiple Pages: Adjust the PDF generation to account for multiple pages if the content exceeds one page. Here's a modified version of the code:

    import React from 'react';
    import html2canvas from 'html2canvas';
    import jsPDF from 'jspdf';
    
    const ExportPDF = () => {
     const handleDownload = () => {
       const input = document.getElementById('capture');
    
       if (!input) {
         console.error('Element with id "capture" not found.');
         return;
       }
    
       html2canvas(input, { scale: 2 }).then((canvas) => {
         const imgData = canvas.toDataURL('image/png');
         const pdf = new jsPDF('p', 'mm', 'a4');
         const imgWidth = pdf.internal.pageSize.getWidth();
         const imgHeight = canvas.height * imgWidth / canvas.width;
         let position = 0;
         const pageHeight = pdf.internal.pageSize.height;
         const totalPages = Math.ceil(imgHeight / pageHeight);
    
         for (let page = 0; page < totalPages; page++) {
           const pageImgHeight = canvas.height * imgWidth / canvas.width;
           const imgPosition = page * pageHeight;
    
           pdf.addImage(imgData, 'PNG', 0, -imgPosition, imgWidth, imgHeight);
           if (page < totalPages - 1) {
             pdf.addPage();
           }
         }
    
         pdf.save('download.pdf');
       }).catch((error) => {
         console.error('Error generating PDF:', error);
       });
     };
    
     return (
       <div>
         <div id="capture">
           {/* Your component content */}
           <h1>Your Content</h1>
           <p>More content...</p>
         </div>
         <button onClick={handleDownload}>Download PDF</button>
       </div>
     );
    };
    
    export default ExportPDF;

Key Changes:

  1. Image Dimensions: Adjusted the imgWidth to the width of the PDF page.
  2. Page Height Calculation: Added pageHeight and used it to split content into multiple pages.
  3. Add Pages Dynamically: Added a loop to handle multiple pages based on content size.

How It Works:

This setup ensures that your content fits within the PDF pages and handles pagination automatically.