This commit is contained in:
@@ -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 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}`, "✕");
|
||||
}
|
||||
|
||||
|
||||
@@ -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 && <>
|
||||
<button className="btn btn-outline-secondary me-2" onClick={() => generateRouteReport()}>
|
||||
<button className="btn btn-outline-secondary me-2" onClick={() => generateRouteReport()} disabled={isExportingRouteReport}>
|
||||
<Download size={16} className="me-2"></Download>Export Route Report
|
||||
</button>
|
||||
<Dropdown
|
||||
@@ -2275,6 +2313,16 @@ const RoutesDashboard = () => {
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
|
||||
<Modal show={isExportingRouteReport} backdrop="static" keyboard={false} centered>
|
||||
<Modal.Header>
|
||||
<Modal.Title>Generating Route Report</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<div className="mb-2">Please wait. User interactions are temporarily disabled.</div>
|
||||
<ProgressBar now={exportRouteReportProgress} animated label={`${Math.round(exportRouteReportProgress)}%`} />
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -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 = () => {
|
||||
<>
|
||||
<div className="list row">
|
||||
<div className="col-md-4 text-primary mb-2">
|
||||
<h5>Route History <button className="btn btn-link btn-sm ms-2 me-2" onClick={() => backToDashboard()}>Back To Dashboard</button> <button type="button" className="btn btn-primary btn-sm me-2" onClick={()=> generateRouteReport()}>Generate Route Report</button></h5>
|
||||
<h5>Route History <button className="btn btn-link btn-sm ms-2 me-2" onClick={() => backToDashboard()} disabled={isExportingRouteReport}>Back To Dashboard</button> <button type="button" className="btn btn-primary btn-sm me-2" onClick={()=> generateRouteReport()} disabled={isExportingRouteReport}>Generate Route Report</button></h5>
|
||||
</div>
|
||||
</div>
|
||||
<div className="list row mb-4">
|
||||
@@ -99,6 +138,16 @@ const RoutesHistory = () => {
|
||||
<PersonnelSection transRoutes={allRoutes} showCompletedInfo={false} showGroupInfo={false} allowForceEdit={AuthService.canAddOrEditRoutes()} showFilter={true} sectionName="Personnel Status (click on each user to edit)"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal show={isExportingRouteReport} backdrop="static" keyboard={false} centered>
|
||||
<Modal.Header>
|
||||
<Modal.Title>Generating Route Report</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<div className="mb-2">Please wait. User interactions are temporarily disabled.</div>
|
||||
<ProgressBar now={exportRouteReportProgress} animated label={`${Math.round(exportRouteReportProgress)}%`} />
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</>
|
||||
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user