diff --git a/app/.DS_Store b/app/.DS_Store index ce5443f..a6a5969 100644 Binary files a/app/.DS_Store and b/app/.DS_Store differ diff --git a/app/views/asset-manifest.json b/app/views/asset-manifest.json index cd279bf..af610e7 100644 --- a/app/views/asset-manifest.json +++ b/app/views/asset-manifest.json @@ -1,16 +1,16 @@ { "files": { - "main.css": "/static/css/main.184a423c.css", - "main.js": "/static/js/main.6094576b.js", + "main.css": "/static/css/main.bbcd4e86.css", + "main.js": "/static/js/main.8f60a967.js", "static/js/787.c4e7f8f9.chunk.js": "/static/js/787.c4e7f8f9.chunk.js", "static/media/landing.png": "/static/media/landing.d4c6072db7a67dff6a78.png", "index.html": "/index.html", - "main.184a423c.css.map": "/static/css/main.184a423c.css.map", - "main.6094576b.js.map": "/static/js/main.6094576b.js.map", + "main.bbcd4e86.css.map": "/static/css/main.bbcd4e86.css.map", + "main.8f60a967.js.map": "/static/js/main.8f60a967.js.map", "787.c4e7f8f9.chunk.js.map": "/static/js/787.c4e7f8f9.chunk.js.map" }, "entrypoints": [ - "static/css/main.184a423c.css", - "static/js/main.6094576b.js" + "static/css/main.bbcd4e86.css", + "static/js/main.8f60a967.js" ] } \ No newline at end of file diff --git a/app/views/index.html b/app/views/index.html index fd23ba4..f0082b6 100644 --- a/app/views/index.html +++ b/app/views/index.html @@ -1 +1 @@ -
| Name | @@ -300,4 +300,4 @@ const CreateEvent = () => { ); }; -export default CreateEvent; \ No newline at end of file +export default CreateEventRequest; \ No newline at end of file diff --git a/client/src/components/events/CreateEvent.js b/client/src/components/events/CreateEvent.js index b826c41..d108b33 100644 --- a/client/src/components/events/CreateEvent.js +++ b/client/src/components/events/CreateEvent.js @@ -153,91 +153,106 @@ const CreateEvent = () => {
|---|
| Name | diff --git a/client/src/components/home/menu.js b/client/src/components/home/menu.js index c7a50a0..4702a3f 100644 --- a/client/src/components/home/menu.js +++ b/client/src/components/home/menu.js @@ -115,14 +115,14 @@ const SideMenu = () => { }, { name: 'Transportation Schedule', - link: '/trans-routes/schedule', + link: '/trans-routes/dashboard', category: '/trans-routes', - roleFunc: AuthService.canAddOrEditRoutes + roleFunc: AuthService.canViewRoutes }, { name: 'Schedule Driver for Appointment', link: '#', - roleFunc: AuthService.canAddOrEditRoutes + roleFunc: AuthService.canViewRoutes } ] }, diff --git a/client/src/components/trans-routes/PersonnelInfoTable.js b/client/src/components/trans-routes/PersonnelInfoTable.js index 5c221c3..1288d00 100644 --- a/client/src/components/trans-routes/PersonnelInfoTable.js +++ b/client/src/components/trans-routes/PersonnelInfoTable.js @@ -10,16 +10,22 @@ import 'react-time-picker/dist/TimePicker.css'; import moment from 'moment'; import { useNavigate } from "react-router-dom"; -const PersonnelInfoTable = ({transRoutes, showCompletedInfo, showGroupInfo, allowForceEdit, showFilter, driverName, vehicle, relatedOutbound, vehicles, isInbound, deleteFile}) => { +const PersonnelInfoTable = ({transRoutes, showCompletedInfo, + showGroupInfo, allowForceEdit, showFilter, + driverName, vehicle, relatedOutbound, + vehicles, isInbound, deleteFile, + keyword, statusFilter, customerNameFilter, + customerTableId, routeTypeFilter, customerTypeFilter +}) => { const [show, setShow] = useState(false); const [showGroupEditor, setShowGroupEditor] = useState(false); const [customerInEdit, setCustomerInEdit] = useState(undefined); const [customersInEdit, setCustomersInEdit] = useState([]); - const [statusFilter, setStatusFilter] = useState(''); - const [customerTypeFilter, setCustomerTypeFilter] = useState(''); - const [customerNameFilter, setCustomerNameFilter] = useState(''); - const [customerTableId, setCustomerTableId] = useState(''); - const [routeTypeFilter, setRouteTypeFilter] = useState(''); + // const [statusFilter, setStatusFilter] = useState(''); + // const [customerTypeFilter, setCustomerTypeFilter] = useState(''); + // const [customerNameFilter, setCustomerNameFilter] = useState(''); + // const [customerTableId, setCustomerTableId] = useState(''); + // const [routeTypeFilter, setRouteTypeFilter] = useState(''); const [customerCheckInTime, setCustomerCheckInTime] = useState(''); const [customerCheckOutTime, setCustomerCheckOutTime] = useState(''); const [customerPickUpTime, setCustomerPickUpTime] = useState(''); @@ -37,13 +43,13 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo, showGroupInfo, allo const { updateRoute } = transRoutesSlice.actions; const params = new URLSearchParams(window.location.search); const scheduleDate = params.get('dateSchedule'); - const clearFilters = () => { - setStatusFilter(''); - setCustomerTypeFilter(''); - setRouteTypeFilter(''); - setCustomerNameFilter(''); - setCustomerTableId(''); - } + // const clearFilters = () => { + // setStatusFilter(''); + // setCustomerTypeFilter(''); + // setRouteTypeFilter(''); + // setCustomerNameFilter(''); + // setCustomerTableId(''); + // } const openForceEditModal = (customer) => { if (allowForceEdit) { @@ -469,7 +475,7 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo, showGroupInfo, allo <> {!showGroupInfo && (
|---|
| No. | +No. | Name | {showCompletedInfo && (Address | )} {showCompletedInfo && (Tel | )} @@ -594,10 +600,11 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo, showGroupInfo, allo } return result1&&result2&&result3&&result4&&result5; }) + //.filter((item) => item?.customer_name?.includes(keyword) || getTextAndClassName(item)?.text?.includes(keyword) || item?.customer_type?.includes(keyword) || item?.table_id?.includes(keyword)) .sort((a, b) => a.customer_name.replace(' ', '') > b.customer_name.replace(' ', '') ? 1: -1 ) .map((customer, index) => { return (|||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {customer.index} | +{index} | { customer.customer_name} | @@ -607,8 +614,8 @@ const PersonnelInfoTable = ({transRoutes, showCompletedInfo, showGroupInfo, allo {showCompletedInfo && ({ customer.customer_phone } | )} -- { getTextAndClassName(customer).text } + |
+ { getTextAndClassName(customer).text }
|
{ CUSTOMER_TYPE_TEXT[customer.customer_type]}
diff --git a/client/src/components/trans-routes/PersonnelSection.js b/client/src/components/trans-routes/PersonnelSection.js
index b861c9d..9706da4 100644
--- a/client/src/components/trans-routes/PersonnelSection.js
+++ b/client/src/components/trans-routes/PersonnelSection.js
@@ -1,13 +1,27 @@
import React from "react";
import PersonnelInfoTable from "./PersonnelInfoTable";
-const PersonnelSection = ({transRoutes, sectionName, showCompletedInfo, showGroupInfo, allowForceEdit, showFilter, driverName, vehicle, relatedOutbound, vehicles, isInbound, deleteFile}) => {
+const PersonnelSection = ({transRoutes, sectionName, showCompletedInfo,
+ showGroupInfo, allowForceEdit, showFilter,
+ driverName, vehicle, relatedOutbound,
+ vehicles, isInbound, deleteFile, keyword,
+ statusFilter, customerTypeFilter, customerNameFilter, customerTableId, routeTypeFilter
+ }) => {
return (
<>
- {sectionName}{sectionName}
-
- {transRoute.name}
- {`${transRoute?.route_customer_list?.length} Participants`}
+ {`#${routeIndex+1} `}{transRoute.name}
{drivers.find((driver) => driver.id === transRoute.driver)?.name}
+ {`${transRoute?.route_customer_list?.length} Participants`}
{vehicles.find((vehicle) => vehicle.id === transRoute.vehicle)?.tag}
diff --git a/client/src/components/trans-routes/RoutesDashboard.js b/client/src/components/trans-routes/RoutesDashboard.js
index ec96757..b47676c 100644
--- a/client/src/components/trans-routes/RoutesDashboard.js
+++ b/client/src/components/trans-routes/RoutesDashboard.js
@@ -1,41 +1,162 @@
import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
-import { useNavigate } from "react-router-dom";
-import { selectInboundRoutes, selectOutboundRoutes, selectAllBreakfastRecords, selectAllLunchRecords, selectAllSnackRecords, selectAllRoutes, selectAllActiveVehicles, selectAllActiveDrivers, transRoutesSlice } from "./../../store";
+import { useNavigate, useSearchParams } from "react-router-dom";
+import { selectInboundRoutes, selectTomorrowAllRoutes, selectTomorrowInboundRoutes, selectTomorrowOutboundRoutes, selectHistoryInboundRoutes, selectHistoryRoutes, selectHistoryOutboundRoutes, selectOutboundRoutes, selectAllBreakfastRecords, selectAllLunchRecords, selectAllSnackRecords, selectAllRoutes, selectAllActiveVehicles, selectAllActiveDrivers, transRoutesSlice } from "./../../store";
import RoutesSection from "./RoutesSection";
import PersonnelSection from "./PersonnelSection";
-import { AuthService, CustomerService, TransRoutesService } from "../../services";
-import { PERSONAL_ROUTE_STATUS, ROUTE_STATUS, reportRootUrl } from "../../shared";
+import { AuthService, CustomerService, TransRoutesService, DriverService, EventsService, SignatureRequestService } from "../../services";
+import { PERSONAL_ROUTE_STATUS, ROUTE_STATUS, reportRootUrl, CUSTOMER_TYPE_TEXT, PERSONAL_ROUTE_STATUS_TEXT, PICKUP_STATUS, PICKUP_STATUS_TEXT, REPORT_TYPE } from "../../shared";
import BreakfastSection from './BreakfastSection';
import moment from 'moment';
import LunchSection from "./LunchSection";
import SnackSection from "./SnackSection";
+import DatePicker from "react-datepicker";
+import { CalendarWeek, ClockHistory, Copy, Download, Eraser, Plus, Clock, Send, Filter, CalendarCheck, Check } from "react-bootstrap-icons";
+import { Breadcrumb, Tabs, Tab, Dropdown, Spinner, Modal, Button } from "react-bootstrap";
+import RouteCustomerTable from "./RouteCustomerTable";
const RoutesDashboard = () => {
const navigate = useNavigate();
const dispatch = useDispatch();
- const { fetchAllRoutes, createRoute, fetchAllBreakfastRecords, fetchAllLunchRecords, fetchAllSnackRecords } = transRoutesSlice.actions;
+ const { fetchAllRoutes, createRoute, fetchAllBreakfastRecords, fetchAllLunchRecords, fetchAllSnackRecords, fetchAllHistoryRoutes, fetchAllTomorrowRoutes } = transRoutesSlice.actions;
const inboundRoutes = useSelector(selectInboundRoutes);
const outboundRoutes = useSelector(selectOutboundRoutes);
+ const tmrInboundRoutes = useSelector(selectTomorrowInboundRoutes);
+ const tmrOutboundRoutes = useSelector(selectTomorrowOutboundRoutes);
+ const historyInboundRoutes = useSelector(selectHistoryInboundRoutes);
+ const historyOutboundRoutes = useSelector(selectHistoryOutboundRoutes);
const allRoutes = useSelector(selectAllRoutes);
+ const allHistoryRoutes = useSelector(selectHistoryRoutes);
+ const allTomorrowRoutes = useSelector(selectTomorrowAllRoutes);
const drivers = useSelector(selectAllActiveDrivers);
const vehicles = useSelector(selectAllActiveVehicles);
const breakfastRecords = useSelector(selectAllBreakfastRecords);
const lunchRecords = useSelector(selectAllLunchRecords);
const snackRecords = useSelector(selectAllSnackRecords);
- const [showCopyDateLoading, setShowCopyDateLoading] = useState(false);
const [showSyncCustomersLoading, setShowSyncCustomersLoading] = useState(false);
+ const [keyword, setKeyword] = useState('');
+
+ const [directorSignature, setDirectorSignature] = useState(undefined);
+ const [selectedFile, setSelectedFile] = useState();
+ const [selectedDriver, setSelectedDriver] = useState(undefined);
+ const [driverList, setDriverList] = useState([]);
+ const [customers, setCustomers] = useState([]);
+ const [dateSelected, setDateSelected] = useState(new Date());
+ const [routesForSignature, setRoutesForSignature] = useState(allRoutes);
+ const [currentTab, setCurrentTab] = useState('allRoutesOverview');
+ const [sorting, setSorting] = useState({key: '', order: ''});
+ const [selectedItems, setSelectedItems] = useState([]);
+ const [showFilterDropdown, setShowFilterDropdown] = useState(false);
+ const [showDateDropdown, setShowDateDropdown] = useState(false);
+ const [showSignatureRequestLoading, setShowSignatureRequestLoading] = useState(false);
+ const [routesForShowing, setRoutesForShowing] = useState(allRoutes);
+ const [routesInboundForShowing, setRoutesInboundForShowing] = useState(inboundRoutes);
+ const [routesOutboundForShowing, setRoutesOutboundForShowing] = useState(outboundRoutes);
+
+ const [isLoading, setIsLoading] = useState(false);
+ const [errorMessage, setErrorMessage] = useState(undefined);
+ const [successMessage, setSuccessMessage] = useState(undefined);
+ const [showCopyTodayLoading, setShowCopyTodayLoading] = useState(false);
+ const [showCopyDateLoading, setShowCopyDateLoading] = useState(false);
+ const [showCopyDateTargetLoading, setShowCopyDateTargetLoading] = useState(false);
+ const [copyDisabled, setCopyDisabled] = useState(false);
+ const [showDeleteModal, setShowDeleteModal] = useState(false);
+ const [targetedDateSelected, setTargetedDateSelected] = useState(undefined);
+ const [originDateSelected, setOriginDateSelected] = useState(undefined);
+ const [showOriginDateDropdown, setShowOriginDateDropdown] = useState(false);
+ const [showTargetDateDropdown, setShowTargetDateDropdown] = useState(false);
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [showFilterReportDropdown, setShowFilterReportDropdown] = useState(false);
+
+ const [statusFilter, setStatusFilter] = useState('');
+ const [customerTypeFilter, setCustomerTypeFilter] = useState('');
+ const [customerNameFilter, setCustomerNameFilter] = useState('');
+ const [customerTableId, setCustomerTableId] = useState('');
+ const [routeTypeFilter, setRouteTypeFilter] = useState('');
+
+
+ const params = new URLSearchParams(window.location.search);
+ const scheduleDate = params.get('dateSchedule');
+
+ const getDateString = (date) => {
+ return ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear()
+ }
+
+ useEffect(() => {
+ if (scheduleDate) {
+ const [year, month, day] = scheduleDate?.split('-').map(Number);
+ setDateSelected(new Date(year, month-1, day));
+ } else {
+ setDateSelected(new Date())
+ }
+ const site = EventsService.site;
+ DriverService.getAllActiveDrivers('driver', 'active').then((data) => {
+ setDriverList(data.data);
+ });
+ CustomerService.getAllCustomers().then((data) => setCustomers(data?.data));
+ CustomerService.getAvatar(`center_director_signature_site_${site}`).then(data => {
+ if (data?.data) {
+ setDirectorSignature(data?.data)
+ }
+ });
+ }, []);
+
+ useEffect(() => {
+ TransRoutesService.getAll(moment(dateSelected)?.format('MM/DD/YYYY')).then(data => {
+ const routesResults = data.data;
+ const finalRoutes = routesResults.map(async (routeItem) => {
+ const dateArr = moment(dateSelected)?.format('MM/DD/YYYY')?.split('/') || [];
+ try {
+ const result = await CustomerService.getAvatar(`${routeItem.id}_${routeItem.driver}_${dateArr[0]}_${dateArr[1]}`);
+ return result?.data ? Object.assign({}, routeItem, {signature: result?.data}) : routeItem;
+ } catch (ex) {
+ return routeItem;
+ }
+ });
+ Promise.all(finalRoutes).then(finalRoutesData => {
+ setRoutesForSignature(finalRoutesData);
+ })
+ });
+ const selectedDateString = getDateString(dateSelected);
+ if (selectedDateString === getDateString(new Date())) {
+ dispatch(fetchAllRoutes());
+ } else {
+ if (dateSelected > new Date()) {
+ dispatch(fetchAllTomorrowRoutes({dateText: moment(dateSelected).format('MM/DD/YYYY')}));
+ } else {
+ dispatch(fetchAllHistoryRoutes({dateText: getDateString(dateSelected)}))
+ }
+ }
+ }, [dateSelected]);
+
+ useEffect(() => {
+ const selectedDateString = getDateString(dateSelected);
+ if (!dateSelected || selectedDateString === getDateString(new Date())) {
+ setRoutesForShowing(allRoutes);
+ setRoutesInboundForShowing(inboundRoutes);
+ setRoutesOutboundForShowing(outboundRoutes);
+ } else {
+ if (dateSelected > new Date()) {
+ setRoutesForShowing(allTomorrowRoutes);
+ setRoutesInboundForShowing(tmrInboundRoutes);
+ setRoutesOutboundForShowing(tmrOutboundRoutes);
+ } else {
+ setRoutesForShowing(allHistoryRoutes);
+ setRoutesOutboundForShowing(historyOutboundRoutes);
+ setRoutesInboundForShowing(historyInboundRoutes);
+ }
+ }
+ }, [allRoutes, allHistoryRoutes, allTomorrowRoutes]);
+
const now = new Date();
const yesterday = new Date();
const tomorrow = new Date();
yesterday.setDate(now.getDate() - 1);
tomorrow.setDate(now.getDate() + 1);
- const getDateString = (date) => {
- return ((date.getMonth() > 8) ? (date.getMonth() + 1) : ('0' + (date.getMonth() + 1))) + '/' + ((date.getDate() > 9) ? date.getDate() : ('0' + date.getDate())) + '/' + date.getFullYear()
- }
+
const directToSchedule = () => {
- navigate(`/trans-routes/schedule?dateSchedule=${moment(tomorrow).format('YYYY-MM-DD')}`);
+ setDateSelected(tomorrow);
}
const generateRouteReport = () => {
window.open(`${reportRootUrl}?token=${localStorage.getItem('token')}&date=${getDateString(now)}`, '_blank');
@@ -43,12 +164,271 @@ const RoutesDashboard = () => {
const goToHistoryPage = () => {
navigate('/trans-routes/history');
}
- const goToSignature = () => {
- navigate('/trans-routes/route-signature');
+ const createVehicle = () => {
+ navigate('/vehicles?redirect=schedule');
}
+
+ const createDriver = () => {
+ navigate('/employees?redirect=schedule&type=driver');
+ }
+ // const goToSignature = () => {
+ // navigate('/trans-routes/route-signature');
+ // }
const createNewRoute = () => {
navigate('/trans-routes/create')
}
+ const goToCreateRoute = (type) => {
+ navigate(`/trans-routes/create?type=${type}&date=${dateSelected? moment(dateSelected).format('YYYY-MM-DD'): 'tomorrow'}`);
+ }
+ const changeTab = (k) => {
+ setCurrentTab(k);
+ setKeyword('');
+ setSorting({key: '', order: ''});
+ setSelectedItems([]);
+ setDateSelected(new Date());
+ setOriginDateSelected(undefined);
+ setTargetedDateSelected(undefined);
+ // setSelectedDriver(undefined);
+ }
+
+ const cleanupSchedule = () => {
+ allTomorrowRoutes.forEach((route) => {
+ TransRoutesService.deleteRoute(route.id);
+ });
+ setTimeout(() => {
+ closeDeleteModal();
+ window.location.reload();
+ }, 1000)
+ }
+
+ const closeDeleteModal = () => {
+ setShowDeleteModal(false);
+ }
+
+ const triggerShowDeleteModal = () => {
+ setShowDeleteModal(true);
+ }
+
+ const startToScheduleDate = (v) => {
+ // setDateSchedule(v);
+ setSearchParams({dateSchedule: moment(v).format('YYYY-MM-DD')});
+ dispatch(fetchAllTomorrowRoutes({dateText: moment(v).format('MM/DD/YYYY')}));
+ }
+
+ const validateSchedule = () => {
+ const inboundCustomersRouteMap = {};
+ let success = true;
+ for (const inboundRoute of tmrInboundRoutes) {
+ for (const inboundCustomer of inboundRoute.route_customer_list) {
+ if (Object.keys(inboundCustomersRouteMap).includes(inboundCustomer.customer_id) && inboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
+ setSuccessMessage(undefined);
+ success = false;
+ setErrorMessage(`Error: Customer ${inboundCustomer.customer_name} was scheduled in both inbound ${inboundRoute.name} and ${inboundCustomersRouteMap[inboundCustomer.customer_id].name}.`)
+ break;
+ } else {
+ if (inboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
+ inboundCustomersRouteMap[inboundCustomer.customer_id] = inboundRoute;
+ }
+
+ }
+ }
+ }
+ const outboundCustomersRouteMap = {};
+ for (const outboundRoute of tmrOutboundRoutes) {
+ for (const outboundCustomer of outboundRoute.route_customer_list) {
+ if (Object.keys(outboundCustomersRouteMap).includes(outboundCustomer.customer_id) && outboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
+ setSuccessMessage(undefined);
+ success = false;
+ setErrorMessage(`Error: Customer ${outboundCustomer.customer_name} was scheduled in both outbound ${outboundRoute.name} and ${outboundCustomersRouteMap[outboundCustomer.customer_id].name}.`)
+ break;
+ } else {
+ if (outboundCustomer.customer_route_status !== PERSONAL_ROUTE_STATUS.DISABLED) {
+ outboundCustomersRouteMap[outboundCustomer.customer_id] = outboundRoute;
+ }
+
+ }
+ }
+ }
+ if (success) {
+ setErrorMessage(undefined);
+ setSuccessMessage(`Routes Schedule Validate Successfully`);
+ }
+ }
+
+ const copyTodayRoutesOver = () => {
+ setShowCopyTodayLoading(true);
+ setIsLoading(true);
+ let count = 0;
+ TransRoutesService.getAll(((now.getMonth() > 8) ? (now.getMonth() + 1) : ('0' + (now.getMonth() + 1))) + '/' + ((now.getDate() > 9) ? now.getDate() : ('0' + now.getDate())) + '/' + now.getFullYear()).then(existingRoutes => {
+ for (const draftRoute of allRoutes) {
+ const existed = existingRoutes?.data?.find(r => r.name === draftRoute.name);
+ if (draftRoute && !existed) {
+ const data = Object.assign({}, {
+ name: draftRoute.name,
+ schedule_date: ((now.getMonth() > 8) ? (now.getMonth() + 1) : ('0' + (now.getMonth() + 1))) + '/' + ((now.getDate() > 9) ? now.getDate() : ('0' + now.getDate())) + '/' + now.getFullYear(),
+ vehicle: draftRoute.vehicle,
+ driver: draftRoute.driver,
+ type: draftRoute.type,
+ start_mileage: vehicles.find((vehicle) => vehicle.id === draftRoute.vehicle)?.mileage,
+ route_customer_list: draftRoute.route_customer_list?.map((customer) => {
+ return Object.assign({}, customer, {
+ customer_enter_center_time: null,
+ customer_leave_center_time: null,
+ customer_pickup_time: null,
+ customer_dropoff_time: null,
+ customer_estimated_pickup_time: null,
+ customer_estimated_dropoff_time: null,
+ customer_route_status: PERSONAL_ROUTE_STATUS.NO_STATUS,
+ customer_address_override: null
+ })
+ })
+ });
+ dispatch(createRoute({ data }));
+ } else {
+ if (existed) {
+ count++;
+ }
+ }
+ }
+ setTimeout(() => {
+ dispatch(fetchAllTomorrowRoutes({}));
+ setShowCopyTodayLoading(false);
+ setCopyDisabled(true);
+ setIsLoading(false);
+ setSuccessMessage('Routes Copied Successfully, please do not click the button again!');
+ if (count > 0) {
+ window.alert(`${count} routes has existed in selected date and is not copied again!`)
+ }
+ }, 2000);
+ })
+ }
+
+ const copyDateRoutesOver = (withTargetDate) => {
+ const dateOrigin = new Date(originDateSelected);
+ const newScheduleDate = withTargetDate ? new Date(targetedDateSelected) : now;
+ if (withTargetDate) {
+ setShowCopyDateTargetLoading(true);
+ } else {
+ setShowCopyDateLoading(true);
+ }
+
+ setIsLoading(true);
+ let count = 0;
+ TransRoutesService.getAll(getDateString(dateOrigin)).then(({data: allHistoryRoutes}) => {
+ TransRoutesService.getAll(((newScheduleDate.getMonth() > 8) ? (newScheduleDate.getMonth() + 1) : ('0' + (newScheduleDate.getMonth() + 1))) + '/' + ((newScheduleDate.getDate() > 9) ? newScheduleDate.getDate() : ('0' + newScheduleDate.getDate())) + '/' + newScheduleDate.getFullYear()).then(existingRoutes => {
+ for (const draftRoute of allHistoryRoutes) {
+ const existed = existingRoutes?.data?.find((r) => r. name === draftRoute.name);
+ if (draftRoute && !existed) {
+ const data = Object.assign({}, {
+ name: draftRoute.name,
+ schedule_date: ((newScheduleDate.getMonth() > 8) ? (newScheduleDate.getMonth() + 1) : ('0' + (newScheduleDate.getMonth() + 1))) + '/' + ((newScheduleDate.getDate() > 9) ? newScheduleDate.getDate() : ('0' + newScheduleDate.getDate())) + '/' + newScheduleDate.getFullYear(),
+ vehicle: draftRoute.vehicle,
+ driver: draftRoute.driver,
+ type: draftRoute.type,
+ start_mileage: vehicles.find((vehicle) => vehicle.id === draftRoute.vehicle)?.mileage,
+ route_customer_list: draftRoute.route_customer_list?.map((customer) => {
+ return Object.assign({}, customer, {
+ customer_enter_center_time: null,
+ customer_leave_center_time: null,
+ customer_pickup_time: null,
+ customer_dropoff_time: null,
+ customer_estimated_pickup_time: null,
+ customer_estimated_dropoff_time: null,
+ customer_route_status: PERSONAL_ROUTE_STATUS.NO_STATUS,
+ customer_address_override: null
+ })
+ })
+ });
+ dispatch(createRoute({ data }));
+ } else {
+ if (existed) {
+ count++;
+ }
+ }
+ }
+ setTimeout(() => {
+ // dispatch(fetchAllTomorrowRoutes({}));
+ startToScheduleDate(withTargetDate ? targetedDateSelected : now);
+ if (withTargetDate) {
+ setShowCopyDateTargetLoading(false);
+ } else {
+ setShowCopyDateLoading(false);
+ }
+ setIsLoading(false);
+ // setCopyDateDisabled(true);
+ setSuccessMessage('Routes Copied Successfully, please do not click the button again!');
+ setDateSelected(targetedDateSelected);
+ setOriginDateSelected(undefined);
+ setTargetedDateSelected(undefined);
+ if (count > 0) {
+ window.alert(`${count} routes has existed on selected date and are not copied again.`)
+ }
+ }, 2000);
+ });
+ });
+ }
+
+
+ const uploadDirectorSignature = () => {
+ const formData = new FormData();
+ const site = EventsService.site;
+ formData.append("file", selectedFile);
+ if (selectedFile) {
+ if (directorSignature) {
+ CustomerService.deleteFile({'name': `center_director_signature_site_${site}`}).then(() => {
+ CustomerService.uploadAvatar(`center_director_signature_site_${site}`, formData).then(() => {
+ CustomerService.getAvatar(`center_director_signature_site_${site}`).then(data => {
+ if (data?.data) {
+ setDirectorSignature(data?.data)
+ }
+ });
+ })
+ })
+ } else {
+ CustomerService.uploadAvatar(`center_director_signature_site_${site}`, formData).then(() => {
+ CustomerService.getAvatar(`center_director_signature_site_${site}`).then(data => {
+ if (data?.data) {
+ setDirectorSignature(data?.data)
+ }
+ });
+ })
+ }
+ }
+ }
+
+ const getAllUniqueCustomers = (routes) => {
+ let result = [];
+ for (const route of routes) {
+ const customerList = route.route_customer_list.map(item => Object.assign({}, item, {routeType: route.type, routeId: route.id, route: route, customer_status_inbound: route.type === 'inbound' && item.customer_route_status, customer_status_outbound: route.type === 'outbound' && item.customer_route_status, inbound: route.type === 'inbound' && route, outbound: route.type === 'outbound' && route}))
+ for (const customer of customerList) {
+ const existItem = result.find((item => (item.customer_id === customer.customer_id) || (item?.customer_name?.replaceAll(' ', '')?.toLowerCase() === customer?.customer_name?.replaceAll(' ', '')?.toLowerCase()) ));
+ if (existItem) {
+ result = result.filter(item => item !== existItem);
+ const newItem = Object.assign({}, existItem, {
+ customer_enter_center_time: existItem?.customer_enter_center_time || customer?.customer_enter_center_time,
+ customer_leave_center_time: existItem?.customer_leave_center_time || customer?.customer_leave_center_time,
+ customer_pickup_time: existItem?.customer_pickup_time || customer?.customer_pickup_time,
+ customer_dropoff_time: existItem?.customer_dropoff_time || customer?.customer_dropoff_time,
+ inbound: existItem?.inbound || customer?.inbound,
+ outbound: existItem?.outbound || customer?.outbound,
+ customer_status_inbound: existItem?.customer_status_inbound || customer?.customer_status_inbound,
+ customer_status_outbound: existItem?.customer_status_outbound || customer?.customer_status_outbound
+ })
+ result.push(newItem);
+ } else {
+ result.push(customer);
+ }
+ }
+ }
+ return result.sort((a, b) => {
+ if (a.customer_name < b.customer_name) {
+ return -1;
+ } else {
+ return 1;
+ }
+ });
+ }
+
const copyYesterdayRoutes = () => {
setShowCopyDateLoading(true);
TransRoutesService.getAll(getDateString(yesterday)).then(({data: yesterdayRoutes}) => {
@@ -131,6 +511,309 @@ const RoutesDashboard = () => {
setTimeout(() => { dispatch(fetchAllRoutes()); setShowSyncCustomersLoading(false);}, 5000);
})
}
+
+ const cleanFilterAndClose = () => {
+ setSelectedDriver(null);
+ // setDateSelected(new Date())
+ setShowFilterDropdown(false);
+ setShowDateDropdown(false);
+ setCustomerTableId('');
+ setStatusFilter('');
+ setCustomerNameFilter('');
+ setCustomerTypeFilter('');
+ setKeyword('');
+ setRouteTypeFilter('');
+ setShowFilterReportDropdown(false);
+ }
+
+ const cleanDate = () => {
+ setDateSelected(new Date());
+ setShowDateDropdown(false);
+ }
+
+ const FilterAndClose = () => {
+ setShowFilterDropdown(false);
+ setShowDateDropdown(false);
+ setShowFilterReportDropdown(false);
+ }
+
+ const getSortingImg = (key) => {
+ return sorting.key === key ? (sorting.order === 'asc' ? 'up_arrow' : 'down_arrow') : 'default';
+ }
+
+ const sortTableWithField = (key) => {
+ let newSorting = {
+ key,
+ order: 'asc',
+ }
+
+ if (sorting.key === key && sorting.order === 'asc') {
+ newSorting = {...newSorting, order: 'desc'};
+ }
+ setSorting(newSorting);
+ }
+
+ const toggleSelectedAllItems = () => {
+ const filteredSignatures = routesForSignature && routesForSignature.filter((route) => {
+ if (!selectedDriver) {
+ return route;
+ } else {
+ return route?.driver === selectedDriver;
+ }
+ }).filter(((route) => route.name?.toLowerCase().includes(keyword?.toLowerCase()) || drivers.find((d) => d.id === route?.driver)?.name?.toLowerCase().includes(keyword?.toLowerCase())));
+ if (selectedItems.length !== filteredSignatures.length || selectedItems.length === 0) {
+ const newSelectedItems = [...filteredSignatures].map((sig) => sig.id);
+ setSelectedItems(newSelectedItems);
+ } else {
+ setSelectedItems([]);
+ }
+ }
+
+ const toggleItem = (id) => {
+ if (selectedItems.includes(id)) {
+ const newSelectedItems = [...selectedItems].filter((item) => item !== id);
+ setSelectedItems(newSelectedItems);
+ } else {
+ const newSelectedItems = [...selectedItems, id];
+ setSelectedItems(newSelectedItems);
+ }
+ }
+
+ const checkSelectAll = () => {
+ const filteredSignatures = routesForSignature && routesForSignature.filter((route) => {
+ if (!selectedDriver) {
+ return route;
+ } else {
+ return route?.driver === selectedDriver;
+ }
+ }).filter((route) => route.name?.toLowerCase().includes(keyword?.toLowerCase()) || drivers.find((d) => d.id === route?.driver)?.name?.toLowerCase().includes(keyword?.toLowerCase()));
+ return selectedItems.length === filteredSignatures.length && selectedItems.length > 0;
+ }
+
+ const pickOriginDateSelected = (v) => {
+ setOriginDateSelected(v);
+ setDateSelected(v);
+ }
+
+ const columns = [
+ {
+ key: 'name',
+ label: 'Route Name'
+ },
+ {
+ key: 'driver',
+ label: 'Driver'
+ },
+ {
+ key: 'end_time',
+ label: 'Route End Time'
+ },
+ {
+ key: 'type',
+ label: 'Route Type'
+ },
+ ];
+
+ const customMenu = React.forwardRef(
+ ({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
+ return (
+
+
+ );
+ },
+ );
+
+ const customReportFilterMenu = React.forwardRef(
+ ({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
+ return (
+ Filter By+
+
+
+
+ Driver
+
+
+
+
+
+
+
+
+
+ );
+ },
+ );
+
+ const customMenuDate = React.forwardRef(
+ ({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
+ return (
+ Filter By+
+
+
+
+ Participate Status
+
+
+
+
+
+ Participant Type
+
+
+
+
+
+ Routes Type
+
+
+
+
+
+ Participant Name
+ setCustomerNameFilter(e.target.value)} />
+
+
+ Table Id
+ setCustomerTableId(e.target.value)} />
+
+
+
+
+
+
+
+
+ );
+ },
+ );
+
+ const customMenuOriginDate = React.forwardRef(
+ ({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
+ return (
+
+
+
+
+ Select Date to Start
+
+
+
+
+
+
+
+
+ );
+ },
+ );
+
+ const customMenuTargetDate = React.forwardRef(
+ ({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
+ return (
+
+
+
+
+ Select Date to Start
+
+
+
+
+
+
+
+ );
+ },
+ );
+
+
+
+ const generateSignatureRequest = async () => {
+ setShowSignatureRequestLoading(true);
+ for (const id of selectedItems) {
+ const currentRoute = routesForSignature.find(route => route?.id === id);
+ const currentDriver = drivers.find(driver => driver?.id === currentRoute?.driver);
+ await SignatureRequestService.createNewSignatureRequest({
+ driver_id: currentRoute?.id,
+ driver_name: currentDriver?.name,
+ route_id: currentRoute?.id,
+ route_date: currentRoute?.schedule_date,
+ route_name: currentRoute?.name,
+ status: 'active',
+ })
+ }
+ setShowSignatureRequestLoading(false);
+ }
+
const confimHasBreakfast = (customer) => {
TransRoutesService.createBreakfastRecords({
customer_id: customer?.customer_id,
@@ -200,14 +883,339 @@ const RoutesDashboard = () => {
dispatch(fetchAllSnackRecords());
})
}
+
+
return (
<>
-
+
+
+
+ Select Date to Start
+
+
+
+
+
+
+
-
- */}
>
);
diff --git a/client/src/components/trans-routes/RoutesSchedule.js b/client/src/components/trans-routes/RoutesSchedule.js
index 535173b..ec3e108 100644
--- a/client/src/components/trans-routes/RoutesSchedule.js
+++ b/client/src/components/trans-routes/RoutesSchedule.js
@@ -323,7 +323,7 @@ const RoutesSchedule = () => {
Today's Route Status+
+
-
+
+ All Routes +
+
-
+
+
+
+ {/*
+
+
+
+
+
+
+
+
+ }
+ {(dateSelected && dateSelected > new Date()) &&
+
+
+
+ }
+ { (dateSelected <= new Date() || !dateSelected) &&
+ {
+ showCopyDateTargetLoading ? <> }
+ {
+ dateSelected > new Date() && <>
+ {errorMessage &&
+
+
+
+ {(!dateSelected || getDateString(dateSelected) === getDateString(new Date())) &&
+ }
+ >
+ }
+
+
+
+
+
+
+
+ +
+ {errorMessage}
+
+ }
+ {successMessage &&
+ {successMessage}
+
+ }
+
+ {isLoading &&
+ >
+ }
+
+
+ +
+
+ + {(AuthService.canCreateOrEditDrivers() || AuthService.canAddOrEditEmployees()) &&
+ }
+ + {AuthService.canAddOrEditVechiles() &&
+ }
+ +
+ {routesForShowing && vehicles &&
+ >}
+
+ + {moment(dateSelected)?.format('MM/DD/YYYY')}+
+
+
+
+
+
+ Center Director Signature:
+ {directorSignature && No Director Signature Uploaded yet }
+ Upload Center Director New Signature:
+ setSelectedFile(e.target.files[0])} className="form-control-file border">
+
+
+
+
+
+
+ {
+ currentTab === 'allRoutesOverview' && <> {
+ !showCopyDateTargetLoading && <>
+
+ Are you sure you want to delete all the schedule?
+
Today's Date: { new Date().toLocaleDateString() }
@@ -223,34 +1231,7 @@ const RoutesDashboard = () => {
-
-
-
- -
-
- -
-
-
-
-
-
-
-
- -
-
+
-
- Are you sure you want to delete all the schedule?
|