mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Seat block issue resolution
This commit is contained in:
@@ -224,16 +224,27 @@ export class SeatsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const availability = await this.segmentsService.getSeatAvailabilityMap(
|
const [availability, persistedSeats] = await Promise.all([
|
||||||
scheduleId, seatIds, stopTimes, reqFrom, reqTo, journeyDirection || JourneyDirection.ONE_WAY,
|
this.segmentsService.getSeatAvailabilityMap(
|
||||||
);
|
scheduleId, seatIds, stopTimes, reqFrom, reqTo, journeyDirection || JourneyDirection.ONE_WAY,
|
||||||
|
),
|
||||||
|
this.prisma.seat.findMany({
|
||||||
|
where: { id: { in: seatIds } },
|
||||||
|
select: { id: true, status: true },
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const persistedStatus = new Map(persistedSeats.map(s => [s.id, s.status]));
|
||||||
|
|
||||||
// Every requested seat defaults to AVAILABLE — this also guards against a stale
|
|
||||||
// persisted Seat.status column (e.g. a leftover 'BOOKED'/'BLOCKED' value) bleeding
|
|
||||||
// through getSeatMap's own fallback, since that fallback only triggers when this
|
|
||||||
// map has no entry at all for a given seat.
|
|
||||||
for (const seatId of seatIds) {
|
for (const seatId of seatIds) {
|
||||||
statusMap.set(seatId, availability.get(seatId) ?? 'AVAILABLE');
|
const persisted = persistedStatus.get(seatId);
|
||||||
|
// BLOCKED and UNDER_MAINTENANCE are cross-schedule flags set by admins —
|
||||||
|
// always honour them regardless of hold/booking state.
|
||||||
|
if ((persisted as string) === 'BLOCKED' || (persisted as string) === 'UNDER_MAINTENANCE') {
|
||||||
|
statusMap.set(seatId, persisted!);
|
||||||
|
} else {
|
||||||
|
statusMap.set(seatId, availability.get(seatId) ?? 'AVAILABLE');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return statusMap;
|
return statusMap;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export default function SeatsPage() {
|
|||||||
queryKey: ['seatmap', selectedSchedule],
|
queryKey: ['seatmap', selectedSchedule],
|
||||||
queryFn: () => selectedSchedule ? seatsApi.getSeatMap(selectedSchedule) : Promise.resolve(null),
|
queryFn: () => selectedSchedule ? seatsApi.getSeatMap(selectedSchedule) : Promise.resolve(null),
|
||||||
enabled: !!selectedSchedule,
|
enabled: !!selectedSchedule,
|
||||||
|
staleTime: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: coachTypesData } = useQuery({
|
const { data: coachTypesData } = useQuery({
|
||||||
@@ -49,6 +50,7 @@ export default function SeatsPage() {
|
|||||||
|
|
||||||
const { data: routeCoachesData, isLoading: routeCoachesLoading } = useQuery({
|
const { data: routeCoachesData, isLoading: routeCoachesLoading } = useQuery({
|
||||||
queryKey: ['routeCoaches', selectedRoute],
|
queryKey: ['routeCoaches', selectedRoute],
|
||||||
|
staleTime: 0,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (!selectedRoute) return null;
|
if (!selectedRoute) return null;
|
||||||
const template: any[] = await routeCoachTemplatesApi.get(selectedRoute);
|
const template: any[] = await routeCoachTemplatesApi.get(selectedRoute);
|
||||||
@@ -79,10 +81,15 @@ export default function SeatsPage() {
|
|||||||
enabled: !!selectedRoute,
|
enabled: !!selectedRoute,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const invalidateSeatData = () => {
|
||||||
|
queryClient.refetchQueries({ queryKey: ['seatmap', selectedSchedule] });
|
||||||
|
queryClient.refetchQueries({ queryKey: ['routeCoaches', selectedRoute] });
|
||||||
|
};
|
||||||
|
|
||||||
const blockMutation = useMutation({
|
const blockMutation = useMutation({
|
||||||
mutationFn: ({ seatId, reason }: any) => seatsApi.block(seatId, { reason }),
|
mutationFn: ({ seatId, reason }: any) => seatsApi.block(seatId, { reason }),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['seatmap'] });
|
invalidateSeatData();
|
||||||
setShowBlockModal(false);
|
setShowBlockModal(false);
|
||||||
setSelectedSeat(null);
|
setSelectedSeat(null);
|
||||||
setBlockReason('');
|
setBlockReason('');
|
||||||
@@ -92,14 +99,14 @@ export default function SeatsPage() {
|
|||||||
const unblockMutation = useMutation({
|
const unblockMutation = useMutation({
|
||||||
mutationFn: (seatId: string) => seatsApi.unblock(seatId),
|
mutationFn: (seatId: string) => seatsApi.unblock(seatId),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['seatmap'] });
|
invalidateSeatData();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const removeSeatMutation = useMutation({
|
const removeSeatMutation = useMutation({
|
||||||
mutationFn: (seatId: string) => seatsApi.removeSeat(seatId),
|
mutationFn: (seatId: string) => seatsApi.removeSeat(seatId),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['seatmap'] });
|
invalidateSeatData();
|
||||||
setShowRemoveModal(false);
|
setShowRemoveModal(false);
|
||||||
setSelectedSeat(null);
|
setSelectedSeat(null);
|
||||||
},
|
},
|
||||||
@@ -108,7 +115,7 @@ export default function SeatsPage() {
|
|||||||
const undoRemoveMutation = useMutation({
|
const undoRemoveMutation = useMutation({
|
||||||
mutationFn: (seatId: string) => seatsApi.undoRemove(seatId),
|
mutationFn: (seatId: string) => seatsApi.undoRemove(seatId),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['seatmap'] });
|
invalidateSeatData();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -116,7 +123,7 @@ export default function SeatsPage() {
|
|||||||
mutationFn: ({ seatId, reason }: { seatId: string; reason: string }) =>
|
mutationFn: ({ seatId, reason }: { seatId: string; reason: string }) =>
|
||||||
seatsApi.setMaintenance(seatId, reason),
|
seatsApi.setMaintenance(seatId, reason),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['seatmap'] });
|
invalidateSeatData();
|
||||||
setShowMaintenanceModal(false);
|
setShowMaintenanceModal(false);
|
||||||
setSelectedSeat(null);
|
setSelectedSeat(null);
|
||||||
setMaintenanceReason('');
|
setMaintenanceReason('');
|
||||||
@@ -125,7 +132,7 @@ export default function SeatsPage() {
|
|||||||
|
|
||||||
const clearMaintenanceMutation = useMutation({
|
const clearMaintenanceMutation = useMutation({
|
||||||
mutationFn: (seatId: string) => seatsApi.clearMaintenance(seatId),
|
mutationFn: (seatId: string) => seatsApi.clearMaintenance(seatId),
|
||||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['seatmap'] }),
|
onSuccess: () => invalidateSeatData(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const schedules = schedulesData?.items || schedulesData?.data || [];
|
const schedules = schedulesData?.items || schedulesData?.data || [];
|
||||||
@@ -139,7 +146,7 @@ export default function SeatsPage() {
|
|||||||
return Promise.all(seatIds.map((seatId: string) => seatsApi.block(seatId, { reason })));
|
return Promise.all(seatIds.map((seatId: string) => seatsApi.block(seatId, { reason })));
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['seatmap'] });
|
invalidateSeatData();
|
||||||
setShowBlockCoachModal(false);
|
setShowBlockCoachModal(false);
|
||||||
setSelectedCoach(null);
|
setSelectedCoach(null);
|
||||||
setBlockCoachReason('');
|
setBlockCoachReason('');
|
||||||
@@ -153,7 +160,7 @@ export default function SeatsPage() {
|
|||||||
return Promise.all(seatIds.map((seatId: string) => seatsApi.unblock(seatId)));
|
return Promise.all(seatIds.map((seatId: string) => seatsApi.unblock(seatId)));
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['seatmap'] });
|
invalidateSeatData();
|
||||||
setShowUnblockCoachModal(false);
|
setShowUnblockCoachModal(false);
|
||||||
setCoachToUnblock(null);
|
setCoachToUnblock(null);
|
||||||
},
|
},
|
||||||
@@ -1015,7 +1022,7 @@ function SeatIcon({
|
|||||||
const color = getSeatColor(status);
|
const color = getSeatColor(status);
|
||||||
const canBlock = status === 'AVAILABLE';
|
const canBlock = status === 'AVAILABLE';
|
||||||
const canUnblock = status === 'BLOCKED';
|
const canUnblock = status === 'BLOCKED';
|
||||||
const canMaintenance = status === 'AVAILABLE' || status === 'BLOCKED';
|
const canMaintenance = false;
|
||||||
const canClearMaintenance = status === 'UNDER_MAINTENANCE';
|
const canClearMaintenance = status === 'UNDER_MAINTENANCE';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user