| @@ -1,6 +1,7 @@ | |||||
| // assets | // assets | ||||
| import BoyIcon from '@mui/icons-material/Boy'; | import BoyIcon from '@mui/icons-material/Boy'; | ||||
| import AssignmentIcon from '@mui/icons-material/Assignment'; | import AssignmentIcon from '@mui/icons-material/Assignment'; | ||||
| import PictureAsPdfOutlinedIcon from '@mui/icons-material/PictureAsPdfOutlined'; | |||||
| // icons | // icons | ||||
| @@ -12,6 +13,7 @@ const icons = { | |||||
| ) | ) | ||||
| }, | }, | ||||
| AssignmentIcon, | AssignmentIcon, | ||||
| FormSigPageIcon: PictureAsPdfOutlinedIcon, | |||||
| }; | }; | ||||
| // ==============================|| MENU ITEMS - DASHBOARD ||============================== // | // ==============================|| MENU ITEMS - DASHBOARD ||============================== // | ||||
| @@ -40,6 +42,15 @@ const client = { | |||||
| breadcrumbs: false, | breadcrumbs: false, | ||||
| ability:['VIEW','TEMPLATE'] | ability:['VIEW','TEMPLATE'] | ||||
| }, | }, | ||||
| { | |||||
| id: 'formSigPage', | |||||
| title: 'Form Sig Page', | |||||
| type: 'item', | |||||
| url: '/formSigPage', | |||||
| icon: icons.FormSigPageIcon, | |||||
| breadcrumbs: false, | |||||
| ability:['VIEW','TEMPLATE'] | |||||
| }, | |||||
| ] | ] | ||||
| }; | }; | ||||
| @@ -13,8 +13,7 @@ import { | |||||
| MenuUnfoldOutlined, | MenuUnfoldOutlined, | ||||
| FileSearchOutlined, | FileSearchOutlined, | ||||
| MailOutlined, | MailOutlined, | ||||
| ApartmentOutlined, | |||||
| FilePdfOutlined | |||||
| ApartmentOutlined | |||||
| } from '@ant-design/icons'; | } from '@ant-design/icons'; | ||||
| // icons | // icons | ||||
| @@ -32,8 +31,7 @@ const icons = { | |||||
| MenuUnfoldOutlined, | MenuUnfoldOutlined, | ||||
| FileSearchOutlined, | FileSearchOutlined, | ||||
| MailOutlined, | MailOutlined, | ||||
| ApartmentOutlined, | |||||
| FilePdfOutlined | |||||
| ApartmentOutlined | |||||
| }; | }; | ||||
| // ==============================|| MENU ITEMS - EXTRA PAGES ||============================== // | // ==============================|| MENU ITEMS - EXTRA PAGES ||============================== // | ||||
| @@ -143,15 +141,6 @@ const setting = { | |||||
| breadcrumbs: false, | breadcrumbs: false, | ||||
| ability:['VIEW','USER'] | ability:['VIEW','USER'] | ||||
| }, | }, | ||||
| { | |||||
| id: 'formSigPage', | |||||
| title: 'Form Sig Page', | |||||
| type: 'item', | |||||
| url: '/formSigPage', | |||||
| icon: icons.FilePdfOutlined, | |||||
| breadcrumbs: false, | |||||
| ability:['MANAGE','SYSTEM_CONFIGURATION'] | |||||
| }, | |||||
| // { | // { | ||||
| // id: 'passwordPolicy', | // id: 'passwordPolicy', | ||||
| // title: 'Password Policy', | // title: 'Password Policy', | ||||
| @@ -13,7 +13,7 @@ import { LIONER_BUTTON_THEME } from "../../themes/colorConst"; | |||||
| import { CARD_MAX_WIDTH } from "../../themes/themeConst"; | import { CARD_MAX_WIDTH } from "../../themes/themeConst"; | ||||
| const FORM_CODES = ['IDA', 'FNA', 'HSBCFIN', 'HSBCA31', 'MLB03S', 'MLFNA_EN', 'MLFNA_CHI', 'SLFNA_EN', 'SLFNA_CHI', 'SLAPP', 'SLGII']; | const FORM_CODES = ['IDA', 'FNA', 'HSBCFIN', 'HSBCA31', 'MLB03S', 'MLFNA_EN', 'MLFNA_CHI', 'SLFNA_EN', 'SLFNA_CHI', 'SLAPP', 'SLGII']; | ||||
| const SIG_TYPES = ['upload1', 'upload2']; | |||||
| const SIG_TYPES = ['upload1', 'upload2', 'upload3']; | |||||
| const FormSigPageSearchForm = ({ applySearch }) => { | const FormSigPageSearchForm = ({ applySearch }) => { | ||||
| const { reset, register, handleSubmit } = useForm(); | const { reset, register, handleSubmit } = useForm(); | ||||
| @@ -37,8 +37,7 @@ import { LIONER_BUTTON_THEME } from "../../themes/colorConst"; | |||||
| import { ThemeProvider } from "@emotion/react"; | import { ThemeProvider } from "@emotion/react"; | ||||
| const FORM_CODES = ['IDA', 'FNA', 'HSBCFIN', 'HSBCA31', 'MLB03S', 'MLFNA_EN', 'MLFNA_CHI', 'SLFNA_EN', 'SLFNA_CHI', 'SLAPP', 'SLGII']; | const FORM_CODES = ['IDA', 'FNA', 'HSBCFIN', 'HSBCA31', 'MLB03S', 'MLFNA_EN', 'MLFNA_CHI', 'SLFNA_EN', 'SLFNA_CHI', 'SLAPP', 'SLGII']; | ||||
| const SIG_TYPES = ['upload1', 'upload2']; | |||||
| const ACTIONS = ['REPLACE', 'SKIP_AND_APPEND']; | |||||
| const SIG_TYPES = ['upload1', 'upload2', 'upload3']; | |||||
| let newRowId = -1; | let newRowId = -1; | ||||
| @@ -86,7 +85,6 @@ function EditToolbar({ setRows, setRowModesModel }) { | |||||
| sigType: 'upload1', | sigType: 'upload1', | ||||
| pageFrom: 1, | pageFrom: 1, | ||||
| pageTo: 1, | pageTo: 1, | ||||
| action: 'REPLACE', | |||||
| isNew: true, | isNew: true, | ||||
| }, | }, | ||||
| ...oldRows, | ...oldRows, | ||||
| @@ -178,13 +176,12 @@ export default function FormSigPageTable({ recordList }) { | |||||
| sigType: newRow.sigType, | sigType: newRow.sigType, | ||||
| pageFrom: Number(newRow.pageFrom), | pageFrom: Number(newRow.pageFrom), | ||||
| pageTo: Number(newRow.pageTo), | pageTo: Number(newRow.pageTo), | ||||
| action: newRow.action, | |||||
| }; | }; | ||||
| if (!isCreate) payload.id = Number(newRow.id); | if (!isCreate) payload.id = Number(newRow.id); | ||||
| return new Promise((resolve, reject) => { | return new Promise((resolve, reject) => { | ||||
| if (!payload.formCode || !payload.startDate || !payload.sigType || | if (!payload.formCode || !payload.startDate || !payload.sigType || | ||||
| payload.pageFrom == null || payload.pageTo == null || !payload.action) { | |||||
| payload.pageFrom == null || payload.pageTo == null) { | |||||
| reject(new Error('All fields are required')); | reject(new Error('All fields are required')); | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -280,14 +277,6 @@ export default function FormSigPageTable({ recordList }) { | |||||
| }, | }, | ||||
| { field: 'pageFrom', headerName: 'Page From', type: 'number', width: 95, editable: true }, | { field: 'pageFrom', headerName: 'Page From', type: 'number', width: 95, editable: true }, | ||||
| { field: 'pageTo', headerName: 'Page To', type: 'number', width: 95, editable: true }, | { field: 'pageTo', headerName: 'Page To', type: 'number', width: 95, editable: true }, | ||||
| { | |||||
| field: 'action', | |||||
| headerName: 'Action', | |||||
| width: 140, | |||||
| editable: true, | |||||
| type: 'singleSelect', | |||||
| valueOptions: ACTIONS, | |||||
| }, | |||||
| ]; | ]; | ||||
| return ( | return ( | ||||
| @@ -1,13 +1,14 @@ | |||||
| // material-ui | // material-ui | ||||
| import { | import { | ||||
| Button, | Button, | ||||
| Grid, | |||||
| Grid, | |||||
| TextField, | TextField, | ||||
| Typography, | Typography, | ||||
| Dialog, | Dialog, | ||||
| DialogTitle, | DialogTitle, | ||||
| DialogContent, | DialogContent, | ||||
| DialogActions | |||||
| DialogActions, | |||||
| InputLabel, | |||||
| } from '@mui/material'; | } from '@mui/material'; | ||||
| import MainCard from "../../components/MainCard"; | import MainCard from "../../components/MainCard"; | ||||
| import {useForm} from "react-hook-form"; | import {useForm} from "react-hook-form"; | ||||
| @@ -21,6 +22,7 @@ import {ThemeProvider} from "@emotion/react"; | |||||
| import {LIONER_BUTTON_THEME} from "../../themes/colorConst"; | import {LIONER_BUTTON_THEME} from "../../themes/colorConst"; | ||||
| import {USER_GROUP_COMBO} from "../../utils/ComboConst"; | import {USER_GROUP_COMBO} from "../../utils/ComboConst"; | ||||
| import {CARD_MAX_WIDTH} from "../../themes/themeConst"; | import {CARD_MAX_WIDTH} from "../../themes/themeConst"; | ||||
| import {GET_CONSULTANT_COMBO_LIST} from "../../utils/ApiPathConst"; | |||||
| // ==============================|| USER SEARCH FORM ||============================== // | // ==============================|| USER SEARCH FORM ||============================== // | ||||
| @@ -33,9 +35,22 @@ const UserSearchForm = ({applySearch}) => { | |||||
| // States for Report Dialog | // States for Report Dialog | ||||
| const [openReportDialog, setOpenReportDialog] = useState(false); | const [openReportDialog, setOpenReportDialog] = useState(false); | ||||
| const [reportDates, setReportDates] = useState({ fromDate: '', toDate: '' }); | const [reportDates, setReportDates] = useState({ fromDate: '', toDate: '' }); | ||||
| const [consultantOptions, setConsultantOptions] = useState([]); | |||||
| const [selectedConsultants, setSelectedConsultants] = useState([]); | |||||
| const { reset, register, handleSubmit } = useForm(); | const { reset, register, handleSubmit } = useForm(); | ||||
| useEffect(() => { | |||||
| axios | |||||
| .get(`${apiPath}${GET_CONSULTANT_COMBO_LIST}`) | |||||
| .then((res) => { | |||||
| if (res.data?.records) { | |||||
| setConsultantOptions(res.data.records); | |||||
| } | |||||
| }) | |||||
| .catch(() => {}); | |||||
| }, []); | |||||
| const onSubmit = (data) => { | const onSubmit = (data) => { | ||||
| const temp = { | const temp = { | ||||
| username: data.userName, | username: data.userName, | ||||
| @@ -53,11 +68,26 @@ const UserSearchForm = ({applySearch}) => { | |||||
| const handleCloseReport = () => { | const handleCloseReport = () => { | ||||
| setOpenReportDialog(false); | setOpenReportDialog(false); | ||||
| setReportDates({ fromDate: '', toDate: '' }); | setReportDates({ fromDate: '', toDate: '' }); | ||||
| setSelectedConsultants([]); | |||||
| }; | }; | ||||
| const handleExport = () => { | const handleExport = () => { | ||||
| const params = { | |||||
| fromDate: reportDates.fromDate, | |||||
| toDate: reportDates.toDate, | |||||
| }; | |||||
| if (selectedConsultants.length > 0) { | |||||
| params.consultantIds = selectedConsultants.map((c) => c.id); | |||||
| } | |||||
| axios.get(`${apiPath}/client/excel-client-consultant-report`, { | axios.get(`${apiPath}/client/excel-client-consultant-report`, { | ||||
| params: reportDates, | |||||
| params, | |||||
| paramsSerializer: (p) => { | |||||
| const search = new URLSearchParams(); | |||||
| if (p.fromDate) search.append('fromDate', p.fromDate); | |||||
| if (p.toDate) search.append('toDate', p.toDate); | |||||
| (p.consultantIds || []).forEach((id) => search.append('consultantIds', String(id))); | |||||
| return search.toString(); | |||||
| }, | |||||
| responseType: 'blob', | responseType: 'blob', | ||||
| }) | }) | ||||
| .then((response) => { | .then((response) => { | ||||
| @@ -153,7 +183,7 @@ const UserSearchForm = ({applySearch}) => { | |||||
| </form> | </form> | ||||
| {/* Report Criteria Dialog */} | {/* Report Criteria Dialog */} | ||||
| <Dialog open={openReportDialog} onClose={handleCloseReport} fullWidth maxWidth="xs"> | |||||
| <Dialog open={openReportDialog} onClose={handleCloseReport} fullWidth maxWidth="sm"> | |||||
| <DialogTitle>Export Client Consultant Report</DialogTitle> | <DialogTitle>Export Client Consultant Report</DialogTitle> | ||||
| <DialogContent> | <DialogContent> | ||||
| <Grid container spacing={2} sx={{ mt: 0.5 }}> | <Grid container spacing={2} sx={{ mt: 0.5 }}> | ||||
| @@ -177,6 +207,27 @@ const UserSearchForm = ({applySearch}) => { | |||||
| onChange={(e) => setReportDates({ ...reportDates, toDate: e.target.value })} | onChange={(e) => setReportDates({ ...reportDates, toDate: e.target.value })} | ||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| <Grid item xs={12}> | |||||
| <InputLabel htmlFor="report-consultant-combo">Consultant (optional)</InputLabel> | |||||
| <Autocomplete | |||||
| multiple | |||||
| disableCloseOnSelect | |||||
| id="report-consultant-combo" | |||||
| size="small" | |||||
| options={consultantOptions} | |||||
| value={selectedConsultants} | |||||
| onChange={(event, newValue) => setSelectedConsultants(newValue)} | |||||
| getOptionLabel={(option) => option?.name ?? ''} | |||||
| isOptionEqualToValue={(a, b) => a?.id === b?.id} | |||||
| renderInput={(params) => ( | |||||
| <TextField | |||||
| {...params} | |||||
| placeholder="All consultants if empty" | |||||
| fullWidth | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| </Grid> | |||||
| </Grid> | </Grid> | ||||
| </DialogContent> | </DialogContent> | ||||
| <DialogActions sx={{ p: 3 }}> | <DialogActions sx={{ p: 3 }}> | ||||
| @@ -39,7 +39,22 @@ import {ThemeProvider} from "@emotion/react"; | |||||
| const initialUploadState = { | const initialUploadState = { | ||||
| id: null, | id: null, | ||||
| templateName: null, // This will be the formCode | templateName: null, // This will be the formCode | ||||
| refType: null, // To differentiate between upload1 and upload2 if needed | |||||
| refType: null, // upload1 | upload2 | upload3 | |||||
| } | |||||
| const REF_TYPE_TO_FILE_FIELD = { | |||||
| upload1: "upload1FileId", | |||||
| upload2: "upload2FileId", | |||||
| upload3: "upload3FileId", | |||||
| }; | |||||
| /** Backend adds sigTypes from form_sig_page for this row's formCode + created date. */ | |||||
| function normalizeSigTypes(row) { | |||||
| const st = row?.sigTypes; | |||||
| if (Array.isArray(st) && st.length > 0) { | |||||
| return st; | |||||
| } | |||||
| return ["upload1"]; | |||||
| } | } | ||||
| export default function PdfTable({recordList}) { | export default function PdfTable({recordList}) { | ||||
| @@ -73,13 +88,19 @@ export default function PdfTable({recordList}) { | |||||
| navigate(`/pdf/maintain/${id}`); | navigate(`/pdf/maintain/${id}`); | ||||
| }; | }; | ||||
| /** Safely get YYYY-MM-DD from row.created; returns null if missing or invalid. */ | |||||
| /** | |||||
| * YYYY-MM-DD in local calendar (matches server JVM date for filled_form.created better than UTC ISO). | |||||
| * Used only as fallback when the API cannot resolve filledFormId. | |||||
| */ | |||||
| const getAsOfDateString = (row) => { | const getAsOfDateString = (row) => { | ||||
| const raw = row?.created; | const raw = row?.created; | ||||
| if (raw == null || raw === "") return null; | if (raw == null || raw === "") return null; | ||||
| const d = new Date(raw); | const d = new Date(raw); | ||||
| if (Number.isNaN(d.getTime())) return null; | if (Number.isNaN(d.getTime())) return null; | ||||
| return d.toISOString().slice(0, 10); | |||||
| const y = d.getFullYear(); | |||||
| const m = String(d.getMonth() + 1).padStart(2, "0"); | |||||
| const day = String(d.getDate()).padStart(2, "0"); | |||||
| return `${y}-${m}-${day}`; | |||||
| }; | }; | ||||
| /** | /** | ||||
| @@ -97,6 +118,7 @@ export default function PdfTable({recordList}) { | |||||
| setIsDialogOpen(true); | setIsDialogOpen(true); | ||||
| const asOfDate = getAsOfDateString(row); | const asOfDate = getAsOfDateString(row); | ||||
| const params = new URLSearchParams({ formCode }); | const params = new URLSearchParams({ formCode }); | ||||
| params.set("filledFormId", String(id)); | |||||
| if (asOfDate) params.set("asOfDate", asOfDate); | if (asOfDate) params.set("asOfDate", asOfDate); | ||||
| axios.get(`${apiPath}${GET_FORM_SIG_PAGE_CONFIG}?${params}`) | axios.get(`${apiPath}${GET_FORM_SIG_PAGE_CONFIG}?${params}`) | ||||
| .then((res) => { | .then((res) => { | ||||
| @@ -122,6 +144,7 @@ export default function PdfTable({recordList}) { | |||||
| setIsDialogOpen(true); | setIsDialogOpen(true); | ||||
| const asOfDate = getAsOfDateString(row); | const asOfDate = getAsOfDateString(row); | ||||
| const params = new URLSearchParams({ formCode }); | const params = new URLSearchParams({ formCode }); | ||||
| params.set("filledFormId", String(id)); | |||||
| if (asOfDate) params.set("asOfDate", asOfDate); | if (asOfDate) params.set("asOfDate", asOfDate); | ||||
| axios.get(`${apiPath}${GET_FORM_SIG_PAGE_CONFIG}?${params}`) | axios.get(`${apiPath}${GET_FORM_SIG_PAGE_CONFIG}?${params}`) | ||||
| .then((res) => { | .then((res) => { | ||||
| @@ -132,6 +155,28 @@ export default function PdfTable({recordList}) { | |||||
| .catch(() => setCurrentUploadLabel("Upload 2")); | .catch(() => setCurrentUploadLabel("Upload 2")); | ||||
| }; | }; | ||||
| const handleUpload3Click = (id, templateName, formCode, row) => () => { | |||||
| setCurrentUploadRow({ | |||||
| id: id, | |||||
| templateName: templateName, | |||||
| formCode: formCode, | |||||
| refType: "upload3" | |||||
| }); | |||||
| setCurrentUploadLabel(null); | |||||
| setIsDialogOpen(true); | |||||
| const asOfDate = getAsOfDateString(row); | |||||
| const params = new URLSearchParams({ formCode }); | |||||
| params.set("filledFormId", String(id)); | |||||
| if (asOfDate) params.set("asOfDate", asOfDate); | |||||
| axios.get(`${apiPath}${GET_FORM_SIG_PAGE_CONFIG}?${params}`) | |||||
| .then((res) => { | |||||
| const configs = res.data?.configs || []; | |||||
| const upload3 = configs.find((c) => c.sigType === "upload3"); | |||||
| setCurrentUploadLabel(upload3?.label || "Upload 3"); | |||||
| }) | |||||
| .catch(() => setCurrentUploadLabel("Upload 3")); | |||||
| }; | |||||
| /** | /** | ||||
| * Handles the standard download (fillable file, endpoint: /download-ff/{id}) | * Handles the standard download (fillable file, endpoint: /download-ff/{id}) | ||||
| */ | */ | ||||
| @@ -241,6 +286,7 @@ export default function PdfTable({recordList}) { | |||||
| const getUploadDialogTitle = (formCode, refType) => { | const getUploadDialogTitle = (formCode, refType) => { | ||||
| if (refType === "upload1") return "Upload Signature"; | if (refType === "upload1") return "Upload Signature"; | ||||
| if (refType === "upload2") return "Upload 2"; | if (refType === "upload2") return "Upload 2"; | ||||
| if (refType === "upload3") return "Upload 3"; | |||||
| return "Upload File"; | return "Upload File"; | ||||
| }; | }; | ||||
| @@ -289,7 +335,7 @@ export default function PdfTable({recordList}) { | |||||
| prevRows.map(row => { | prevRows.map(row => { | ||||
| if (row.id === id) { | if (row.id === id) { | ||||
| // Update the relevant file ID field based on refType | // Update the relevant file ID field based on refType | ||||
| const updateField = refType === 'upload1' ? 'upload1FileId' : 'upload2FileId'; | |||||
| const updateField = REF_TYPE_TO_FILE_FIELD[refType] || "upload1FileId"; | |||||
| return { | return { | ||||
| ...row, | ...row, | ||||
| [updateField]: uploadedFileId // Set the file ID to trigger the icon | [updateField]: uploadedFileId // Set the file ID to trigger the icon | ||||
| @@ -367,46 +413,47 @@ export default function PdfTable({recordList}) { | |||||
| Upload Sig. | Upload Sig. | ||||
| </div> | </div> | ||||
| ), | ), | ||||
| width: 100, | |||||
| width: 150, | |||||
| cellClassName: 'actions', | cellClassName: 'actions', | ||||
| getActions: ({ id, row }) => { | getActions: ({ id, row }) => { | ||||
| // Check upload status | // Check upload status | ||||
| const isUploaded1 = !!row.upload1FileId; | const isUploaded1 = !!row.upload1FileId; | ||||
| const isUploaded2 = !!row.upload2FileId; | |||||
| const isUploaded2 = !!row.upload2FileId; | |||||
| const isUploaded3 = !!row.upload3FileId; | |||||
| const templateName = row.templateName; | const templateName = row.templateName; | ||||
| const formCode = row.formCode; | const formCode = row.formCode; | ||||
| // FIX 5: Use conditional colors for Upload 1 | |||||
| const upload1Icon = isUploaded1 | |||||
| ? <CheckCircleIcon sx={{fontSize: 25, color: 'success.main'}} /> // Green tick if uploaded | |||||
| : <UploadFileIcon sx={{fontSize: 25, color: 'warning.main'}} />; // Warning color if not uploaded | |||||
| const sigTypes = normalizeSigTypes(row); | |||||
| const showUpload1 = sigTypes.includes("upload1"); | |||||
| const showUpload2 = sigTypes.includes("upload2"); | |||||
| const showUpload3 = sigTypes.includes("upload3"); | |||||
| const upload1Label = isUploaded1 ? "Update Signature" : "Upload Signature"; | |||||
| const actions = []; | |||||
| // Define the actions | |||||
| const actions = [ | |||||
| <ThemeProvider key="UploadSign1" theme={LIONER_BUTTON_THEME}> | |||||
| <GridActionsCellItem | |||||
| icon={upload1Icon} // Use the dynamic icon | |||||
| label={upload1Label} // Use the dynamic label | |||||
| className="textPrimary" | |||||
| onClick={handleUploadClick(id, templateName, formCode, row)} | |||||
| color="upload" | |||||
| /> | |||||
| </ThemeProvider> | |||||
| ]; | |||||
| if (showUpload1) { | |||||
| const upload1Icon = isUploaded1 | |||||
| ? <CheckCircleIcon sx={{fontSize: 25, color: 'success.main'}} /> | |||||
| : <UploadFileIcon sx={{fontSize: 25, color: 'warning.main'}} />; | |||||
| const upload1Label = isUploaded1 ? "Update Signature" : "Upload Signature"; | |||||
| actions.push( | |||||
| <ThemeProvider key="UploadSign1" theme={LIONER_BUTTON_THEME}> | |||||
| <GridActionsCellItem | |||||
| icon={upload1Icon} | |||||
| label={upload1Label} | |||||
| className="textPrimary" | |||||
| onClick={handleUploadClick(id, templateName, formCode, row)} | |||||
| color="upload" | |||||
| /> | |||||
| </ThemeProvider> | |||||
| ); | |||||
| } | |||||
| // Conditional rendering logic for Upload 2 | |||||
| if (row.formCode === "MLB03S" || row.formCode === "SLGII" || row.formCode === "SLAPP") { | |||||
| // FIX 5: Use conditional colors for Upload 2 | |||||
| if (showUpload2) { | |||||
| const upload2Icon = isUploaded2 | const upload2Icon = isUploaded2 | ||||
| ? <CheckCircleIcon sx={{fontSize: 25, color: 'success.main'}} /> // Green tick if uploaded | |||||
| : <UploadFileIcon sx={{fontSize: 25, color: 'warning.main'}} />; // Warning color if not uploaded | |||||
| ? <CheckCircleIcon sx={{fontSize: 25, color: 'success.main'}} /> | |||||
| : <UploadFileIcon sx={{fontSize: 25, color: 'warning.main'}} />; | |||||
| const upload2Label = isUploaded2 ? "Update 2" : "Upload 2"; | const upload2Label = isUploaded2 ? "Update 2" : "Upload 2"; | ||||
| actions.push( | actions.push( | ||||
| <ThemeProvider key="UploadSign2" theme={LIONER_BUTTON_THEME}> | <ThemeProvider key="UploadSign2" theme={LIONER_BUTTON_THEME}> | ||||
| <GridActionsCellItem | <GridActionsCellItem | ||||
| @@ -420,6 +467,24 @@ export default function PdfTable({recordList}) { | |||||
| ); | ); | ||||
| } | } | ||||
| if (showUpload3) { | |||||
| const upload3Icon = isUploaded3 | |||||
| ? <CheckCircleIcon sx={{fontSize: 25, color: 'success.main'}} /> | |||||
| : <UploadFileIcon sx={{fontSize: 25, color: 'warning.main'}} />; | |||||
| const upload3Label = isUploaded3 ? "Update 3" : "Upload 3"; | |||||
| actions.push( | |||||
| <ThemeProvider key="UploadSign3" theme={LIONER_BUTTON_THEME}> | |||||
| <GridActionsCellItem | |||||
| icon={upload3Icon} | |||||
| label={upload3Label} | |||||
| className="textPrimary" | |||||
| onClick={handleUpload3Click(id, templateName, formCode, row)} | |||||
| color="upload" | |||||
| /> | |||||
| </ThemeProvider> | |||||
| ); | |||||
| } | |||||
| return actions; | return actions; | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -16,6 +16,7 @@ const PdfFormUpAndDown = Loadable(lazy(() => import('pages/pdf/PdfFormUpAndDown' | |||||
| const PdfViewer = Loadable(lazy(() => import('pages/pdf/PdfViewer'))); | const PdfViewer = Loadable(lazy(() => import('pages/pdf/PdfViewer'))); | ||||
| const PdfSearchPage = Loadable(lazy(() => import('pages/pdf/PdfSearchPage'))); | const PdfSearchPage = Loadable(lazy(() => import('pages/pdf/PdfSearchPage'))); | ||||
| const TemplateSearchPage = Loadable(lazy(() => import('pages/pdf/TemplateSearchPage'))); | const TemplateSearchPage = Loadable(lazy(() => import('pages/pdf/TemplateSearchPage'))); | ||||
| const FormSigPageSearchPanel = Loadable(lazy(() => import('pages/formSigPage'))); | |||||
| // ==============================|| AUTH ROUTING ||============================== // | // ==============================|| AUTH ROUTING ||============================== // | ||||
| @@ -88,6 +89,18 @@ const ClientRoutes =() => { | |||||
| </Require2FA> | </Require2FA> | ||||
| ), | ), | ||||
| }, | }, | ||||
| { | |||||
| path: '/formSigPage', | |||||
| element: ( | |||||
| <Require2FA> | |||||
| {handleRouteAbility( | |||||
| ability.can('VIEW', 'TEMPLATE'), | |||||
| <FormSigPageSearchPanel />, | |||||
| <Navigate to="/" /> | |||||
| )} | |||||
| </Require2FA> | |||||
| ), | |||||
| }, | |||||
| { | { | ||||
| path: '/pdf/form-up-down/:id', | path: '/pdf/form-up-down/:id', | ||||
| element: ( | element: ( | ||||
| @@ -29,8 +29,6 @@ const EmailConfigPage = Loadable(lazy(() => import('pages/lionerEmailConfig'))); | |||||
| const GenerateReminderPage = Loadable(lazy(() => import('pages/lionerManualButtonPage'))); | const GenerateReminderPage = Loadable(lazy(() => import('pages/lionerManualButtonPage'))); | ||||
| const ClientDepartmentPage = Loadable(lazy(() => import('pages/lionerClientDepartmentPage'))); | const ClientDepartmentPage = Loadable(lazy(() => import('pages/lionerClientDepartmentPage'))); | ||||
| const ProfilePage = Loadable(lazy(() => import('pages/profile/profile'))); | const ProfilePage = Loadable(lazy(() => import('pages/profile/profile'))); | ||||
| const FormSigPageSearchPanel = Loadable(lazy(() => import('pages/formSigPage'))); | |||||
| // ==============================|| AUTH ROUTING ||============================== // | // ==============================|| AUTH ROUTING ||============================== // | ||||
| const SettingRoutes = () => { | const SettingRoutes = () => { | ||||
| @@ -261,16 +259,6 @@ const SettingRoutes = () => { | |||||
| ) | ) | ||||
| ), | ), | ||||
| }, | }, | ||||
| { | |||||
| path: 'formSigPage', | |||||
| element: ( | |||||
| handleRouteAbility( | |||||
| ability.can('MANAGE', 'SYSTEM_CONFIGURATION'), | |||||
| <FormSigPageSearchPanel />, | |||||
| <Navigate to="/" /> | |||||
| ) | |||||
| ), | |||||
| }, | |||||
| { | { | ||||
| path: 'logout', | path: 'logout', | ||||
| element: <LogoutPage /> | element: <LogoutPage /> | ||||