Revert departure and arrival datetime of stops

This commit is contained in:
Roba Boru
2026-07-21 00:24:32 +03:00
parent 5adb145aca
commit be933c2c0d
8 changed files with 338 additions and 1402 deletions

View File

@@ -10,14 +10,6 @@ import Modal from '@/components/ui/Modal';
import ConfirmDialog from '@/components/ui/ConfirmDialog';
import { routesApi } from '@/lib/api/routes';
import { stationsApi, fleetApi, routeCoachTemplatesApi } from '@/lib/api';
import DateTimePicker from '@/components/ui/DateTimePicker';
// EAT ↔ UTC helpers (same as schedules page)
const EAT_MS = 3 * 60 * 60 * 1000;
const isoToEAT = (iso: string): string =>
new Date(new Date(iso).getTime() + EAT_MS).toISOString().slice(0, 16);
const eatToISO = (local: string): string =>
new Date(new Date(local + ':00Z').getTime() - EAT_MS).toISOString();
interface RouteStop {
stationId: string;
@@ -25,8 +17,6 @@ interface RouteStop {
distanceKm?: number;
distanceFromOrigin?: number;
checkinMinutesBefore?: number;
plannedArrivalTime?: string;
plannedDepartureTime?: string;
}
type Tab = 'routes' | 'coaches';
@@ -185,8 +175,6 @@ export default function RoutesPage() {
const [destinationDistance, setDestinationDistance] = useState<number | undefined>(undefined);
const [originCheckinMinutes, setOriginCheckinMinutes] = useState<number | undefined>(undefined);
const [destinationCheckinMinutes, setDestinationCheckinMinutes] = useState<number | undefined>(undefined);
const [originDepartureTime, setOriginDepartureTime] = useState<string>('');
const [destinationArrivalTime, setDestinationArrivalTime] = useState<string>('');
const [deleteConfirm, setDeleteConfirm] = useState<{ isOpen: boolean; route: any | null; error?: string; cascade?: boolean; cascadeChecked?: boolean }>({ isOpen: false, route: null });
const [search, setSearch] = useState('');
const queryClient = useQueryClient();
@@ -257,27 +245,18 @@ export default function RoutesPage() {
// distanceKm = cumulative distance from origin (fare engine uses destStop.distanceKm - originStop.distanceKm)
const stopsArray = [
{
stationId: originStationId,
sequence: 1,
distanceKm: 0,
checkinMinutesBefore: originCheckinMinutes ?? undefined,
plannedDepartureTime: originDepartureTime ? eatToISO(originDepartureTime) : undefined,
},
{ stationId: originStationId, sequence: 1, distanceKm: 0, checkinMinutesBefore: originCheckinMinutes ?? undefined },
...sortedMiddleStops.map((stop, idx) => ({
stationId: stop.stationId,
sequence: idx + 2,
distanceKm: stop.distanceFromOrigin || 0,
checkinMinutesBefore: stop.checkinMinutesBefore ?? undefined,
plannedArrivalTime: stop.plannedArrivalTime ? eatToISO(stop.plannedArrivalTime) : undefined,
plannedDepartureTime: stop.plannedDepartureTime ? eatToISO(stop.plannedDepartureTime) : undefined,
})),
{
stationId: destinationStationId,
sequence: sortedMiddleStops.length + 2,
distanceKm: destinationDistance || 0,
checkinMinutesBefore: destinationCheckinMinutes ?? undefined,
plannedArrivalTime: destinationArrivalTime ? eatToISO(destinationArrivalTime) : undefined,
},
];
@@ -408,10 +387,8 @@ export default function RoutesPage() {
const destStop = routeStops[routeStops.length - 1];
setOriginStationId(originStop.stationId);
setOriginCheckinMinutes(originStop.checkinMinutesBefore ?? undefined);
setOriginDepartureTime(originStop.plannedDepartureTime ? isoToEAT(originStop.plannedDepartureTime) : '');
setDestinationStationId(destStop.stationId);
setDestinationCheckinMinutes(destStop.checkinMinutesBefore ?? undefined);
setDestinationArrivalTime(destStop.plannedArrivalTime ? isoToEAT(destStop.plannedArrivalTime) : '');
setDestinationDistance(destStop.distanceKm || 0);
setStops(routeStops.slice(1, -1).map((s: any) => ({
stationId: s.stationId,
@@ -419,8 +396,6 @@ export default function RoutesPage() {
distanceKm: s.distanceKm,
distanceFromOrigin: s.distanceKm || 0,
checkinMinutesBefore: s.checkinMinutesBefore ?? undefined,
plannedArrivalTime: s.plannedArrivalTime ? isoToEAT(s.plannedArrivalTime) : '',
plannedDepartureTime: s.plannedDepartureTime ? isoToEAT(s.plannedDepartureTime) : '',
})));
}
setShowModal(true);
@@ -458,10 +433,8 @@ export default function RoutesPage() {
setEditingRoute(null);
setOriginStationId('');
setOriginCheckinMinutes(undefined);
setOriginDepartureTime('');
setDestinationStationId('');
setDestinationCheckinMinutes(undefined);
setDestinationArrivalTime('');
setDestinationDistance(undefined);
setStops([]);
setShowModal(true);
@@ -546,7 +519,7 @@ export default function RoutesPage() {
setSearch('');
}}
title={`${editingRoute ? 'Edit' : 'Add'} Route`}
size="xl"
size="lg"
>
<form onSubmit={handleSubmit} className="space-y-4 max-h-[calc(100vh-200px)] overflow-y-auto">
{editingRoute && (
@@ -692,7 +665,7 @@ export default function RoutesPage() {
<div className="border-t pt-4">
<div className="flex items-center justify-between mb-3">
<label className="label mb-0">Route Stops</label>
<span className="text-xs text-muted-foreground">Drag to rearrange · <span className="font-medium">Cutoff</span> overrides check-in · <span className="font-medium">Arr/Dep time</span> sets default times (auto-filled on schedule creation)</span>
<span className="text-xs text-muted-foreground">Drag to rearrange · <span className="font-medium">Cutoff min</span> overrides route check-in window per stop (leave blank to inherit)</span>
</div>
<div className="space-y-2">
@@ -710,7 +683,7 @@ export default function RoutesPage() {
<span className="text-muted-foreground">Select origin station above</span>
)}
</div>
<div className="w-24 flex-shrink-0">
<div className="w-28 flex-shrink-0">
<input
type="number"
className="input input-sm"
@@ -721,15 +694,7 @@ export default function RoutesPage() {
title="Check-in cutoff override (minutes) for this stop"
/>
</div>
<div className="w-44 flex-shrink-0">
<DateTimePicker
value={originDepartureTime}
onChange={setOriginDepartureTime}
placeholder="Dep time"
label="Planned Departure"
/>
</div>
<div className="text-sm text-muted-foreground w-10 text-right flex-shrink-0">0 km</div>
<div className="text-sm text-muted-foreground w-12 text-right flex-shrink-0">0 km</div>
</div>
{stops.map((stop, index) => (
@@ -764,7 +729,7 @@ export default function RoutesPage() {
))}
</select>
</div>
<div className="w-20">
<div className="w-28">
<input
type="number"
className="input input-sm"
@@ -776,33 +741,17 @@ export default function RoutesPage() {
required
/>
</div>
<div className="w-20">
<div className="w-28">
<input
type="number"
className="input input-sm"
placeholder="cutoff"
placeholder="cutoff min"
value={stop.checkinMinutesBefore ?? ''}
onChange={(e) => updateStop(index, 'checkinMinutesBefore', e.target.value ? parseInt(e.target.value) : undefined)}
min={1}
title="Check-in cutoff override (minutes) for this stop"
/>
</div>
<div className="w-44">
<DateTimePicker
value={stop.plannedArrivalTime ?? ''}
onChange={(v) => updateStop(index, 'plannedArrivalTime', v)}
placeholder="Arr time"
label="Planned Arrival"
/>
</div>
<div className="w-44">
<DateTimePicker
value={stop.plannedDepartureTime ?? ''}
onChange={(v) => updateStop(index, 'plannedDepartureTime', v)}
placeholder="Dep time"
label="Planned Departure"
/>
</div>
<button
type="button"
onClick={() => removeStop(index)}
@@ -841,7 +790,7 @@ export default function RoutesPage() {
<span className="text-muted-foreground">Select destination station above</span>
)}
</div>
<div className="w-24">
<div className="w-28">
{destinationStationId && (
<input
type="number"
@@ -854,18 +803,7 @@ export default function RoutesPage() {
/>
)}
</div>
<div className="w-44">
{destinationStationId && (
<DateTimePicker
value={destinationArrivalTime}
onChange={setDestinationArrivalTime}
placeholder="Arr time"
label="Planned Arrival"
/>
)}
</div>
<div className="w-44" />
<div className="w-24">
<div className="w-28">
{destinationStationId && (
<input
type="number"

File diff suppressed because it is too large Load Diff