From ed56964c3f775366c858aebe4298029fdad6d31d Mon Sep 17 00:00:00 2001 From: Jason Chuang Date: Sat, 8 Aug 2026 23:24:23 +0800 Subject: [PATCH] CR023 - update holiday import --- src/pages/Holiday/SearchForm.js | 70 +++++++++++++++++++++++++++----- src/pages/Holiday/index.js | 71 +++++++++++++++++++++++++++++---- src/utils/ApiPathConst.js | 1 + 3 files changed, 123 insertions(+), 19 deletions(-) diff --git a/src/pages/Holiday/SearchForm.js b/src/pages/Holiday/SearchForm.js index 6f7fa91..0264b2d 100644 --- a/src/pages/Holiday/SearchForm.js +++ b/src/pages/Holiday/SearchForm.js @@ -12,14 +12,17 @@ import * as React from "react"; // import * as DateUtils from "utils/DateUtils"; import {PNSPS_BUTTON_THEME} from "themes/buttonConst"; import {ThemeProvider} from "@emotion/react"; +import { GeneralConfirmWindow } from "utils/CommonFunction"; +import { isGrantedAny } from "auth/utils"; // import * as ComboData from "utils/ComboData"; // ==============================|| DASHBOARD - DEFAULT ||============================== // -const SearchHolidayForm = ({ applySearch, comboData, onGridReady}) => { +const SearchHolidayForm = ({ applySearch, comboData, searchCriteria, onGridReady, onDeleteYear, waitDelete }) => { const [selectedYear, setSelectedYear] = React.useState(null); // const [defaultYear, setDefaultYear] = React.useState(searchCriteria.year); const [comboList, setComboList] = React.useState([]); + const [isConfirmOpen, setIsConfirmOpen] = React.useState(false); // const [onReady, setOnReady] = React.useState(false); const { @@ -36,17 +39,28 @@ const SearchHolidayForm = ({ applySearch, comboData, onGridReady}) => { }; React.useEffect(() => { - if (comboData && comboData.length > 0) { - // console.log(comboData) - // const labelValue = comboData.find(obj => obj.label === searchCriteria.year); - // console.log(labelValue) - if (!selectedYear) { - setSelectedYear(comboData[0]); - } - setComboList(comboData) - // setSelectedYear(searchCriteria.dateFrom) + const nextCombo = Array.isArray(comboData) ? [...comboData] : []; + setComboList(nextCombo); + + if (nextCombo.length === 0) { + setSelectedYear(null); + return; + } + + const criteriaYear = searchCriteria?.year; + const matchedByCriteria = criteriaYear != null + ? nextCombo.find((obj) => String(obj.label) === String(criteriaYear)) + : null; + if (matchedByCriteria) { + setSelectedYear(matchedByCriteria); + return; } - }, [comboData]); + + const matchedBySelected = selectedYear + ? nextCombo.find((obj) => String(obj.label) === String(selectedYear.label)) + : null; + setSelectedYear(matchedBySelected || nextCombo[0]); + }, [comboData, searchCriteria]); return ( @@ -79,6 +93,9 @@ const SearchHolidayForm = ({ applySearch, comboData, onGridReady}) => { ? String(option.label) : "" } + isOptionEqualToValue={(option, value) => + String(option?.label) === String(value?.label) + } onChange={(event, newValue) => { setSelectedYear(newValue); }} @@ -91,6 +108,22 @@ const SearchHolidayForm = ({ applySearch, comboData, onGridReady}) => { /> + {isGrantedAny(["MAINTAIN_GAZETTE_ISSUE"]) ? + + + + + + : null + } + {/* { + + setIsConfirmOpen(false)} + onConfirmClose={() => { + setIsConfirmOpen(false); + if (selectedYear != null && onDeleteYear) { + onDeleteYear(selectedYear.label); + } + }} + /> ); }; diff --git a/src/pages/Holiday/index.js b/src/pages/Holiday/index.js index 164d244..2ae0a16 100644 --- a/src/pages/Holiday/index.js +++ b/src/pages/Holiday/index.js @@ -8,6 +8,7 @@ import { import * as UrlUtils from "utils/ApiPathConst"; import * as React from "react"; import * as HttpUtils from "utils/HttpUtils"; +import axios from "axios"; import Loadable from 'components/Loadable'; const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); @@ -29,7 +30,7 @@ const BackgroundHead = { import { PNSPS_LONG_BUTTON_THEME } from "themes/buttonConst"; import { ThemeProvider } from "@emotion/react"; import { dateStr_Year } from "utils/DateUtils"; -import { notifySaveSuccess } from 'utils/CommonFunction'; +import { notifyDeleteSuccess, notifySaveSuccess } from 'utils/CommonFunction'; import { isGrantedAny } from "auth/utils"; import { useIntl } from 'react-intl'; @@ -49,6 +50,7 @@ const Index = () => { const [attachments, setAttachments] = React.useState([]); const [waitImport, setWaitImport] = React.useState(false); const [waitDownload, setWaitDownload] = React.useState(false); + const [waitDelete, setWaitDelete] = React.useState(false); const [isWarningPopUp, setIsWarningPopUp] = React.useState(false); const [warningText, setWarningText] = React.useState(""); const fileInputRef = React.useRef(null); @@ -58,13 +60,17 @@ const Index = () => { loadForm(); }, [searchCriteria]); - function loadForm() { + function loadForm(refreshCombo = false, criteria = null) { + const params = criteria || searchCriteria; HttpUtils.get({ url: UrlUtils.GET_HOLIDAY, - params: searchCriteria, + params, onSuccess: (responseData) => { setRecord(responseData); - if (comboData.length === 0) { + if (criteria) { + setSearchCriteria(criteria); + } + if (refreshCombo || comboData.length === 0) { loadCombo(); } else { setOnSearchReady(true); @@ -77,8 +83,7 @@ const Index = () => { HttpUtils.get({ url: UrlUtils.GET_HOLIDAY_COMBO, onSuccess: (responseData) => { - let combo = responseData; - setComboData(combo); + setComboData(Array.isArray(responseData) ? [...responseData] : []); setOnReady(true); setOnSearchReady(true); } @@ -94,6 +99,43 @@ const Index = () => { setGridOnReady(input); } + function deleteYear(year) { + if (year == null || year === "") { + setWarningText("Please select a year."); + setIsWarningPopUp(true); + return; + } + setWaitDelete(true); + setOnSearchReady(false); + axios.delete(`${UrlUtils.DELETE_HOLIDAY_YEAR}/${year}`) + .then(() => { + notifyDeleteSuccess(); + HttpUtils.get({ + url: UrlUtils.GET_HOLIDAY_COMBO, + onSuccess: (responseData) => { + const combo = Array.isArray(responseData) ? [...responseData] : []; + setComboData(combo); + setWaitDelete(false); + const nextYear = combo.length > 0 ? combo[0].label : year; + applySearch({ year: nextYear }); + }, + onError: () => { + setComboData([]); + setWaitDelete(false); + applySearch({ year }); + } + }); + }) + .catch((error) => { + const msg = error?.response?.data?.error + || "Delete failed. Please try again."; + setWarningText(msg); + setIsWarningPopUp(true); + setWaitDelete(false); + setOnSearchReady(true); + }); + } + React.useEffect(() => { if (attachments.length > 0) { importHoliday(); @@ -132,7 +174,9 @@ const Index = () => { setOnSearchReady(false); if (!attachments || attachments.length <= 0) { setWarningText("Please upload file."); + setIsWarningPopUp(true); setWaitImport(false); + setOnSearchReady(true); return; } HttpUtils.postWithFiles({ @@ -142,7 +186,16 @@ const Index = () => { notifySaveSuccess(); setWaitImport(false); setAttachments([]); - loadForm(); + loadForm(true); + }, + onError: (error) => { + const msg = error?.response?.data?.error + || "Import failed. Please try again."; + setWarningText(msg); + setIsWarningPopUp(true); + setWaitImport(false); + setAttachments([]); + setOnSearchReady(true); } }); }; @@ -226,6 +279,8 @@ const Index = () => { searchCriteria={searchCriteria} comboData={comboData} onGridReady={onGridReady} + onDeleteYear={deleteYear} + waitDelete={waitDelete} /> @@ -255,7 +310,7 @@ const Index = () => { > Warning - {warningText} + {warningText} diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index 161dff9..3381dff 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -254,6 +254,7 @@ export const GET_HOLIDAY = apiPath+'/holiday/list'; //GET export const POST_HOLIDAY = apiPath+'/holiday/import'; //POST export const GET_HOLIDAY_COMBO = apiPath+'/holiday/combo'; //GET export const GET_HOLIDAY_TEMPLATE = apiPath+'/holiday/export'; //GET +export const DELETE_HOLIDAY_YEAR = apiPath+'/holiday/year'; //DELETE /{year} export const GET_JVM_INFO = apiPath+'/jvm-info'; //GET