312 lines
14 KiB
JavaScript
312 lines
14 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import { useSelector } from "react-redux";
|
|
import { useNavigate, useParams } from "react-router-dom";
|
|
import { selectAllActiveDrivers, selectAllActiveVehicles } from "./../../store";
|
|
import { Modal, Button, Breadcrumb, Tabs, Tab } from "react-bootstrap";
|
|
import RouteCustomerEditor from "./RouteCustomerEditor";
|
|
import { AuthService, DailyRoutesTemplateService } from "../../services";
|
|
|
|
const CreateTemplateRoute = () => {
|
|
const params = useParams();
|
|
const templateId = params.id;
|
|
const routeType = new URLSearchParams(window.location.search).get('type');
|
|
|
|
const drivers = useSelector(selectAllActiveDrivers);
|
|
const vehicles = useSelector(selectAllActiveVehicles);
|
|
const navigate = useNavigate();
|
|
|
|
const [routeName, setRouteName] = useState('');
|
|
const [newDriver, setNewDriver] = useState('');
|
|
const [newVehicle, setNewVehicle] = useState('');
|
|
const [newRouteType, setNewRouteType] = useState(routeType || 'inbound');
|
|
const [newCustomerList, setNewCustomerList] = useState([]);
|
|
const [errorMessage, setErrorMessage] = useState(undefined);
|
|
const [disableSave, setDisableSave] = useState(false);
|
|
const [template, setTemplate] = useState(null);
|
|
|
|
const currentVehicle = vehicles.find((vehicle) => vehicle.id === newVehicle);
|
|
|
|
useEffect(() => {
|
|
if (!AuthService.canAddOrEditRoutes()) {
|
|
window.alert('You haven\'t login yet OR this user does not have access to this page. Please change an admin account to login.')
|
|
AuthService.logout();
|
|
navigate(`/login`);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
// Fetch the template to get its name
|
|
DailyRoutesTemplateService.getDailyRoutesTemplate(templateId).then(data => {
|
|
setTemplate(data.data);
|
|
});
|
|
}, [templateId]);
|
|
|
|
const redirectToTemplate = () => {
|
|
navigate(`/trans-routes/daily-templates/view/${templateId}`);
|
|
}
|
|
|
|
const validateRoute = () => {
|
|
const errors = [];
|
|
|
|
// Required fields validation
|
|
if (!routeName || routeName.trim() === '') {
|
|
errors.push('Route Name');
|
|
}
|
|
if (!newRouteType || newRouteType === '') {
|
|
errors.push('Route Type');
|
|
}
|
|
if (!newDriver || newDriver === '') {
|
|
errors.push('Driver');
|
|
}
|
|
if (!newVehicle || newVehicle === '') {
|
|
errors.push('Vehicle');
|
|
}
|
|
|
|
if (errors.length > 0) {
|
|
window.alert(`Please fill in the following required fields:\n${errors.join('\n')}`);
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
const saveRoute = () => {
|
|
if (!disableSave) {
|
|
if (!validateRoute()) {
|
|
return;
|
|
}
|
|
setDisableSave(true);
|
|
|
|
// Fetch the current template
|
|
DailyRoutesTemplateService.getDailyRoutesTemplate(templateId).then(response => {
|
|
const currentTemplate = response.data;
|
|
|
|
// Create the new route object
|
|
const newRoute = {
|
|
name: routeName,
|
|
route_customer_list: newCustomerList,
|
|
driver: newDriver,
|
|
vehicle: newVehicle,
|
|
type: newRouteType,
|
|
start_mileage: currentVehicle.mileage,
|
|
status: [],
|
|
start_time: null,
|
|
end_time: null,
|
|
estimated_start_time: null,
|
|
checklist_result: []
|
|
};
|
|
|
|
// Add the new route to the template's routes array
|
|
const updatedRoutes = [...(currentTemplate.routes || []), newRoute];
|
|
|
|
// Update the template
|
|
const updatedTemplate = {
|
|
...currentTemplate,
|
|
routes: updatedRoutes
|
|
};
|
|
|
|
DailyRoutesTemplateService.updateDailyRoutesTemplate(templateId, updatedTemplate)
|
|
.then(() => {
|
|
setTimeout(() => {
|
|
setDisableSave(false);
|
|
redirectToTemplate();
|
|
}, 1000);
|
|
})
|
|
.catch(err => {
|
|
setDisableSave(false);
|
|
setErrorMessage('Failed to save route to template');
|
|
});
|
|
}).catch(err => {
|
|
setDisableSave(false);
|
|
setErrorMessage('Failed to fetch template');
|
|
});
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div className="list row mb-4">
|
|
<Breadcrumb>
|
|
<Breadcrumb.Item href="/trans-routes/dashboard">Transportation</Breadcrumb.Item>
|
|
<Breadcrumb.Item href="/trans-routes/daily-templates/list">
|
|
Daily Route Templates
|
|
</Breadcrumb.Item>
|
|
{template && (
|
|
<Breadcrumb.Item href={`/trans-routes/daily-templates/view/${templateId}`}>
|
|
{template.name}
|
|
</Breadcrumb.Item>
|
|
)}
|
|
<Breadcrumb.Item active>
|
|
Create New Route
|
|
</Breadcrumb.Item>
|
|
</Breadcrumb>
|
|
<div className="col-md-12 text-primary">
|
|
<h4>
|
|
Create New Route for Template <button className="btn btn-link btn-sm" onClick={() => {redirectToTemplate()}}>Back</button>
|
|
</h4>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="app-main-content-list-container form-page">
|
|
<div className="app-main-content-list-func-container">
|
|
<Tabs defaultActiveKey="routeOverview" id="route-view-tab">
|
|
<Tab eventKey="routeOverview" title="Route Information">
|
|
<div className="multi-columns-container">
|
|
<div className="column-container">
|
|
<div className="column-card">
|
|
<h6 className="text-primary">Route Details</h6>
|
|
|
|
<div className="app-main-content-fields-section">
|
|
<div className="me-4">
|
|
<div className="field-label">Route Name
|
|
<span className="required">*</span>
|
|
</div>
|
|
<input type="text" value={routeName || ''} onChange={e => setRouteName(e.target.value)}/>
|
|
</div>
|
|
<div className="me-4">
|
|
<div className="field-label">Vechile
|
|
<span className="required">*</span>
|
|
</div>
|
|
<select value={newVehicle} onChange={e => setNewVehicle(e.target.value)}>
|
|
<option value=""></option>
|
|
{vehicles.map((vehicle) => (<option key={vehicle.id} value={vehicle.id}>{vehicle.vehicle_number}</option>))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div className="app-main-content-fields-section">
|
|
<div className="me-4">
|
|
<div className="field-label">Driver
|
|
<span className="required">*</span>
|
|
</div>
|
|
<select value={newDriver} onChange={e => setNewDriver(e.target.value)}>
|
|
<option value=""></option>
|
|
{drivers.map((driver) => <option key={driver.id} value={driver.id}>{driver.name}</option>)}
|
|
</select>
|
|
</div>
|
|
<div className="me-4">
|
|
<div className="field-label">Route Type
|
|
<span className="required">*</span>
|
|
</div>
|
|
<select value={newRouteType} onChange={e => setNewRouteType(e.target.value)}>
|
|
<option value="inbound">Inbound</option>
|
|
<option value="outbound">Outbound</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="column-card adjust">
|
|
<div className="col-md-12 mb-4">
|
|
<RouteCustomerEditor currentRoute={undefined} setNewCustomerList={setNewCustomerList}></RouteCustomerEditor>
|
|
</div>
|
|
</div>
|
|
<div className="list row mb-5">
|
|
<div className="col-md-12 col-sm-12 col-xs-12">
|
|
|
|
<button className="btn btn-default btn-sm float-right" onClick={() => redirectToTemplate()}> Cancel </button>
|
|
<button className="btn btn-primary btn-sm float-right" disabled={disableSave} onClick={() => saveRoute()}> Save </button>
|
|
</div>
|
|
{errorMessage && <div className="col-md-12 col-sm-12 col-xs-12 alert alert-danger mt-4">{errorMessage}</div>}
|
|
|
|
</div>
|
|
</div>
|
|
<div className="column-container">
|
|
{ newVehicle && newVehicle !== '' && <div className="column-card mb-4">
|
|
<h6 className="text-primary">Vehicle Information</h6>
|
|
<div className="app-main-content-fields-section short">
|
|
<div className="field-body">
|
|
<div className="field-label">Vehicle Number</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.vehicle_number}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Seating Capacity</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.capacity}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Mileage</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.mileage}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Make</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.make}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Model</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.model}</div>
|
|
</div>
|
|
</div>
|
|
<div className="app-main-content-fields-section short">
|
|
<div className="field-body">
|
|
<div className="field-label">License Plate</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.tag}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Year</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.year}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">GPS ID</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.gps_tag}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">EZPass</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.ezpass}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Vin</div>
|
|
<div className="field-value">{vehicles.find(item => item.id === newVehicle)?.vin || ''}</div>
|
|
</div>
|
|
</div>
|
|
</div>}
|
|
{
|
|
newDriver && newDriver !== '' && <div className="column-card">
|
|
<h6 className="text-primary">Driver Information</h6>
|
|
<div className="text-primary">Personal Details</div>
|
|
<div className="app-main-content-fields-section short">
|
|
<div className="field-body">
|
|
<div className="field-label">Driver Name</div>
|
|
<div className="field-value">{drivers.find(item => item.id === newDriver)?.name}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Preferred Name</div>
|
|
<div className="field-value">{drivers.find(item => item.id === newDriver)?.name_cn}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Job Title</div>
|
|
<div className="field-value">{drivers.find(item => item.id === newDriver)?.title}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Job Status</div>
|
|
<div className="field-value">{drivers.find(item => item.id === newDriver)?.employment_status}</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div className="app-main-content-fields-section short">
|
|
<div className="field-body">
|
|
<div className="field-label">Driver Capacity</div>
|
|
<div className="field-value">{drivers.find(item => item.id === newDriver)?.driver_capacity}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Phone Number</div>
|
|
<div className="field-value">{drivers.find(item => item.id === newDriver)?.phone}</div>
|
|
</div>
|
|
<div className="field-body">
|
|
<div className="field-label">Email</div>
|
|
<div className="field-value">{drivers.find(item => item.id === newDriver)?.email}</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</Tab>
|
|
</Tabs>
|
|
</div>
|
|
</div>
|
|
</>
|
|
|
|
);
|
|
};
|
|
|
|
export default CreateTemplateRoute;
|
|
|