|
- import React, { useEffect, useRef, useState } from 'react';
- import { Button, Grid, InputLabel, TextField } from '@mui/material';
- import { GeneralConfirmWindow, notifySaveSuccess } from "../../../utils/CommonFunction";
- import axios from 'axios';
- import {apiPath, adobeAPIKey} from "../../../auth/utils";
- import {
- GET_PDF_TEMPLATE_PATH,
- GET_PDF_PATH,
- POST_PDF_PATH
- } from "../../../utils/ApiPathConst";
- import {LIONER_BUTTON_THEME} from "../../../themes/colorConst";
- import {ThemeProvider} from "@emotion/react";
- import {useNavigate} from "react-router-dom";
- import {useForm} from "react-hook-form";
- import {useLocation, useParams} from "react-router-dom";
-
- // Import your chosen commercial PDF SDK (e.g., PSPDFKit)
- import PSPDFKit from 'pspdfkit';
- import WebViewer from '@compdfkit_pdf_sdk/webviewer';
- import Nutrient from "@nutrient-sdk/viewer";
- import { CollectionsBookmarkRounded } from '../../../../node_modules/@mui/icons-material/index';
- import LoadingComponent from "../../extra-pages/LoadingComponent";
- import { fill } from 'lodash';
-
- function PDF() {
- const viewerRef = useRef(null); // Ref for the DOM element where PDF will render
- const [pdfLoaded, setPdfLoaded] = useState(false);
- const [viewerLoaded, setViewerLoaded] = useState(false);
- const [viewInstance,setViewInstance] = useState();
- const [adobeDCView,setAdobeDCView] = useState();
- const [pdfUrl, setPdfUrl] = useState();
- const [record, setRecord] = useState();
-
- const navigate = useNavigate()
- const params = useParams();
- const location = useLocation();
- const queryParams = new URLSearchParams(location.search);
- const refId = queryParams.get("refId");
-
- const loadPdfForm = async (id, templateId = 0, clientId = 0) => {
- if (!pdfLoaded) {
- if (id > 0) {
- // axios.get(`${apiPath}${GET_PDF_TEMPLATE_PATH}`, {
- axios.get(`${apiPath}${GET_PDF_PATH}/${id}`, {
- // responseType: 'arraybuffer', // Essential for binary data
- })
- .then((response) => {
- if (response.status === 200) {
- // setRecord(rec => {
- // const { ["blobValue"]: _, ...newData } = response.data; // Destructure to remove blobValue
- // return newData;
- // });
- const res = response.data;
- setRecord({ // WIP - allow to update all record
- id : res.id,
- clientId: res.clientId,
- templateId: res.templateId
- })
-
- //Convert Base64 to binary data
- const byteChar = atob(response.data.blobValue);
- const byteNum = new Uint8Array(byteChar.length);
-
- for (let i = 0; i < byteChar.length; i++) {
- byteNum[i] = byteChar.charCodeAt(i);
- }
-
- handlePdfUrl(byteNum);
- setPdfLoaded(true);
- }
- })
- .catch(error => {
- console.log(error);
- return false;
- });
-
- } else {
- axios.get(`${apiPath}${GET_PDF_TEMPLATE_PATH}`, {
- // axios.get(`${apiPath}${GET_PDF_TEMPLATE_PATH}/${templateId}`, {
- responseType: 'arraybuffer', // Essential for binary data
- params: {
- templateId: templateId,
- clientId: clientId,
- },
- })
- .then((response) => {
- if (response.status === 200) {
- handlePdfUrl(response.data);
- setPdfLoaded(true);
- }
- })
- .catch(error => {
- console.log(error);
- return false;
- });
- }
- }
- };
-
- const handlePdfUrl = (pdfBytes) => {
- const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
- // const pdfFile = new File([pdfBlob], 'document.pdf', { type: 'application/pdf' });
- console.log(pdfBlob);
- const pdfUrl = URL.createObjectURL(pdfBlob);
- setPdfUrl(pdfUrl);
- }
-
- const loadPdfViewer = async () => {
- if (pdfLoaded && viewerRef.current && !viewerLoaded && !adobeDCView) {
- try {
- loadAdobeSDK();
- } catch (error) {
- console.error('Error loading PDF:', error);
- }
- }
- };
-
- const loadAdobeSDK = async() => {
- // const token = localStorage.getItem('accessToken');
- if (window.AdobeDC) {
- const DCViewer = (new window.AdobeDC.View({
- clientId: `${adobeAPIKey}`,
- divId: 'adobe-dc-view',
- }));
-
- setAdobeDCView(DCViewer);
-
- await DCViewer.previewFile(
- {
- content: {
- location: {
- url: pdfUrl,
- // headers: [{ key: 'Authorization', value: `Bearer ${token}` }],
- },
- },
- metaData: { fileName: 'document.pdf'/*templateName */ },
- },
- {
- embedMode: 'FULL_WINDOW',
- showAnnotationTools: true,
- enableFormFilling: true,
- }
-
- ).catch(error => {
- console.error('Preview error:', error);
- setError('Failed to load PDF: ' + error.message);
-
- }).then(instance => {
- URL.revokeObjectURL(pdfUrl);
- setViewInstance(instance);
- console.log('Instance: ', instance);
- setViewerLoaded(true);
- });
-
- DCViewer.registerCallback(
- window.AdobeDC.View.Enum.CallbackType.SAVE_API,
- handleSavePdf,
- { autoSaveFrequency: 0, enableFormFilling: true }
- );
- } else {
- console.error('AdobeDC not available');
- setError('Adobe SDK not loaded');
- }
- };
-
- useEffect(() => {
- if (params.id !== null) {
- const pdfData = (params.id).split("T");
-
- if (pdfData[0] > 0) { // Existing Record
- loadPdfForm(pdfData[0]);
- } else { // New Record
- const clientId = pdfData[0] * -1;
- const templateId = pdfData[1] * 1;
- setRecord({
- id: -1,
- clientId: clientId, //If PDF ID is negative, convert it to client ID
- templateId: templateId});
- loadPdfForm(-1, templateId, clientId); // Load new Template
- }
- }
- }, [params.id]);
-
- useEffect(() => { // Update Save function callback after record is updated
- console.log("Record Updated: ",record);
- if (record && adobeDCView) {
- adobeDCView.registerCallback(
- window.AdobeDC.View.Enum.CallbackType.SAVE_API,
- handleSavePdf,
- { autoSaveFrequency: 0, enableFormFilling: true }
- );
- }
- }, [record]);
-
- useEffect(() => {
- loadPdfViewer();
- }, [viewerRef.current, pdfLoaded]);
-
- const handleSavePdf = async (metaData, content, options) => {
- try {
- const filledPdfBlob = new Blob([content], { type: 'application/pdf' });
- // Create FormData to send the file to Spring Boot
- const formData = new FormData();
- formData.append('file', filledPdfBlob, 'filled_form.pdf');
- formData.append('record', JSON.stringify(record));
- // Send the filled PDF to your Spring Boot backend's save endpoint
- await axios.post(`${apiPath}${POST_PDF_PATH}`, formData, {
- headers: {
- 'Content-Type': 'multipart/form-data' // Important for file uploads
- },
- })
- .then(response => {
- console.log('PDF saved on server:', response.data);
- setRecord({
- id: response.data.data.id,
- clientId: record.clientId,
- templateId: record.templateId
- });
- notifySaveSuccess()});
- return {
- code: window.AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
- data: { metaData } // Return metaData to prevent t.data undefined
- };
- } catch (error) {
- console.error('Error saving PDF:', error);
- alert('Failed to save PDF.');
- return { code: window.AdobeDC.View.Enum.ApiResponseCode.FAIL };
- }
- };
-
- const handlePrintPdf = () => {
- if (viewInstance.current) {
- // Trigger the SDK's built-in print functionality
- viewInstance.current.print();
- }
- };
-
- // Confirmation Window //
- const [isWindowOpen, setIsWindowOpen] = useState(false);
-
- const handleClose = () => {
- setIsWindowOpen(false);
- };
-
- const handleBackClick = () => {
- setIsWindowOpen(true);
- };
-
- const handleBack = async () => {
- if (viewerLoaded) {
- await Nutrient.unload(viewerRef.current);
- }
- navigate(`/pdf/${record.clientId}`);
- };
-
- const handleTest = () => {
- // const element = document.getElementById('pdfViewer');
- // const inputFields = element.querySelectorAll('iframe')[0];
- // console.log(element);
- // console.log(inputFields.contentDocument);
-
- // inputFields.forEach(input => {
- // console.log('Name:', input.name, 'Value:', input.value);
- // });
- };
-
- return (
- <ThemeProvider theme={LIONER_BUTTON_THEME}>
- <div className="pdf-form-page"> {/* This is your 'pdfForm' page */}
- <header className="page-header">
- <Grid item>
- <Grid container>
- <Grid item sx={{ml:3, mr:1.5, mb:2}}>
- {/* <Button
- variant="contained"
- type="submit"
- color="save"
- // disabled={!viewerLoaded}
- onClick={handleTest}
- // onClick={handleSavePdf}
- >
- Save
- </Button> */}
- </Grid>
- <Grid item sx={{ml:{xs:1.5, md:1.5, lg:1.5}, mr:1.5, mb:2}}>
- <Button
- variant="contained"
- color="cancel"
- onClick={viewerLoaded ? handleBackClick : handleBack}
- >
- Back
- </Button>
- <GeneralConfirmWindow
- isWindowOpen={isWindowOpen}
- title={"Back to previous page"}
- //content={`Confirm to delete Event "${clientDetail.name}" ?`}
- content={`Are you sure to leave this page?\nAny unsaved progress will be lost.`}
- onNormalClose={handleClose}
- onConfirmClose={handleBack}
- />
- </Grid>
-
- {/* <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:0.5}}>
- <InputLabel htmlFor="remarks">Remarks</InputLabel>
- </Grid>
- <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:0.5}}>
- <TextField
- fullWidth
- inputProps={{maxLength: 500}}
- id="remarks"
- autoComplete="off"
- />
- </Grid> */}
- </Grid>
- </Grid>
- {/* {pdfLoaded ? (
- <div className="action-buttons">
- <button onClick={handleSavePdf} className="action-button save-button">
- Save Filled PDF
- </button>
- <button onClick={handlePrintPdf} className="action-button print-button">
- Print PDF
- </button>
- </div>
- ) : (
- <p>Loading PDF viewer...</p>
- )} */}
- </header>
- {!pdfLoaded && (<LoadingComponent/>)}
- <div id="adobe-dc-view" ref={viewerRef} style={{
- width: '100%',
- height: 'calc(100vh - 180px)', // Adjust height based on header/footer
- border: '1px solid #ccc',
- }}
- hidden={!pdfLoaded}
- />
- {/* <div
- // id={viewerRef}
- ref={viewerRef}
- // className="pdf-viewer-container"
- style={{
- width: '100%',
- height: 'calc(100vh - 180px)', // Adjust height based on header/footer
- border: '1px solid #ccc',
- }}
- >
- </div> */}
- </div>
- </ThemeProvider>
- );
- }
-
- export default PDF;
|