Bladeren bron

truckdashboard update

production
tommy 3 uur geleden
bovenliggende
commit
0c82a8c79b
1 gewijzigde bestanden met toevoegingen van 98 en 104 verwijderingen
  1. +98
    -104
      src/components/DashboardPage/truckSchedule/TruckScheduleDashboard.tsx

+ 98
- 104
src/components/DashboardPage/truckSchedule/TruckScheduleDashboard.tsx Bestand weergeven

@@ -203,87 +203,91 @@ const TruckScheduleDashboard: React.FC = () => {
return '-';
};

// Calculate time remaining for truck departure
const calculateTimeRemaining = useCallback((item: TruckScheduleDashboardItem, dateOption: string): string => {
// If all tickets are completed, return the difference between ETD and last ticket end time
if (item.numberOfPickTickets > 0 && item.numberOfTicketsCompleted >= item.numberOfPickTickets) {
const lastTicketEndTime = item.lastTicketEndTime;
const departureTime = item.truckDepartureTime;
if (!lastTicketEndTime || !departureTime) return '-';
// Parse last ticket end time
let lastEndDayjs: dayjs.Dayjs;
if (Array.isArray(lastTicketEndTime)) {
lastEndDayjs = arrayToDayjs(lastTicketEndTime, true);
} else if (typeof lastTicketEndTime === 'string') {
lastEndDayjs = dayjs(lastTicketEndTime);
if (!lastEndDayjs.isValid()) return '-';
// Compare a timestamp against the selected date (today/tomorrow/...) and return a short label.
// Used to avoid confusion when picking crosses midnight.
const relativeDayLabel = useCallback(
(dateTimeData: string | number[] | null, dateOption: string): string | null => {
if (!dateTimeData) return null;
const dateOffset = getDateOffset(dateOption);
const baseDate = dayjs().startOf('day').add(dateOffset, 'day');

let dt: dayjs.Dayjs;
if (Array.isArray(dateTimeData)) {
dt = arrayToDayjs(dateTimeData, true);
} else {
return '-';
dt = dayjs(dateTimeData);
}
// Parse departure time
if (!dt.isValid()) return null;

const diffDays = dt.startOf('day').diff(baseDate, 'day');
if (diffDays === 0) return null;
if (diffDays === -1) return '昨日';
if (diffDays === 1) return '明日';
if (diffDays <= -2) return `${Math.abs(diffDays)}日前`;
return `${diffDays}日後`;
},
[],
);

const getDepartureEtdDayjs = useCallback(
(departureTime: string | number[] | null, dateOption: string): dayjs.Dayjs | null => {
if (!departureTime) return null;
const dateOffset = getDateOffset(dateOption);
const baseDate = dayjs().add(dateOffset, 'day');
let departureDayjs: dayjs.Dayjs;
const baseDate = dayjs().startOf('day').add(dateOffset, 'day');

let hour: number;
let minute: number;

if (Array.isArray(departureTime)) {
if (departureTime.length < 2) return '-';
const hour = departureTime[0] || 0;
const minute = departureTime[1] || 0;
departureDayjs = baseDate.hour(hour).minute(minute).second(0);
if (departureTime.length < 2) return null;
hour = departureTime[0] || 0;
minute = departureTime[1] || 0;
} else if (typeof departureTime === 'string') {
const parts = departureTime.split(':');
if (parts.length < 2) return '-';
const hour = parseInt(parts[0], 10);
const minute = parseInt(parts[1], 10);
departureDayjs = baseDate.hour(hour).minute(minute).second(0);
if (parts.length < 2) return null;
hour = parseInt(parts[0], 10);
minute = parseInt(parts[1], 10);
} else {
return '-';
return null;
}
// Calculate difference: ETD - lastTicketEndTime
const diffMinutes = departureDayjs.diff(lastEndDayjs, 'minute');
if (diffMinutes < 0) {
// ETD is before last ticket end (negative difference)
const absDiff = Math.abs(diffMinutes);
const hours = Math.floor(absDiff / 60);
const minutes = absDiff % 60;
return `-${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
} else {
// ETD is after last ticket end (positive difference)
const hours = Math.floor(diffMinutes / 60);
const minutes = diffMinutes % 60;
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
}
}
const departureTime = item.truckDepartureTime;
if (!departureTime || !currentTime) return '-';
const now = currentTime;
let departureHour: number;
let departureMinute: number;
if (Array.isArray(departureTime)) {
if (departureTime.length < 2) return '-';
departureHour = departureTime[0] || 0;
departureMinute = departureTime[1] || 0;
} else if (typeof departureTime === 'string') {
const parts = departureTime.split(':');
if (parts.length < 2) return '-';
departureHour = parseInt(parts[0], 10);
departureMinute = parseInt(parts[1], 10);
} else {
return '-';

return baseDate.hour(hour).minute(minute).second(0);
},
[],
);

const getLastEndDayjsOrNull = useCallback((lastTicketEndTime: string | number[] | null): dayjs.Dayjs | null => {
if (!lastTicketEndTime) return null;
if (Array.isArray(lastTicketEndTime)) {
return arrayToDayjs(lastTicketEndTime, true);
}
// Create departure datetime for the selected date (today, tomorrow, or day after tomorrow)
const dateOffset = getDateOffset(dateOption);
const departure = now.clone().add(dateOffset, 'day').hour(departureHour).minute(departureMinute).second(0);
const diffMinutes = departure.diff(now, 'minute');
const d = dayjs(lastTicketEndTime);
return d.isValid() ? d : null;
}, []);

const getDiffMinutesForRemaining = useCallback(
(item: TruckScheduleDashboardItem, dateOption: string): number | null => {
if (!currentTime) return null;
const etd = getDepartureEtdDayjs(item.truckDepartureTime, dateOption);
if (!etd) return null;

const allDone =
item.numberOfTicketsReleased > 0 && item.numberOfTicketsCompleted >= item.numberOfTicketsReleased;
if (allDone) {
const lastEnd = getLastEndDayjsOrNull(item.lastTicketEndTime);
if (!lastEnd) return null;
return etd.diff(lastEnd, 'minute');
}

return etd.diff(currentTime, 'minute');
},
[currentTime, getDepartureEtdDayjs, getLastEndDayjsOrNull],
);

// Calculate time remaining for truck departure
const calculateTimeRemaining = useCallback((item: TruckScheduleDashboardItem, dateOption: string): string => {
const diffMinutes = getDiffMinutesForRemaining(item, dateOption);
if (diffMinutes === null) return '-';
if (diffMinutes < 0) {
// Past departure time
@@ -296,7 +300,7 @@ const TruckScheduleDashboard: React.FC = () => {
const minutes = diffMinutes % 60;
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
}
}, [currentTime]);
}, [getDiffMinutesForRemaining]);

// Generate unique key for tracking completed items
const getItemKey = (item: TruckScheduleDashboardItem): string => {
@@ -414,34 +418,12 @@ const TruckScheduleDashboard: React.FC = () => {
}, [allData, selectedDate, selectedStore]);

// Get chip color based on time remaining
const getTimeChipColor = (departureTime: string | number[] | null, dateOption: string): "success" | "warning" | "error" | "default" => {
if (!departureTime || !currentTime) return "default";
const now = currentTime;
let departureHour: number;
let departureMinute: number;
if (Array.isArray(departureTime)) {
if (departureTime.length < 2) return "default";
departureHour = departureTime[0] || 0;
departureMinute = departureTime[1] || 0;
} else if (typeof departureTime === 'string') {
const parts = departureTime.split(':');
if (parts.length < 2) return "default";
departureHour = parseInt(parts[0], 10);
departureMinute = parseInt(parts[1], 10);
} else {
return "default";
}
// Create departure datetime for the selected date (today, tomorrow, or day after tomorrow)
const dateOffset = getDateOffset(dateOption);
const departure = now.clone().add(dateOffset, 'day').hour(departureHour).minute(departureMinute).second(0);
const diffMinutes = departure.diff(now, 'minute');
if (diffMinutes < 0) return "error"; // Past due
if (diffMinutes <= 30) return "warning"; // Within 30 minutes
return "success"; // More than 30 minutes
const getTimeChipColor = (item: TruckScheduleDashboardItem, dateOption: string): "success" | "warning" | "error" | "default" => {
const diffMinutes = getDiffMinutesForRemaining(item, dateOption);
if (diffMinutes === null) return "default";
if (diffMinutes < 0) return "error";
if (diffMinutes < 30) return "warning";
return "success";
};

return (
@@ -535,7 +517,9 @@ const TruckScheduleDashboard: React.FC = () => {
) : (
filteredData.map((row, index) => {
const timeRemaining = calculateTimeRemaining(row, selectedDate);
const chipColor = getTimeChipColor(row.truckDepartureTime, selectedDate);
const chipColor = getTimeChipColor(row, selectedDate);
const startRel = relativeDayLabel(row.firstTicketStartTime, selectedDate);
const endRel = relativeDayLabel(row.lastTicketEndTime, selectedDate);
return (
<TableRow
@@ -597,10 +581,20 @@ const TruckScheduleDashboard: React.FC = () => {
</Typography>
</TableCell>
<TableCell>
{formatDateTime(row.firstTicketStartTime)}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
<Typography variant="body2">{formatDateTime(row.firstTicketStartTime)}</Typography>
{startRel && (
<Chip size="small" variant="outlined" color="warning" label={startRel} />
)}
</Box>
</TableCell>
<TableCell>
{formatDateTime(row.lastTicketEndTime)}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
<Typography variant="body2">{formatDateTime(row.lastTicketEndTime)}</Typography>
{endRel && (
<Chip size="small" variant="outlined" color="warning" label={endRel} />
)}
</Box>
</TableCell>
<TableCell align="right">
<Typography


Laden…
Annuleren
Opslaan