kelvinsuen пре 1 месец
родитељ
комит
f4c2538df2
14 измењених фајлова са 442 додато и 169 уклоњено
  1. +1
    -1
      src/components/AutoLogoutProvider.js
  2. +21
    -8
      src/menu-items/client.js
  3. +2
    -1
      src/menu-items/dashboard.js
  4. +2
    -1
      src/menu-items/index.js
  5. +9
    -9
      src/menu-items/setting.js
  6. +3
    -2
      src/pages/client/ClientMaintainPage/ClientForm.js
  7. +9
    -2
      src/pages/client/ClientSearchPage/ClientTable.js
  8. +158
    -103
      src/pages/pdf/PdfMaintainPage/index.js
  9. +106
    -34
      src/pages/pdf/PdfSearchPage/PdfSearchForm.js
  10. +14
    -4
      src/pages/pdf/PdfSearchPage/PdfTable.js
  11. +37
    -1
      src/pages/pdf/PdfSearchPage/index.js
  12. +12
    -1
      src/routes/ClientRoutes.js
  13. +3
    -1
      src/routes/MainRoutes.js
  14. +65
    -1
      src/utils/CommonFunction.js

+ 1
- 1
src/components/AutoLogoutProvider.js Прегледај датотеку

@@ -68,7 +68,7 @@ const AutoLogoutProvider = ({ children }) => {
} = useIdleTimer({
onIdle,
onActive,
timeout: 10_000,
timeout: 60_000,
throttle: 500,
crossTab: true,
syncTimers: 200,


+ 21
- 8
src/menu-items/client.js Прегледај датотеку

@@ -1,13 +1,17 @@
// assets
import BoyIcon from '@mui/icons-material/Boy';
import AssignmentIcon from '@mui/icons-material/Assignment';

// icons
const ClientIcon = () => {
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginLeft: '-4px' }}>
<BoyIcon fontSize="medium"/>
</div>
);

const icons = {
ClientIcon : () => { return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginLeft: '-4px' }}>
<BoyIcon fontSize="medium"/>
</div>
)
},
AssignmentIcon,
};

// ==============================|| MENU ITEMS - DASHBOARD ||============================== //
@@ -19,14 +23,23 @@ const client = {
//ability:['SUPPRESS','REMINDER'],
children: [
{
id: 'Client',
id: 'client',
title: 'Client',
type: 'item',
url: '/client',
icon: ClientIcon,
icon: icons.ClientIcon,
breadcrumbs: false,
ability:['VIEW','DASHBOARD']
},
// {
// id: 'template',
// title: 'Template',
// type: 'item',
// url: '/template',
// icon: icons.AssignmentIcon,
// breadcrumbs: false,
// ability:['VIEW','DASHBOARD']
// },
]
};



+ 2
- 1
src/menu-items/dashboard.js Прегледај датотеку

@@ -32,7 +32,8 @@ const dashboard = {
id: 'lionerdashboard',
title: <FormattedMessage id="Dashboard"/>,
type: 'item',
url: '/lionerDashboard',
url: '/client',
// url: '/lionerDashboard',
icon: icons.SpeedIcon,
breadcrumbs: false,
ability:['VIEW','DASHBOARD']


+ 2
- 1
src/menu-items/index.js Прегледај датотеку

@@ -12,7 +12,8 @@ import appreciation from "./appreciation";
// ==============================|| MENU ITEMS ||============================== //

const menuItems = {
items: [dashboard, client, setting]
items: [client, setting]
// items: [dashboard, client, setting]
};
// pages, utilities, support, misc



+ 9
- 9
src/menu-items/setting.js Прегледај датотеку

@@ -86,15 +86,15 @@ const setting = {
// breadcrumbs: false,
// ability:['MAINTAIN','CLIENT_DEPARTMENT']
// },
{
id: 'userGroup',
title: 'User Group',
type: 'item',
url: '/usergroupSearchview',
icon: icons.UsergroupAddOutlined,
breadcrumbs: false,
ability:['MAINTAIN','USER_GROUP']
},
// {
// id: 'userGroup',
// title: 'User Group',
// type: 'item',
// url: '/usergroupSearchview',
// icon: icons.UsergroupAddOutlined,
// breadcrumbs: false,
// ability:['MAINTAIN','USER_GROUP']
// },
{
id: 'user',
title: 'User',


+ 3
- 2
src/pages/client/ClientMaintainPage/ClientForm.js Прегледај датотеку

@@ -1012,14 +1012,15 @@ const ClientForm = ({ refClientDetail,

</Grid>
<Grid item sx={{ml:{xs:1.5,md:1.5,lg:1.5}, mr:3, mb:1, mt:2}}>
<Button
{!isNewRecord && (<Button
variant="contained"
color="delete"
disabled={isNewRecord || !ability.can('DELETE','EVENT')}
disabled={!ability.can('DELETE','EVENT')}
onClick={handleDeleteClick}
>
Delete
</Button>
)}
<GeneralConfirmWindow
isWindowOpen={isWindowOpen}
title={"Attention"}


+ 9
- 2
src/pages/client/ClientSearchPage/ClientTable.js Прегледај датотеку

@@ -91,15 +91,22 @@ export default function ClientTable({recordList}) {
id: 'fullname',
field: 'fullname',
headerName: 'Client Name',
flex: 2,
flex: 1.5,
renderCell: (params) => {
return (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
{params.row.title ? `(${params.row.title})` : ''} {params.value}
{params.value}
{/* {params.row.title ? `(${params.row.title})` : ''} {params.value} */}
</div>
);
}
},
{
id: 'title',
field: 'title',
headerName: 'Title',
flex: 1.5,
},
{
id: 'joinDate',
field: 'joinDate',


+ 158
- 103
src/pages/pdf/PdfMaintainPage/index.js Прегледај датотеку

@@ -1,8 +1,8 @@
import React, { useEffect, useRef, useState } from 'react';
import { Button, Grid } from '@mui/material';
import { Button, Grid, InputLabel, TextField } from '@mui/material';
import { GeneralConfirmWindow, notifySaveSuccess } from "../../../utils/CommonFunction";
import axios from 'axios';
import {apiPath, appURL} from "../../../auth/utils";
import {apiPath, adobeAPIKey} from "../../../auth/utils";
import {
GET_PDF_TEMPLATE_PATH,
GET_PDF_PATH,
@@ -16,14 +16,19 @@ 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 [pdfBytes, setPdfBytes] = useState();
const [adobeDCView,setAdobeDCView] = useState();
const [pdfUrl, setPdfUrl] = useState();
const [record, setRecord] = useState();
const navigate = useNavigate()
@@ -32,7 +37,7 @@ function PDF() {
const queryParams = new URLSearchParams(location.search);
const refId = queryParams.get("refId");

const loadPdfForm = async (id, templateId = 0) => {
const loadPdfForm = async (id, templateId = 0, clientId = 0) => {
if (!pdfLoaded) {
if (id > 0) {
// axios.get(`${apiPath}${GET_PDF_TEMPLATE_PATH}`, {
@@ -60,7 +65,7 @@ function PDF() {
byteNum[i] = byteChar.charCodeAt(i);
}

setPdfBytes(byteNum);
handlePdfUrl(byteNum);
setPdfLoaded(true);
}
})
@@ -71,11 +76,16 @@ function PDF() {

} 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) {
setPdfBytes(response.data);
handlePdfUrl(response.data);
setPdfLoaded(true);
}
})
@@ -87,66 +97,72 @@ function PDF() {
}
};

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) {
if (pdfLoaded && viewerRef.current && !viewerLoaded && !adobeDCView) {
try {
//New try
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
console.log(pdfBlob);
const pdfUrl = URL.createObjectURL(pdfBlob);
// console.log('Template: ');
// console.log(record);
// console.log('URL: ');
// console.log(pdfUrl);
// console.log('Viewer: ');
// console.log(viewerRef.current);
// await PSPDFKit.unload(viewerRef.current);
await PSPDFKit.load({//click into load
container: viewerRef.current,
// container: '#viewer',
document: pdfUrl,
// baseUrl: `./sdk/`, // Path to SDK assets
baseUrl: `${appURL}/sdk/`, // Path to SDK
// baseUrl: `${window.location.protocol}//${window.location.host}/${import.meta.env.BASE_URL}`,
// baseUrl: `https://cdn.jsdelivr.net/npm/pspdfkit@VERSION/dist/`, // Path to SDK assets so this is work?
// baseUrl: `${process.env.PUBLIC_URL}/`, // Path to SDK assets
disableWebAssemblyStreaming: true,
initialViewState: new PSPDFKit.ViewState({
sidebarMode: PSPDFKit.SidebarMode.THUMBNAILS
})
})
.then(instance => {
URL.revokeObjectURL(pdfUrl);
setViewInstance(instance);
console.log('instance: ');
console.log(instance);
setViewerLoaded(true);
// instance.addEventListener("formFields.load", (loadedFormFields) => {
// console.log("loaded fields:", loadedFormFields);
// });
const formFieldValues = instance.getFormFieldValues();
// console.log(formFieldValues); // => { textField: 'Text Value', checkBoxField: ['A', 'B'], buttonField: null }e.log(getFormFieldValues);
});

// instanceRef.current = instance;

// 3. Clean up on component unmount
// return () => {
// if (instance) {
// instance.unload(); // Unload SDK instance
// }
// URL.revokeObjectURL(pdfUrl); // Revoke the Blob URL
// };

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");
@@ -154,53 +170,61 @@ function PDF() {
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: pdfData[0] * -1, //If PDF ID is negative, convert it to client ID
templateId: pdfData[1],});
loadPdfForm(-1, pdfData[1]); // Load new Template
clientId: clientId, //If PDF ID is negative, convert it to client ID
templateId: templateId});
loadPdfForm(-1, templateId, clientId); // Load new Template
}
}
}, [params.id]);

// useEffect(() => {
// if (record) {
// console.log(record);
// loadPdfForm();
// }
// }, [record]);
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 () => {
if (viewInstance) {
try {
// Export the filled PDF from the SDK as an ArrayBuffer
const arrayBuffer = await viewInstance.exportPDF();
const filledPdfBlob = new Blob([arrayBuffer], { 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
const response = await axios.post(`${apiPath}${POST_PDF_PATH}`, formData, {
headers: {
'Content-Type': 'multipart/form-data' // Important for file uploads
},
});
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);
notifySaveSuccess();

if (viewerLoaded) {
await PSPDFKit.unload(viewerRef.current);
}
navigate(`/pdf/${record.clientId}`);
} catch (error) {
console.error('Error saving PDF:', error);
alert('Failed to save PDF.');
}
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 };
}
};

@@ -224,11 +248,22 @@ function PDF() {

const handleBack = async () => {
if (viewerLoaded) {
await PSPDFKit.unload(viewerRef.current);
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 */}
@@ -236,15 +271,16 @@ function PDF() {
<Grid item>
<Grid container>
<Grid item sx={{ml:3, mr:1.5, mb:2}}>
<Button
{/* <Button
variant="contained"
type="submit"
color="save"
disabled={!viewerLoaded}
onClick={handleSavePdf}
// disabled={!viewerLoaded}
onClick={handleTest}
// onClick={handleSavePdf}
>
Save
</Button>
</Button> */}
</Grid>
<Grid item sx={{ml:{xs:1.5, md:1.5, lg:1.5}, mr:1.5, mb:2}}>
<Button
@@ -252,7 +288,7 @@ function PDF() {
color="cancel"
onClick={viewerLoaded ? handleBackClick : handleBack}
>
Cancel
Back
</Button>
<GeneralConfirmWindow
isWindowOpen={isWindowOpen}
@@ -263,6 +299,18 @@ function PDF() {
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 ? (
@@ -278,18 +326,25 @@ function PDF() {
<p>Loading PDF viewer...</p>
)} */}
</header>
<div
{!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'
border: '1px solid #ccc',
}}
>
{/* The PDF SDK will render the PDF viewer here */}
</div>
</div> */}
</div>
</ThemeProvider>
);


+ 106
- 34
src/pages/pdf/PdfSearchPage/PdfSearchForm.js Прегледај датотеку

@@ -41,6 +41,12 @@ import {ExpandMore} from "@mui/icons-material";
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { isNull } from 'lodash';

import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogActions from '@mui/material/DialogActions';
import Dialog from '@mui/material/Dialog';

// ==============================|| DASHBOARD - DEFAULT ||============================== //

// const EventSearchForm = ({applySearch, refTemplateData, isUpdating,
@@ -50,6 +56,8 @@ const PdfSearchForm = ({applySearch, setExpanded,expanded, clientId}) => {
const navigate = useNavigate()
const ability = useContext(AbilityContext);

const [isWindowOpen, setIsWindowOpen] = useState(false);

const [createDateFrom, setCreateDateFrom] = useState(null);
const [createDateTo, setCreateDateTo] = useState(null);

@@ -77,25 +85,25 @@ const PdfSearchForm = ({applySearch, setExpanded,expanded, clientId}) => {
}
}, [createDateToError]);

const createNewForm = () => {
navigate(`/pdf/maintain/-${clientId}T${1}`);
const createNewForm = (templateId) => {
navigate(`/pdf/maintain/-${clientId}T${templateId}`);
};

const createFormUpDown = () => {
navigate(`/pdf/form-up-down/-${clientId}T${1}`);
};
// const createFormUpDown = () => {
// navigate(`/pdf/form-up-down/-${clientId}T${1}`);
// };

const createFormIDA = () => {
navigate(`/pdf/newIDA/${clientId}`);
};
// const createFormIDA = () => {
// navigate(`/pdf/newIDA/${clientId}`);
// };

const createFormFNA = () => {
navigate(`/pdf/newFNA/${clientId}`);
};
// const createFormFNA = () => {
// navigate(`/pdf/newFNA/${clientId}`);
// };

const createFormHSBCFIN = () => {
navigate(`/pdf/newHSBCFIN/${clientId}`);
};
// const createFormHSBCFIN = () => {
// navigate(`/pdf/newHSBCFIN/${clientId}`);
// };

const onSubmit = (data) => {
const criteria = {
@@ -299,26 +307,90 @@ const PdfSearchForm = ({applySearch, setExpanded,expanded, clientId}) => {
</Grid>
</Grid>

<Grid container spacing={1}>
{/* <Grid item>
<Button
variant="contained"
color="create"
onClick={createNewForm}
>
New
</Button>
<Grid item>
<Grid container>
{ability.can('EDIT','EVENT') ?
<Grid item sx={{ml:3, mr:3, mb:0.5}}>
<Button
variant="contained"
color="create"
onClick={() => setIsWindowOpen(true)}
>
New Form
</Button>
<Dialog
open={isWindowOpen}
onClose={() => setIsWindowOpen(false)}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
PaperProps={{
sx: {
maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '30vw' },
maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '50vh' }
}
}}
>
<DialogTitle id="alert-dialog-title">
<Typography variant="lionerBold" component="span">
Select Template
</Typography>
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
<Button
variant="contained"
color="create"
sx={{mr: 1}}
onClick={() => createNewForm(1)}
>
Lioner IDA
</Button>
<Button
variant="contained"
color="create"
sx={{mr: 1}}
onClick={() => createNewForm(2)}
>
Lioner FNA
</Button>
<Button
variant="contained"
color="create"
sx={{mr: 1}}
onClick={() => createNewForm(3)}
>
HSBC FIN
</Button>
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => setIsWindowOpen(false)}>
<Typography variant="lionerSize" component="span">
Cancel
</Typography>
</Button>
</DialogActions>
</Dialog>




{/* <Button
variant="contained"
color="create"
onClick={createFormUpDown}
>
New Form By Upload/Download
</Button> */}
</Grid>
:
<Grid/>
}
</Grid>
<Grid item>
<Button
variant="contained"
color="create"
onClick={createFormUpDown}
>
New By Upload/Download
</Button>
</Grid> */}
<Grid item>

{/* <Grid item>
<Button
variant="contained"
color="create"
@@ -416,7 +488,7 @@ const PdfSearchForm = ({applySearch, setExpanded,expanded, clientId}) => {
>
New SL Saving
</Button>
</Grid>
</Grid> */}
</Grid>
</ThemeProvider>
</Grid>


+ 14
- 4
src/pages/pdf/PdfSearchPage/PdfTable.js Прегледај датотеку

@@ -85,9 +85,22 @@ export default function PdfTable({recordList}) {
headerName: 'Form Name',
flex: 2,
renderCell: (params) => {
const getFormLabel = (value) => {
switch (value) {
case 1:
return 'Lioner IDA';
case 2:
return 'Lioner FNA';
case 3:
return 'HSBC FIN';
default:
return 'Form';
}
};

return (
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', whiteSpace: 'normal', wordBreak: 'break-word'}}>
{params.value}
{getFormLabel(params.value)}
</div>
);
}
@@ -203,9 +216,6 @@ export default function PdfTable({recordList}) {

return (
<div>
<h2 style={{ marginBottom: '16px', color: '#333' }}>
Existing Forms
</h2>
<DataGrid
rows={rows}
columns={columns}


+ 37
- 1
src/pages/pdf/PdfSearchPage/index.js Прегледај датотеку

@@ -9,6 +9,7 @@ import {apiPath} from "../../../auth/utils";
import {
// GET_DIVISION_FROM_SUB_DIVISION,
GET_PDF_PATH,
GET_CLIENT_PATH,
// GET_SEARCH_TEMPLATE_COMBO_PATH,
// GET_SEARCH_TEMPLATE_PATH
} from "../../../utils/ApiPathConst";
@@ -33,6 +34,7 @@ import {useParams} from "react-router-dom";
const PdfSearchPage = () => {
const [onReady, setOnReady] = useState(false);
const [expanded, setExpanded] = React.useState(true);
const [clientInfo,setClientInfo] = useState([]);
const [record,setRecord] = useState([]);
const [searchCriteria, setSearchCriteria] = useState({});
const params = useParams();
@@ -62,6 +64,21 @@ const PdfSearchPage = () => {
}

useEffect(() => {
if (params.id) {
if (params.id > 0) {console.log("loggg");
axios.get(`${apiPath}${GET_CLIENT_PATH}/${params.id}`
)
.then((response) => {
if (response.status === 200) {
setClientInfo(response.data);
}
})
.catch(error => {
console.log(error);
return false;
});
}
}
setSearchCriteria({clientId: params.id,
...searchCriteria});
}, [params.id]);
@@ -80,6 +97,15 @@ const PdfSearchPage = () => {
return (
<Grid container rowSpacing={3} columnSpacing={2.75} >
<ThemeProvider theme={LIONER_FORM_THEME}>
<Grid item xs={12} md={12} lg={12} >
<Grid container maxWidth justifyContent="space-between" sx={{mt:-2, width:CARD_MAX_WIDTH}} >
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ mb: 2, display: 'flex', alignItems: 'center'}}>
<Typography variant="h2">{clientInfo.data? clientInfo.data.fullname:""}</Typography>
</Grid>
</Grid>
</Grid>

<Grid item xs={12} md={12} lg={12} >
<Grid container maxWidth justifyContent="space-between" sx={{mt:-2, width:CARD_MAX_WIDTH}} >
<Grid item xs={4} s={4} md={4} lg={4}
@@ -104,12 +130,22 @@ const PdfSearchPage = () => {
/>
</Grid>

<Grid item xs={12} md={12} lg={12} >
<Grid container maxWidth justifyContent="space-between" sx={{mt:-2, width:CARD_MAX_WIDTH}} >
<Grid item xs={4} s={4} md={4} lg={4}
sx={{ mb: -2.25, display: 'flex', alignItems: 'center'}}>
<Typography variant="h4">Existing Forms</Typography>
</Grid>
</Grid>
</Grid>

{!onReady? <LoadingComponent/> :
// PDF Table
<Grid item xs={12} md={12} lg={12}>
<MainCard elevation={0}
content={false}
sx={{mt:{lg:-1.5}, width: CARD_MAX_WIDTH}}
sx={{//mt:{lg:-1.5},
width: CARD_MAX_WIDTH}}

>
<div style={{/*height: expanded? '46vh' : '75vh',*/ width: '100%'}}>


+ 12
- 1
src/routes/ClientRoutes.js Прегледај датотеку

@@ -15,6 +15,7 @@ const PdfMaintainPage = Loadable(lazy(() => import('pages/pdf/PdfMaintainPage'))
const PdfFormUpAndDown = Loadable(lazy(() => import('pages/pdf/PdfFormUpAndDown')));
const PdfViewer = Loadable(lazy(() => import('pages/pdf/PdfViewer')));
const PdfSearchPage = Loadable(lazy(() => import('pages/pdf/PdfSearchPage')));
const TemplateSearchPage = Loadable(lazy(() => import('pages/pdf/TemplateSearchPage')));

// ==============================|| AUTH ROUTING ||============================== //

@@ -64,7 +65,17 @@ const ClientRoutes =() => {
<Navigate to="/" />
)
),
},
},
{
path: '/template/',
element: (
handleRouteAbility(
ability.can('VIEW', 'DASHBOARD'),
<TemplateSearchPage />,
<Navigate to="/" />
)
),
},
{
path: '/pdf/form-up-down/:id',
element: (


+ 3
- 1
src/routes/MainRoutes.js Прегледај датотеку

@@ -6,6 +6,7 @@ import MainLayout from 'layout/MainLayout';
import AbilityContext from "../components/AbilityProvider";
import {handleRouteAbility} from "../utils/CommonFunction";
import {Navigate} from "react-router";
import ClientSearchPage from 'pages/client/ClientSearchPage/index';

// render - dashboard
//const DashboardDefault = Loadable(lazy(() => import('pages/dashboard')));
@@ -47,7 +48,8 @@ const MainRoutes = () => {
element: (
handleRouteAbility(
ability.can('VIEW', 'DASHBOARD'),
<LIONERDashboard />,
<ClientSearchPage />,
// <LIONERDashboard />,
<Navigate to="/client" />
)
),


+ 65
- 1
src/utils/CommonFunction.js Прегледај датотеку

@@ -878,6 +878,20 @@ export function UploadFileWindow({ isWindowOpen, title, video, onNormalClose, on
});
}
}

const handleDragOver = (e) => {
e.preventDefault();
e.stopPropagation();
};

const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
const droppedFiles = Array.from(e.dataTransfer.files);
console.log(droppedFiles);
// setFiles((prevFiles) => [...prevFiles, ...droppedFiles]);
};

return (
<Dialog
PaperProps={{
@@ -972,7 +986,57 @@ export function UploadFileWindow({ isWindowOpen, title, video, onNormalClose, on
</Grid>
</Grid>
) : (
<Grid />
<Grid container alignItems={'center'} sx={{ mt: 3 }}>
<Grid item xs={7} s={7} md={7} lg={7}>
<FormControl fullWidth required>
<Grid container alignItems={'flex-start'} sx={{ mt: 3 }}>
<Grid item xs={7} s={7} md={7} lg={8} sx={{display: 'flex', alignItems: 'flex-start' }}>

<MuiFileInput
inputProps={{
accept: '.png, .jpeg, .jpg',
}}
InputProps={{
padding: '7.5px 8px 7.5px 12px',
startAdornment: null, // Set startAdornment to null to disable it
}}
value={file}
onChange={handleFieldChange}
error={!!errors.error}
helperText={errors.error}
// disabled={video.mimetype !== 'video'}
/>
</Grid>
<Grid item xs={4} s={4} md={4} lg={4} sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<div
onDragOver={handleDragOver}
onDrop={handleDrop}>
<input
type="file"
accept=".png, .jpeg, .jpg"
style={{ display: 'none' }}
ref={fileInputRef}
onChange={handleChange}
/>
<Button
component="label"
variant="contained"
startIcon={<CloudUploadIcon />}
inputprops={{
accept: '.png, .jpeg, .jpg',
startAdornment: <AttachFileIcon />
}}
onClick={handleOpenFileSelect}
>
Upload file
</Button>
{/*Selected file: {file ? file.name : 'None'}*/}
</div>
</Grid>
</Grid>
</FormControl>
</Grid>
</Grid>
)}

<Grid container alignItems={'flex-start'} sx={{ mt: 3 }}>


Loading…
Откажи
Сачувај