Search code examples
reactjstypescriptreact-pdfrenderer

React pdf render maximum item per page


I am trying to create a function to generate a pdf with a list of qr code. The number of qr code can be many, so I wish to limit there is maximum 9 qr code and 3 qr code in a row. What should I do to achieve this.

function QrCodePDF(props: QrCodeInfo[]) {
  const qrCodeInfo = props;
  const qrCodeItems: QrCodeInfo[] = [];

  for (let index in qrCodeInfo) {
    qrCodeItems.push({
      dealTitle: qrCodeInfo[index]!.dealTitle,
      qrCodeId: qrCodeInfo[index]!.qrCodeId,
      qrCodeUrl: qrCodeInfo[index]!.qrCodeUrl,
    });
  }

  return (
    <Document>
      <Page
        size="A4"
        style={{
          flexDirection: 'column',
          backgroundColor: '#fff',
          color: '#000',
          padding: 10,
        }}
        wrap={true}
      >
        <View
          style={{
            flex: 1,
            width: '100%',
            border: '1px solid #000',
          }}
          key={'QrCodeTable'}
        >
          <View
            style={{
              display: 'flex',
              width: '100%',
              fontWeight: 'bold',
              fontSize: '20px',
              textAlign: 'center',
              flexDirection: 'row',
              alignItems: 'center',
              borderBottom: '1px solid #000',
            }}
          >
            <Text
              style={{
                width: '100%',
                padding: 10,
              }}
            >
              Qr Code for {qrCodeItems[0]?.dealTitle}
            </Text>
          </View>
          <View
            style={{
              display: 'flex',
              flexWrap: 'wrap',
              flexDirection: 'row',
              alignItems: 'center',
              justifyContent: 'center',
            }}
            key={'QrCodeWrapper'}
          >
            {qrCodeItems.map((item, index) => {
              return (
                <View
                  key={index}
                  style={{
                    width: '33.33%',
                    alignItems: 'center',
                    flexDirection: 'row',
                    fontWeight: 'normal',
                    fontSize: '14px',
                    textAlign: 'left',
                    color: '#000',
                    flexWrap: 'wrap',
                    gap: 0,
                  }}
                  break={index > 3}
                  wrap={true}
                >
                  <Image
                    src={item.qrCodeUrl}
                    style={{ width: '100%', padding: 10 }}
                  ></Image>
                </View>
              );
            })}
          </View>
        </View>
      </Page>
    </Document>
  );
}

This is the code I tried, but it doesn't work as what I think. What can I try next?


Solution

  • I try to figure out myself by using Array.from with .splice

    const renderPage = (items: QrCodeInfo[], maximumQuantityPerPage: number) => {
      const viewItems = Array.from(
        { length: Math.ceil(items.length / maximumQuantityPerPage) },
        () => items.splice(0, maximumQuantityPerPage)
      );
    
      const renderedItem = viewItems.map(item => {
        return (
          <Page
            size="A4"
            style={{
              flexDirection: 'column',
              backgroundColor: PRIMARY_COLOR,
              color: BLACK,
              padding: 10,
            }}
            wrap={true}
          >
            <View
              style={{
                border: `1px solid ${BLACK}`,
                height: '100%',
              }}
            >
              <View
                style={{
                  textAlign: 'center',
                  fontSize: '20px',
                  fontWeight: 'bold',
                  display: 'flex',
                  padding: 10,
                  borderBottom: `1px solid ${BLACK}`,
                  justifyContent: 'center',
                  fontFamily: 'Poppins',
                }}
              >
                <Text>Qr code for {item[0]?.dealTitle}</Text>
              </View>
              <View
                style={{
                  display: 'flex',
                  flexWrap: 'wrap',
                  flexDirection: 'row',
                  alignItems: 'flex-start',
                  justifyContent: 'flex-start',
                }}
                key={'QrCodeWrapper'}
              >
                {item.map((qrCode, index) => {
                  return (
                    <View
                      key={index}
                      style={{
                        width: '33.33%',
                        color: BLACK,
                        padding: 10,
                      }}
                      break={index > 2}
                      wrap={false}
                    >
                      <Image
                        src={qrCode.qrCodeUrl}
                        style={{
                          width: '100%',
                          padding: 10,
                          backgroundColor: LIGHT_RED,
                        }}
                      ></Image>
                    </View>
                  );
                })}
              </View>
            </View>
          </Page>
        );
      });
    
      return renderedItem;
    };
    
    const QrCodePDF = (props: QrCodeInfo[]) => {
      const qrCodeInfo = props;
      const qrCodeItems: QrCodeInfo[] = [];
    
      for (let index in qrCodeInfo) {
        qrCodeItems.push({
          dealTitle: qrCodeInfo[index]!.dealTitle,
          qrCodeId: qrCodeInfo[index]!.qrCodeId,
          qrCodeUrl: qrCodeInfo[index]!.qrCodeUrl,
        });
      }
    
      return <Document>{renderPage(qrCodeItems, 12)}</Document>;
    };