diff --git a/app/controllers/report.controller.js b/app/controllers/report.controller.js index a9c3f90..2cb644e 100644 --- a/app/controllers/report.controller.js +++ b/app/controllers/report.controller.js @@ -151,13 +151,19 @@ const buildRoutePdfBuffer = async (templateBytes, route, seqNum, driversMap, veh const pickupTime = formatUtcToLocalHm(customer?.customer_pickup_time); if (pickupTime) safeSetField(form, `pick_${row}`, pickupTime); - const enterCenterTime = formatUtcToLocalHm(customer?.customer_enter_center_time); - if (enterCenterTime) { - safeSetField(form, `arrive_${row}`, enterCenterTime); + const hasEnterCenterTime = customer?.customer_enter_center_time !== undefined && customer?.customer_enter_center_time !== null; + if (hasEnterCenterTime) { + const enterCenterTime = formatUtcToLocalHm(customer?.customer_enter_center_time); + if (enterCenterTime) { + safeSetField(form, `arrive_${row}`, enterCenterTime); + } safeSetField(form, `y_${row}`, "✓"); + safeSetField(form, `n_${row}`, ""); } else if (customer?.customer_route_status === "inCenter") { safeSetField(form, `y_${row}`, "✓"); + safeSetField(form, `n_${row}`, ""); } else { + safeSetField(form, `y_${row}`, ""); safeSetField(form, `n_${row}`, "✕"); } diff --git a/client/src/components/trans-routes/RoutesDashboard.js b/client/src/components/trans-routes/RoutesDashboard.js index 1a72564..3246d13 100644 --- a/client/src/components/trans-routes/RoutesDashboard.js +++ b/client/src/components/trans-routes/RoutesDashboard.js @@ -97,6 +97,8 @@ const RoutesDashboard = () => { const [isScheduleImporting, setIsScheduleImporting] = useState(false); const [scheduleImportProgress, setScheduleImportProgress] = useState(0); const [scheduleImportLabel, setScheduleImportLabel] = useState(''); + const [isExportingRouteReport, setIsExportingRouteReport] = useState(false); + const [exportRouteReportProgress, setExportRouteReportProgress] = useState(0); const [showCheckRoutesModal, setShowCheckRoutesModal] = useState(false); const [checkRoutesResult, setCheckRoutesResult] = useState({ inbound: [], outbound: [], attendance: [], addressMismatch: [], customerTypeMismatch: [], customerSpecialNeedsMismatch: [], customerNoteMismatch: [], dischargedOnRoute: [] }); const [customerTypeFixing, setCustomerTypeFixing] = useState({}); @@ -104,6 +106,32 @@ const RoutesDashboard = () => { const [customerNoteFixing, setCustomerNoteFixing] = useState({}); const [isScheduleEditMode, setIsScheduleEditMode] = useState(false); const scheduleImportProgressTimerRef = useRef(null); + const exportProgressTimerRef = useRef(null); + + const stopExportProgressTimer = () => { + if (exportProgressTimerRef.current) { + clearInterval(exportProgressTimerRef.current); + exportProgressTimerRef.current = null; + } + }; + + const startExportRouteReportProgress = () => { + stopExportProgressTimer(); + setIsExportingRouteReport(true); + setExportRouteReportProgress(12); + exportProgressTimerRef.current = setInterval(() => { + setExportRouteReportProgress((prev) => (prev >= 90 ? 90 : prev + 5)); + }, 250); + }; + + const finishExportRouteReportProgress = () => { + stopExportProgressTimer(); + setExportRouteReportProgress(100); + setTimeout(() => { + setIsExportingRouteReport(false); + setExportRouteReportProgress(0); + }, 250); + }; const params = new URLSearchParams(window.location.search); @@ -718,6 +746,12 @@ const RoutesDashboard = () => { setIsScheduleEditMode(false); }, [dateSelected, currentTab]); + useEffect(() => { + return () => { + stopExportProgressTimer(); + }; + }, []); + const now = new Date(); const yesterday = new Date(); const tomorrow = new Date(); @@ -879,6 +913,8 @@ const RoutesDashboard = () => { } const generateRouteReport = async () => { const targetDate = dateSelected || now; + if (isExportingRouteReport) return; + startExportRouteReportProgress(); try { const selectedDateText = getDateString(targetDate); const response = await ReportService.exportRouteReportZip(selectedDateText); @@ -895,6 +931,8 @@ const RoutesDashboard = () => { console.error('Failed to export route report:', error); const message = await getErrorMessageFromBlob(error?.response?.data); window.alert(message); + } finally { + finishExportRouteReportProgress(); } } const goToHistoryPage = () => { @@ -1952,7 +1990,7 @@ const RoutesDashboard = () => { { currentTab === 'allRoutesOverview' && <> { !showCopyDateTargetLoading && <> - { + + + + Generating Route Report + + +
Please wait. User interactions are temporarily disabled.
+ +
+
diff --git a/client/src/components/trans-routes/RoutesHistory.js b/client/src/components/trans-routes/RoutesHistory.js index ce40466..69e0bf0 100644 --- a/client/src/components/trans-routes/RoutesHistory.js +++ b/client/src/components/trans-routes/RoutesHistory.js @@ -1,10 +1,11 @@ -import React, {useState} from "react"; +import React, {useEffect, useRef, useState} from "react"; import { useSelector, useDispatch } from "react-redux"; import { useNavigate } from "react-router-dom"; import { transRoutesSlice ,selectHistoryInboundRoutes, selectHistoryOutboundRoutes, selectHistoryRoutes, selectAllActiveDrivers, selectAllActiveVehicles } from "./../../store"; import RoutesSection from "./RoutesSection"; import PersonnelSection from "./PersonnelSection"; import DatePicker from "react-datepicker"; +import { Modal, ProgressBar } from "react-bootstrap"; import { AuthService, ReportService } from "../../services"; const RoutesHistory = () => { @@ -25,8 +26,42 @@ const RoutesHistory = () => { const outboundRoutes = useSelector(selectHistoryOutboundRoutes); const allRoutes = useSelector(selectHistoryRoutes); const [selectedDate, setSelectedDate] = useState(undefined); + const [isExportingRouteReport, setIsExportingRouteReport] = useState(false); + const [exportRouteReportProgress, setExportRouteReportProgress] = useState(0); + const exportProgressTimerRef = useRef(null); const drivers = useSelector(selectAllActiveDrivers); const vehicles = useSelector(selectAllActiveVehicles); + + const stopExportProgressTimer = () => { + if (exportProgressTimerRef.current) { + clearInterval(exportProgressTimerRef.current); + exportProgressTimerRef.current = null; + } + }; + + const startExportRouteReportProgress = () => { + stopExportProgressTimer(); + setIsExportingRouteReport(true); + setExportRouteReportProgress(12); + exportProgressTimerRef.current = setInterval(() => { + setExportRouteReportProgress((prev) => (prev >= 90 ? 90 : prev + 5)); + }, 250); + }; + + const finishExportRouteReportProgress = () => { + stopExportProgressTimer(); + setExportRouteReportProgress(100); + setTimeout(() => { + setIsExportingRouteReport(false); + setExportRouteReportProgress(0); + }, 250); + }; + + useEffect(() => { + return () => { + stopExportProgressTimer(); + }; + }, []); const backToDashboard = () => { navigate('/trans-routes/dashboard'); } @@ -44,6 +79,8 @@ const RoutesHistory = () => { window.alert('Please select a date first.'); return; } + if (isExportingRouteReport) return; + startExportRouteReportProgress(); try { const selectedDateText = getDateString(selectedDate); const response = await ReportService.exportRouteReportZip(selectedDateText); @@ -60,6 +97,8 @@ const RoutesHistory = () => { console.error('Failed to export route report:', error); const message = await getErrorMessageFromBlob(error?.response?.data); window.alert(message); + } finally { + finishExportRouteReportProgress(); } } @@ -67,7 +106,7 @@ const RoutesHistory = () => { <>
-
Route History
+
Route History
@@ -99,6 +138,16 @@ const RoutesHistory = () => {
+ + + + Generating Route Report + + +
Please wait. User interactions are temporarily disabled.
+ +
+
);