diff --git a/src/menu-items/setting.js b/src/menu-items/setting.js
index 9d6bbff..ab652ce 100644
--- a/src/menu-items/setting.js
+++ b/src/menu-items/setting.js
@@ -13,7 +13,8 @@ import {
MenuUnfoldOutlined,
FileSearchOutlined,
MailOutlined,
- ApartmentOutlined
+ ApartmentOutlined,
+ FilePdfOutlined
} from '@ant-design/icons';
// icons
@@ -31,7 +32,8 @@ const icons = {
MenuUnfoldOutlined,
FileSearchOutlined,
MailOutlined,
- ApartmentOutlined
+ ApartmentOutlined,
+ FilePdfOutlined
};
// ==============================|| MENU ITEMS - EXTRA PAGES ||============================== //
@@ -141,6 +143,15 @@ const setting = {
breadcrumbs: false,
ability:['VIEW','USER']
},
+ {
+ id: 'formSigPage',
+ title: 'Form Sig Page',
+ type: 'item',
+ url: '/formSigPage',
+ icon: icons.FilePdfOutlined,
+ breadcrumbs: false,
+ ability:['MANAGE','SYSTEM_CONFIGURATION']
+ },
// {
// id: 'passwordPolicy',
// title: 'Password Policy',
diff --git a/src/pages/formSigPage/FormSigPageSearchForm.js b/src/pages/formSigPage/FormSigPageSearchForm.js
new file mode 100644
index 0000000..39a3f70
--- /dev/null
+++ b/src/pages/formSigPage/FormSigPageSearchForm.js
@@ -0,0 +1,84 @@
+import {
+ Button,
+ Grid,
+ InputLabel,
+ MenuItem,
+ TextField,
+} from '@mui/material';
+import MainCard from "../../components/MainCard";
+import { useForm } from "react-hook-form";
+import * as React from "react";
+import { ThemeProvider } from "@emotion/react";
+import { LIONER_BUTTON_THEME } from "../../themes/colorConst";
+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 SIG_TYPES = ['upload1', 'upload2'];
+
+const FormSigPageSearchForm = ({ applySearch }) => {
+ const { reset, register, handleSubmit } = useForm();
+
+ const onSubmit = (data) => {
+ applySearch(data);
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default FormSigPageSearchForm;
diff --git a/src/pages/formSigPage/FormSigPageTable.js b/src/pages/formSigPage/FormSigPageTable.js
new file mode 100644
index 0000000..bd72905
--- /dev/null
+++ b/src/pages/formSigPage/FormSigPageTable.js
@@ -0,0 +1,325 @@
+import * as React from 'react';
+import {
+ Button,
+} from '@mui/material';
+import {
+ DataGrid,
+ GridActionsCellItem,
+ GridRowEditStopReasons,
+ GridRowModes,
+ GridToolbarContainer
+} from "@mui/x-data-grid";
+import { DatePicker } from '@mui/x-date-pickers/DatePicker';
+import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
+import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import dayjs from 'dayjs';
+import EditIcon from '@mui/icons-material/Edit';
+import DeleteIcon from '@mui/icons-material/DeleteOutlined';
+import SaveIcon from '@mui/icons-material/Save';
+import CancelIcon from '@mui/icons-material/Close';
+import AddIcon from '@mui/icons-material/Add';
+import axios from "axios";
+import { apiPath } from "../../auth/utils";
+import {
+ GET_FORM_SIG_PAGE_LIST,
+ UPDATE_FORM_SIG_PAGE_PATH,
+} from "../../utils/ApiPathConst";
+import {
+ CustomNoRowsOverlay,
+ GeneralConfirmWindow,
+ notifyDeleteError,
+ notifyDeleteSuccess,
+ notifySaveSuccess,
+ removeObjectWithId
+} from "../../utils/CommonFunction";
+import UploadContext from "../../components/UploadProvider";
+import { LIONER_BUTTON_THEME } from "../../themes/colorConst";
+import { ThemeProvider } from "@emotion/react";
+
+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'];
+
+let newRowId = -1;
+
+function normalizeStartDate(value) {
+ if (value == null || value === '') return '';
+ if (dayjs.isDayjs(value)) return value.format('YYYY-MM-DD');
+ const d = dayjs(value);
+ return d.isValid() ? d.format('YYYY-MM-DD') : String(value);
+}
+
+function toDayjsOrNull(value) {
+ if (value == null || value === '') return null;
+ if (dayjs.isDayjs(value)) return value;
+ if (typeof value === 'string') {
+ const d = dayjs(value);
+ return d.isValid() ? d : null;
+ }
+ if (Array.isArray(value) && value.length >= 3) {
+ const y = value[0];
+ const m = String(value[1]).padStart(2, '0');
+ const d = dayjs(`${y}-${m}-${String(value[2]).padStart(2, '0')}`);
+ return d.isValid() ? d : null;
+ }
+ if (typeof value === 'object' && value.year != null && value.month != null && value.day != null) {
+ const d = dayjs(`${value.year}-${String(value.month).padStart(2, '0')}-${String(value.day).padStart(2, '0')}`);
+ return d.isValid() ? d : null;
+ }
+ const d = dayjs(value);
+ return d.isValid() ? d : null;
+}
+
+function formatStartDate(value) {
+ const d = toDayjsOrNull(value);
+ return d ? d.format('YYYY-MM-DD') : '';
+}
+
+function EditToolbar({ setRows, setRowModesModel }) {
+ const handleClick = () => {
+ const id = newRowId--;
+ setRows((oldRows) => [
+ {
+ id,
+ formCode: 'IDA',
+ startDate: '2000-01-01',
+ sigType: 'upload1',
+ pageFrom: 1,
+ pageTo: 1,
+ action: 'REPLACE',
+ isNew: true,
+ },
+ ...oldRows,
+ ]);
+ setRowModesModel((oldModel) => ({
+ ...oldModel,
+ [id]: { mode: GridRowModes.Edit, fieldToFocus: 'formCode' },
+ }));
+ };
+
+ return (
+
+ } onClick={handleClick}>
+ Add Form Sig Page
+
+
+ );
+}
+
+export default function FormSigPageTable({ recordList }) {
+ const [rows, setRows] = React.useState([]);
+ const [rowModesModel, setRowModesModel] = React.useState({});
+ const { setIsUploading } = React.useContext(UploadContext);
+ const [isWindowOpen, setIsWindowOpen] = React.useState(false);
+ const [selectedId, setSelectedId] = React.useState(null);
+ const [paginationModel, setPaginationModel] = React.useState({ page: 0, pageSize: 10 });
+
+ React.useEffect(() => {
+ setPaginationModel({ page: 0, pageSize: 10 });
+ setRows(recordList || []);
+ }, [recordList]);
+
+ const handleClose = () => setIsWindowOpen(false);
+
+ const handleDeleteClick = (id) => () => {
+ setIsWindowOpen(true);
+ setSelectedId(id);
+ };
+
+ const updateData = () => {
+ setIsUploading(true);
+ axios
+ .delete(`${apiPath}${GET_FORM_SIG_PAGE_LIST}/${selectedId}`)
+ .then((response) => {
+ if (response.status === 204) {
+ notifyDeleteSuccess();
+ setRows((prev) => removeObjectWithId(prev, selectedId));
+ setIsWindowOpen(false);
+ }
+ setIsUploading(false);
+ })
+ .catch((err) => {
+ console.error(err);
+ notifyDeleteError(err?.response?.data?.message || 'Delete failed');
+ setIsUploading(false);
+ });
+ };
+
+ const handleRowEditStop = (params, event) => {
+ if (params.reason === GridRowEditStopReasons.rowFocusOut) {
+ event.defaultMuiPrevented = true;
+ }
+ };
+
+ const handleEditClick = (id) => () => {
+ setRowModesModel((prev) => ({ ...prev, [id]: { mode: GridRowModes.Edit, fieldToFocus: 'formCode' } }));
+ };
+
+ const handleSaveClick = (id) => () => {
+ setRowModesModel((prev) => ({ ...prev, [id]: { mode: GridRowModes.View } }));
+ };
+
+ const handleCancelClick = (id) => () => {
+ setRowModesModel((prev => {
+ const next = { ...prev, [id]: { mode: GridRowModes.View, ignoreModifications: true } };
+ return next;
+ }));
+ const editedRow = rows.find((r) => r.id === id);
+ if (editedRow?.isNew) {
+ setRows((prev) => prev.filter((r) => r.id !== id));
+ }
+ };
+
+ const processRowUpdate = (newRow) => {
+ const isCreate = newRow.isNew === true || newRow.id == null || Number(newRow.id) <= 0;
+ const payload = {
+ formCode: newRow.formCode,
+ startDate: normalizeStartDate(newRow.startDate),
+ sigType: newRow.sigType,
+ pageFrom: Number(newRow.pageFrom),
+ pageTo: Number(newRow.pageTo),
+ action: newRow.action,
+ };
+ if (!isCreate) payload.id = Number(newRow.id);
+
+ return new Promise((resolve, reject) => {
+ if (!payload.formCode || !payload.startDate || !payload.sigType ||
+ payload.pageFrom == null || payload.pageTo == null || !payload.action) {
+ reject(new Error('All fields are required'));
+ return;
+ }
+ if (payload.pageFrom > payload.pageTo) {
+ reject(new Error('pageFrom must be <= pageTo'));
+ return;
+ }
+ setIsUploading(true);
+ axios
+ .post(`${apiPath}${UPDATE_FORM_SIG_PAGE_PATH}`, payload)
+ .then((res) => {
+ const savedId = res.data?.id;
+ const updatedRow = { ...newRow, id: savedId != null ? savedId : newRow.id, isNew: false };
+ setRows((prev) => prev.map((r) => (r.id === newRow.id ? updatedRow : r)));
+ notifySaveSuccess();
+ setIsUploading(false);
+ resolve(updatedRow);
+ })
+ .catch((err) => {
+ setIsUploading(false);
+ notifyDeleteError(err?.response?.data?.message || 'Save failed');
+ reject(err);
+ });
+ });
+ };
+
+ const columns = [
+ {
+ field: 'actions',
+ type: 'actions',
+ headerName: 'Actions',
+ width: 120,
+ getActions: ({ id }) => {
+ const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;
+ if (isInEditMode) {
+ return [
+
+ } label="Cancel" onClick={handleCancelClick(id)} color="delete" />,
+ ,
+
+ } label="Save" onClick={handleSaveClick(id)} color="save" />,
+ ,
+ ];
+ }
+ return [
+
+ } label="Delete" onClick={handleDeleteClick(id)} color="delete" />,
+ ,
+
+ } label="Edit" onClick={handleEditClick(id)} color="edit" />,
+ ,
+ ];
+ },
+ },
+ {
+ field: 'formCode',
+ headerName: 'Form Code',
+ width: 120,
+ editable: true,
+ type: 'singleSelect',
+ valueOptions: FORM_CODES,
+ },
+ {
+ field: 'startDate',
+ headerName: 'Start Date',
+ width: 140,
+ editable: true,
+ valueGetter: (params) => formatStartDate(params.row?.startDate),
+ renderCell: (params) => formatStartDate(params.row?.startDate),
+ renderEditCell: (params) => (
+
+
+ params.api.setEditCellValue({
+ id: params.id,
+ field: params.field,
+ value: d ? d.format('YYYY-MM-DD') : '',
+ })
+ }
+ slotProps={{ textField: { size: 'small', fullWidth: true } }}
+ />
+
+ ),
+ },
+ {
+ field: 'sigType',
+ headerName: 'Sig Type',
+ width: 90,
+ editable: true,
+ type: 'singleSelect',
+ valueOptions: SIG_TYPES,
+ },
+ { field: 'pageFrom', headerName: 'Page From', 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 (
+
+ notifyDeleteError(err?.message || 'Update failed')}
+ getRowHeight={() => 'auto'}
+ paginationModel={paginationModel}
+ onPaginationModelChange={setPaginationModel}
+ pageSizeOptions={[10, 25, 50]}
+ slots={{
+ toolbar: EditToolbar,
+ noRowsOverlay: () => CustomNoRowsOverlay(),
+ }}
+ slotProps={{ toolbar: { setRows, setRowModesModel } }}
+ autoHeight
+ />
+
+
+ );
+}
diff --git a/src/pages/formSigPage/index.js b/src/pages/formSigPage/index.js
new file mode 100644
index 0000000..bebce6d
--- /dev/null
+++ b/src/pages/formSigPage/index.js
@@ -0,0 +1,78 @@
+import {
+ Box,
+ Grid,
+ Typography
+} from '@mui/material';
+import MainCard from "../../components/MainCard";
+import FormSigPageSearchForm from "./FormSigPageSearchForm";
+import FormSigPageTable from "./FormSigPageTable";
+import { useEffect, useState } from "react";
+import * as React from "react";
+import axios from "axios";
+import { apiPath } from "../../auth/utils";
+import { GET_FORM_SIG_PAGE_LIST } from "../../utils/ApiPathConst";
+import LoadingComponent from "../extra-pages/LoadingComponent";
+import { LIONER_FORM_THEME, CARD_MAX_WIDTH } from "../../themes/themeConst";
+import { ThemeProvider } from "@emotion/react";
+
+const FormSigPageSearchPanel = () => {
+ const [record, setRecord] = useState([]);
+ const [searchCriteria, setSearchCriteria] = useState({});
+ const [onReady, setOnReady] = useState(false);
+
+ const fetchList = () => {
+ const params = {};
+ if (searchCriteria.formCode) params.formCode = searchCriteria.formCode;
+ if (searchCriteria.sigType) params.sigType = searchCriteria.sigType;
+ axios
+ .get(`${apiPath}${GET_FORM_SIG_PAGE_LIST}`, { params })
+ .then((response) => {
+ if (response.status === 200 && response.data?.records) {
+ setRecord(response.data.records);
+ }
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ };
+
+ useEffect(() => {
+ fetchList();
+ }, [searchCriteria]);
+
+ useEffect(() => {
+ setOnReady(true);
+ }, [record]);
+
+ const applySearch = (input) => {
+ setSearchCriteria(input || {});
+ };
+
+ if (!onReady) return ;
+
+ return (
+
+
+
+
+
+
+ Form Signature Page Config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default FormSigPageSearchPanel;
diff --git a/src/pages/pdf/PdfSearchPage/PdfTable.js b/src/pages/pdf/PdfSearchPage/PdfTable.js
index 6b93141..e61252d 100644
--- a/src/pages/pdf/PdfSearchPage/PdfTable.js
+++ b/src/pages/pdf/PdfSearchPage/PdfTable.js
@@ -1,7 +1,7 @@
// material-ui
import * as React from 'react';
import {apiPath} from "../../../auth/utils";
-import { POST_SIG_UPLOAD1 } from "../../../utils/ApiPathConst";
+import { POST_SIG_UPLOAD1, GET_FORM_SIG_PAGE_CONFIG } from "../../../utils/ApiPathConst";
import axios from 'axios';
import {
DataGrid,
@@ -50,6 +50,7 @@ export default function PdfTable({recordList}) {
const [isDialogOpen, setIsDialogOpen] = React.useState(false);
// State to hold the ID, templateName, and refType for the current upload operation
const [currentUploadRow, setCurrentUploadRow] = React.useState(initialUploadState);
+ const [currentUploadLabel, setCurrentUploadLabel] = React.useState(null);
const [isUploading, setIsUploading] = React.useState(false);
const navigate = useNavigate()
@@ -72,32 +73,63 @@ export default function PdfTable({recordList}) {
navigate(`/pdf/maintain/${id}`);
};
+ /** Safely get YYYY-MM-DD from row.created; returns null if missing or invalid. */
+ const getAsOfDateString = (row) => {
+ const raw = row?.created;
+ if (raw == null || raw === "") return null;
+ const d = new Date(raw);
+ if (Number.isNaN(d.getTime())) return null;
+ return d.toISOString().slice(0, 10);
+ };
+
/**
- * Opens the upload dialog and sets the current row details for Upload 1
+ * Opens the upload dialog and sets the current row details for Upload 1.
+ * Fetches form-sig-page config from API for dynamic label (page number).
*/
- const handleUploadClick = (id, templateName, formCode) => () => {
+ const handleUploadClick = (id, templateName, formCode, row) => () => {
setCurrentUploadRow({
id: id,
templateName: templateName,
formCode: formCode,
refType: "upload1"
});
+ setCurrentUploadLabel(null);
setIsDialogOpen(true);
+ const asOfDate = getAsOfDateString(row);
+ const params = new URLSearchParams({ formCode });
+ if (asOfDate) params.set("asOfDate", asOfDate);
+ axios.get(`${apiPath}${GET_FORM_SIG_PAGE_CONFIG}?${params}`)
+ .then((res) => {
+ const configs = res.data?.configs || [];
+ const upload1 = configs.find((c) => c.sigType === "upload1");
+ setCurrentUploadLabel(upload1?.label || "Upload Signature");
+ })
+ .catch(() => setCurrentUploadLabel("Upload Signature"));
};
/**
- * Opens the upload dialog and sets the current row details for Upload 2
+ * Opens the upload dialog and sets the current row details for Upload 2.
+ * Fetches form-sig-page config from API for dynamic label.
*/
- const handleUpload2Click = (id, templateName, formCode) => () => {
- // Placeholder for Upload 2
- console.log(`Uploading for row ID ${id} (Upload 2)`);
- setCurrentUploadRow({
+ const handleUpload2Click = (id, templateName, formCode, row) => () => {
+ setCurrentUploadRow({
id: id,
templateName: templateName,
formCode: formCode,
- refType: "upload2" // A different refType for a different upload logic/API
+ refType: "upload2"
});
- setIsDialogOpen(true);
+ setCurrentUploadLabel(null);
+ setIsDialogOpen(true);
+ const asOfDate = getAsOfDateString(row);
+ const params = new URLSearchParams({ formCode });
+ if (asOfDate) params.set("asOfDate", asOfDate);
+ axios.get(`${apiPath}${GET_FORM_SIG_PAGE_CONFIG}?${params}`)
+ .then((res) => {
+ const configs = res.data?.configs || [];
+ const upload2 = configs.find((c) => c.sigType === "upload2");
+ setCurrentUploadLabel(upload2?.label || "Upload 2");
+ })
+ .catch(() => setCurrentUploadLabel("Upload 2"));
};
/**
@@ -198,60 +230,18 @@ export default function PdfTable({recordList}) {
const handleCloseDialog = () => {
setIsDialogOpen(false);
- setCurrentUploadRow(initialUploadState); // Reset the current row
+ setCurrentUploadRow(initialUploadState);
+ setCurrentUploadLabel(null);
if (fileInputRef.current) {
fileInputRef.current.value = ""; // Clear the file input
}
};
- // Function to generate the dynamic dialog title
+ // Fallback dialog title when API config is not yet loaded or fails
const getUploadDialogTitle = (formCode, refType) => {
- console.log("formCode:" + formCode + " refType:" + refType);
- if (refType === 'upload1') {
- switch (formCode) {
- case "IDA":
- return "Upload Page 15";
- case "FNA":
- return "Upload Page 10";
- case "HSBCFIN":
- return "Upload Page 11";
- case "HSBCA31":
- return "Upload Page 28-29";
- case "MLB03S":
- return "Upload Page 9";
- case "MLFNA_EN":
- return "Upload Page 4";
- case "MLFNA_CHI":
- return "Upload Page 4";
- case "SLGII":
- return "Upload Page 13";
- case "SLAPP":
- return "Upload Page 17";
- case "SLFNA_EN":
- return "Upload Page 5";
- case "SLFNA_CHI":
- return "Upload Page 5";
- default:
- return "Unknown Form";
- }
- }else if (refType === 'upload2') {
- switch (formCode) {
- case "MLB03S":
- return "Upload Page 12-13";
- case "SLGII":
- return "Upload Page 15-16";
- case "SLAPP":
- return "Upload Page 19-20";
- default:
- return "Unknown Form";
- }
- }
- // Handle other refTypes if needed, e.g., 'upload2'
- if (refType === 'upload2') {
- return `Upload Template 2 for ${formCode}`;
- }
-
- return "Upload File"; // Fallback
+ if (refType === "upload1") return "Upload Signature";
+ if (refType === "upload2") return "Upload 2";
+ return "Upload File";
};
// Function to handle file selection and API submission
@@ -401,7 +391,7 @@ export default function PdfTable({recordList}) {
icon={upload1Icon} // Use the dynamic icon
label={upload1Label} // Use the dynamic label
className="textPrimary"
- onClick={handleUploadClick(id, templateName, formCode)}
+ onClick={handleUploadClick(id, templateName, formCode, row)}
color="upload"
/>
@@ -423,7 +413,7 @@ export default function PdfTable({recordList}) {
icon={upload2Icon}
label={upload2Label}
className="textPrimary"
- onClick={handleUpload2Click(id, templateName, formCode)}
+ onClick={handleUpload2Click(id, templateName, formCode, row)}
color="upload"
/>
@@ -551,8 +541,7 @@ export default function PdfTable({recordList}) {
TransitionProps={{ onExited: handleCloseDialog }}
>
- {/* Dynamic Title based on currentUploadRow state */}
- **{getUploadDialogTitle(currentUploadRow.formCode, currentUploadRow.refType)}**
+ {currentUploadLabel != null ? currentUploadLabel : getUploadDialogTitle(currentUploadRow.formCode, currentUploadRow.refType)}
diff --git a/src/routes/SettingRoutes.js b/src/routes/SettingRoutes.js
index 0314e19..56bf7b8 100644
--- a/src/routes/SettingRoutes.js
+++ b/src/routes/SettingRoutes.js
@@ -29,6 +29,7 @@ const EmailConfigPage = Loadable(lazy(() => import('pages/lionerEmailConfig')));
const GenerateReminderPage = Loadable(lazy(() => import('pages/lionerManualButtonPage')));
const ClientDepartmentPage = Loadable(lazy(() => import('pages/lionerClientDepartmentPage')));
const ProfilePage = Loadable(lazy(() => import('pages/profile/profile')));
+const FormSigPageSearchPanel = Loadable(lazy(() => import('pages/formSigPage')));
// ==============================|| AUTH ROUTING ||============================== //
@@ -260,6 +261,16 @@ const SettingRoutes = () => {
)
),
},
+ {
+ path: 'formSigPage',
+ element: (
+ handleRouteAbility(
+ ability.can('MANAGE', 'SYSTEM_CONFIGURATION'),
+ ,
+
+ )
+ ),
+ },
{
path: 'logout',
element:
diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js
index 889aaba..c2a49e3 100644
--- a/src/utils/ApiPathConst.js
+++ b/src/utils/ApiPathConst.js
@@ -72,6 +72,9 @@ export const GET_PDF_TEMPLATE_PATH = "/pdf/template"
export const GET_MERGE_PDF = "/pdf/merge-pdf"
export const GET_REMOVE_PDF_PASSWORD = "/pdf/remove-pdf-password"
export const POST_SIG_UPLOAD1 = "/pdf/upload1"
+export const GET_FORM_SIG_PAGE_CONFIG = "/pdf/form-sig-page-config"
+export const GET_FORM_SIG_PAGE_LIST = "/pdf/form-sig-page"
+export const UPDATE_FORM_SIG_PAGE_PATH = "/pdf/form-sig-page/save"
export const GET_CLIENT_PATH = "/client"
export const POST_CLIENT_PATH = "/client/save"
export const GET_EVENT_PATH = "/event"