How can I display a pdf using a graphQL query and react?

How can I display a pdf using a graphQL query and react?


-1

My task is to use a query, send the mandatory variables and get a pdf from the BE.
Right now, I have the code but I can’t get the pdf downloaded.
In the network tab I can see my request and the response is a url as string
This is the request:

query getCollectionReportOverview(
  $filterReportCollectionOverview: ReportCollectionOverviewInput!
) {
  getCollectionReportOverview(
    filterReportCollectionOverview: $filterReportCollectionOverview
  )
}
{
  "filterReportCollectionOverview": {
    "collectionNames": [
      "2024 copy"
    ],
    "collectionNumbers": [
      49464
    ],
    "brandName": "fake it",
    "createdByName": "John doe",
    "createdBy": "125256",
    "sortby": "masterCategoryName"
  }
}

I’m not entirely sure about the code for getting the pdf but the query works.
As a result, the response is a url as a string.
I’ve tried this code to display the pdf in the app I can’t see any pdf downloaded.
Here is my code

const CreateViewButton = ({ isLargeScreen, onClick, isOptionSelected }: ButtonProps): ReactElement => (
  <Button size={isLargeScreen ? 'large' : 'small'} disabled={!isOptionSelected} onClick={(): void => void onClick()}>
    view report
  </Button>
);

 export const ReportsFooter = ({
    isOptionSelected,
    handleOnClearAll,
    sortby,
    collectionNames,
    collectionNumbers,
    brandName,
   }: {
    isOptionSelected: boolean;
    handleOnClearAll: () => void;
    sortby: string;
    collectionNames: Array<string>;
    collectionNumbers: Array<number>;
    brandName: string;
  }): ReactElement => {
  const theme = useTheme();
  const isLargeScreen = useMediaQuery(theme.breakpoints.up('lg'));

  const { buyingProfile } = useProfiles();

  const [getCollectionReportOverview, { loading, error, data, called }] = useLazyQuery(
    GET_COLLECTION_REPORT_OVERVIEW,
    {
      onCompleted: (result) => {
        console.log('Request completed');
        const base64Pdf = result?.data?.getCollectionReportOverview;
        console.log(base64Pdf);
        if (base64Pdf) {
          downloadPdf(base64Pdf);
        }
      },
      onError: (error) => {
        console.error('GraphQL error:', error);
      },
      fetchPolicy: 'network-only',
      context: { clientName: GraphClientNames['reports'] },
    }
  );

  const filterReportCollectionOverview = {
    collectionNames: collectionNames,
    collectionNumbers: collectionNumbers,
    brandName: brandName,
    createdByName: buyingProfile?.name,
    createdBy:  buyingProfile?.userNumber,
    sortBy: sortby,
  };

  const handleClickCreateViewButton = (): void => {
    console.log('Button clicked'); // Add this log
    getCollectionReportOverview({
      variables: {
        filterReportCollectionOverview: filterReportCollectionOverview,
      },
    });
  };

  const downloadPdf = (base64Pdf: string, fileName = 'report.pdf') => {
    console.log('Downloading PDF'); // Add this log
    const blob = b64toBlob(base64Pdf, 'application/pdf');
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = fileName;
    link.click();
    URL.revokeObjectURL(url);
  };

  const b64toBlob = (base64: string, type = 'application/octet-stream') => {
    const byteCharacters = atob(base64);
    const byteArrays: Array<number> = [];

    for (let offset = 0; offset < byteCharacters.length; offset += 512) {
      const slice = byteCharacters.slice(offset, offset + 512);
      const byteNumbers = new Array<number>(slice.length);

      for (let i = 0; i < slice.length; i++) {
        byteNumbers[i] = slice.charCodeAt(i);
      }

      byteArrays.push(...byteNumbers);
    }

    const blob = new Blob([new Uint8Array(byteArrays)], { type });
    return blob;
  };

  const hintComponent = (
    <Box
      sx={{
        display: 'flex',
        flexDirection: 'column',
        flex: '1',
        alignItems: 'center',
      }}
    >
      <Box
        sx={{
          display: 'flex',
          alignItems: 'center',
          flexDirection: 'row',
          justifyContent: 'space-between',
          flex: '1',
        }}
      >
        <Typography variant={isLargeScreen ? 'body.default' : 'bodySmall.default'} sx={{ whiteSpace: 'nowrap' }}>
          * required:&nbsp;
        </Typography>
        <Typography variant={isLargeScreen ? 'body.highlight' : 'bodySmall.highlight'} sx={{ paddingLeft: 1, whiteSpace: 'nowrap' }}>
          {isOptionSelected ? '1/1' : '0/1'}
        </Typography>
      </Box>
      <Typography variant='captions.default' sx={{ paddingLeft: 1, whiteSpace: 'nowrap' }}>
        {isOptionSelected ? "You're good to go" : 'Select a Collection'}
      </Typography>
    </Box>
  );

  return (
    <ProcessFooter
      leftSideComponents={[
        <Button
          key='cancel-button'
          variant="outlined"
          size={isLargeScreen ? 'large' : 'small'}
          disabled={!isOptionSelected}
          onClick={handleOnClearAll}
        >
          <CrossIcon style={{ padding: '0px 12px 0px 0px' }} />
          clear all
        </Button>,
      ]}
      hint={hintComponent}
      rightSideComponents={[
        loading ? (
          <Stack
            justifyContent="center"
            alignItems="center"
            spacing={5}
          >
            <LoadingSpinner />
            <Typography variant="headings.h4" textAlign="center">
              generating report
            </Typography>
          </Stack>
        ) : (
          <CreateViewButton
            key='create-orders-button'
            isLargeScreen={isLargeScreen}
            isOptionSelected={isOptionSelected}
            sortbyValue={sortby}
            collectionNames={collectionNames}
            collectionNumbers={collectionNumbers}
            brandName={brandName}
            onClick={handleClickCreateViewButton}
          />
        ),
      ]}
    />
  );
};

If someone can guide me and counsel me as I’m a bit lost and confused.

I’m not entirely sure about the code for getting the pdf but the query works.
As a result, the response is a url as a string.

New contributor

Jdeveloper is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


Load 7 more related questions


Show fewer related questions

0



Leave a Reply

Your email address will not be published. Required fields are marked *