|
|
@@ -49,6 +49,18 @@ function requiredDeliveryDateToDayString(value: unknown): string { |
|
|
return dayjs(value as string | number | Date).format("YYYY-MM-DD"); |
|
|
return dayjs(value as string | number | Date).format("YYYY-MM-DD"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function formatTicketDateTime(value: unknown): string { |
|
|
|
|
|
if (!value) return "-"; |
|
|
|
|
|
if (Array.isArray(value)) { |
|
|
|
|
|
return arrayToDayjs(value as number[], true).format("HH:mm"); |
|
|
|
|
|
} |
|
|
|
|
|
const parsedDate = dayjs(value as string, "YYYYMMDDHHmmss"); |
|
|
|
|
|
if (!parsedDate.isValid()) { |
|
|
|
|
|
return dayjs(value as string | number | Date).format("HH:mm"); |
|
|
|
|
|
} |
|
|
|
|
|
return parsedDate.format("HH:mm"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
function isCompletedStatus(status: string | null | undefined): boolean { |
|
|
function isCompletedStatus(status: string | null | undefined): boolean { |
|
|
return (status ?? "").toLowerCase() === "completed"; |
|
|
return (status ?? "").toLowerCase() === "completed"; |
|
|
} |
|
|
} |
|
|
@@ -71,6 +83,8 @@ const WorkbenchTicketReleaseTableTab: React.FC = () => { |
|
|
const [selectedStatus, setSelectedStatus] = useState<string>("released"); |
|
|
const [selectedStatus, setSelectedStatus] = useState<string>("released"); |
|
|
const [data, setData] = useState<WorkbenchTicketReleaseTable[]>([]); |
|
|
const [data, setData] = useState<WorkbenchTicketReleaseTable[]>([]); |
|
|
const [loading, setLoading] = useState<boolean>(true); |
|
|
const [loading, setLoading] = useState<boolean>(true); |
|
|
|
|
|
const [now, setNow] = useState(dayjs()); |
|
|
|
|
|
const [lastDataRefreshTime, setLastDataRefreshTime] = useState<dayjs.Dayjs | null>(null); |
|
|
const [paginationController, setPaginationController] = useState({ |
|
|
const [paginationController, setPaginationController] = useState({ |
|
|
pageNum: 0, |
|
|
pageNum: 0, |
|
|
pageSize: 5, |
|
|
pageSize: 5, |
|
|
@@ -82,6 +96,7 @@ const WorkbenchTicketReleaseTableTab: React.FC = () => { |
|
|
const dayStr = queryDate.format("YYYY-MM-DD"); |
|
|
const dayStr = queryDate.format("YYYY-MM-DD"); |
|
|
const result = await fetchWorkbenchTicketReleaseTable(dayStr, dayStr); |
|
|
const result = await fetchWorkbenchTicketReleaseTable(dayStr, dayStr); |
|
|
setData(result); |
|
|
setData(result); |
|
|
|
|
|
setLastDataRefreshTime(dayjs()); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error("Error fetching workbench ticket release table:", error); |
|
|
console.error("Error fetching workbench ticket release table:", error); |
|
|
setData([]); |
|
|
setData([]); |
|
|
@@ -92,8 +107,17 @@ const WorkbenchTicketReleaseTableTab: React.FC = () => { |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
useEffect(() => { |
|
|
void loadData(); |
|
|
void loadData(); |
|
|
|
|
|
const id = setInterval(() => { |
|
|
|
|
|
void loadData(); |
|
|
|
|
|
}, 5 * 60 * 1000); |
|
|
|
|
|
return () => clearInterval(id); |
|
|
}, [loadData]); |
|
|
}, [loadData]); |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
const tick = setInterval(() => setNow(dayjs()), 30 * 1000); |
|
|
|
|
|
return () => clearInterval(tick); |
|
|
|
|
|
}, []); |
|
|
|
|
|
|
|
|
const dayStr = queryDate.format("YYYY-MM-DD"); |
|
|
const dayStr = queryDate.format("YYYY-MM-DD"); |
|
|
const filteredData = useMemo(() => { |
|
|
const filteredData = useMemo(() => { |
|
|
return data.filter((item) => { |
|
|
return data.filter((item) => { |
|
|
@@ -231,6 +255,16 @@ const WorkbenchTicketReleaseTableTab: React.FC = () => { |
|
|
<MenuItem value="completed">{t("completed")}</MenuItem> |
|
|
<MenuItem value="completed">{t("completed")}</MenuItem> |
|
|
</Select> |
|
|
</Select> |
|
|
</FormControl> |
|
|
</FormControl> |
|
|
|
|
|
<Box sx={{ flexGrow: 1 }} /> |
|
|
|
|
|
<Stack direction="row" spacing={2} sx={{ flexShrink: 0, alignSelf: "center" }}> |
|
|
|
|
|
<Typography variant="body2" sx={{ color: "text.secondary" }} suppressHydrationWarning> |
|
|
|
|
|
{t("Now")}: {now.format("HH:mm")} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
<Typography variant="body2" sx={{ color: "text.secondary" }}> |
|
|
|
|
|
{t("Auto-refresh every 5 minutes")} | {t("Last updated")}:{" "} |
|
|
|
|
|
{lastDataRefreshTime ? lastDataRefreshTime.format("HH:mm:ss") : "--:--:--"} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
</Stack> |
|
|
</Stack> |
|
|
</Stack> |
|
|
|
|
|
|
|
|
{loading ? ( |
|
|
{loading ? ( |
|
|
@@ -240,17 +274,47 @@ const WorkbenchTicketReleaseTableTab: React.FC = () => { |
|
|
) : ( |
|
|
) : ( |
|
|
<> |
|
|
<> |
|
|
<TableContainer component={Paper} sx={{ maxHeight: 440, overflow: "auto" }}> |
|
|
<TableContainer component={Paper} sx={{ maxHeight: 440, overflow: "auto" }}> |
|
|
<Table size="small"> |
|
|
|
|
|
|
|
|
<Table size="small" sx={{ minWidth: 650 }}> |
|
|
<TableHead> |
|
|
<TableHead> |
|
|
<TableRow> |
|
|
|
|
|
|
|
|
<TableRow |
|
|
|
|
|
sx={{ |
|
|
|
|
|
position: "sticky", |
|
|
|
|
|
top: 0, |
|
|
|
|
|
zIndex: 1, |
|
|
|
|
|
backgroundColor: "grey.100", |
|
|
|
|
|
}} |
|
|
|
|
|
> |
|
|
<TableCell>{t("Store ID")}</TableCell> |
|
|
<TableCell>{t("Store ID")}</TableCell> |
|
|
<TableCell>{t("Required Delivery Date")}</TableCell> |
|
|
<TableCell>{t("Required Delivery Date")}</TableCell> |
|
|
<TableCell>{t("Truck Information")}</TableCell> |
|
|
|
|
|
<TableCell>{t("Shop Name")}</TableCell> |
|
|
|
|
|
|
|
|
<TableCell> |
|
|
|
|
|
<Box sx={{ display: "flex", flexDirection: "column", gap: 0.5 }}> |
|
|
|
|
|
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}> |
|
|
|
|
|
{t("Truck Information")} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
<Typography variant="caption" sx={{ color: "text.secondary" }}> |
|
|
|
|
|
{t("Truck Lane Code")} - {t("Departure Time")} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
</Box> |
|
|
|
|
|
</TableCell> |
|
|
|
|
|
<TableCell sx={{ minWidth: 200, width: "20%" }}>{t("Shop Name")}</TableCell> |
|
|
<TableCell align="right">{t("Loading Sequence")}</TableCell> |
|
|
<TableCell align="right">{t("Loading Sequence")}</TableCell> |
|
|
<TableCell>{t("Ticket Information")}</TableCell> |
|
|
|
|
|
|
|
|
<TableCell> |
|
|
|
|
|
<Box sx={{ display: "flex", flexDirection: "column", gap: 0.5 }}> |
|
|
|
|
|
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}> |
|
|
|
|
|
{t("Ticket Information")} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
<Typography variant="caption" sx={{ color: "text.secondary" }}> |
|
|
|
|
|
{t("Ticket No.")} ({t("Status")}) |
|
|
|
|
|
</Typography> |
|
|
|
|
|
<Typography variant="caption" sx={{ color: "text.secondary" }}> |
|
|
|
|
|
{t("Released Time")} - {t("Completed Time")} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
</Box> |
|
|
|
|
|
</TableCell> |
|
|
<TableCell>{t("Handler Name")}</TableCell> |
|
|
<TableCell>{t("Handler Name")}</TableCell> |
|
|
<TableCell align="right">{t("Number of FG Items (Order Item(s) Count)")}</TableCell> |
|
|
|
|
|
|
|
|
<TableCell align="right" sx={{ minWidth: 100, width: "8%", whiteSpace: "nowrap" }}> |
|
|
|
|
|
{t("Number of FG Items (Order Item(s) Count)")} |
|
|
|
|
|
</TableCell> |
|
|
<TableCell align="center" sx={{ minWidth: 200 }}> |
|
|
<TableCell align="center" sx={{ minWidth: 200 }}> |
|
|
{t("Actions")} |
|
|
{t("Actions")} |
|
|
</TableCell> |
|
|
</TableCell> |
|
|
@@ -276,13 +340,25 @@ const WorkbenchTicketReleaseTableTab: React.FC = () => { |
|
|
{row.truckDepartureTime && <Chip label={String(row.truckDepartureTime).slice(0, 5)} size="small" color="secondary" />} |
|
|
{row.truckDepartureTime && <Chip label={String(row.truckDepartureTime).slice(0, 5)} size="small" color="secondary" />} |
|
|
</Box> |
|
|
</Box> |
|
|
</TableCell> |
|
|
</TableCell> |
|
|
<TableCell>{row.shopName || "-"}</TableCell> |
|
|
|
|
|
|
|
|
<TableCell sx={{ minWidth: 200, width: "20%" }}>{row.shopName || "-"}</TableCell> |
|
|
<TableCell align="right">{row.loadingSequence ?? "-"}</TableCell> |
|
|
<TableCell align="right">{row.loadingSequence ?? "-"}</TableCell> |
|
|
<TableCell> |
|
|
<TableCell> |
|
|
{row.ticketNo || "-"} ({row.ticketStatus ? t(row.ticketStatus.toLowerCase()) : "-"}) |
|
|
|
|
|
|
|
|
<Box sx={{ display: "flex", flexDirection: "column", gap: 0.5 }}> |
|
|
|
|
|
<Typography variant="body2"> |
|
|
|
|
|
{row.ticketNo || "-"} ({row.ticketStatus ? t(row.ticketStatus.toLowerCase()) : "-"}) |
|
|
|
|
|
</Typography> |
|
|
|
|
|
<Typography variant="body2"> |
|
|
|
|
|
{t("Released Time")}: {formatTicketDateTime(row.ticketReleaseTime)} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
<Typography variant="body2"> |
|
|
|
|
|
{t("Completed Time")}: {formatTicketDateTime(row.ticketCompleteDateTime)} |
|
|
|
|
|
</Typography> |
|
|
|
|
|
</Box> |
|
|
</TableCell> |
|
|
</TableCell> |
|
|
<TableCell>{row.handlerName ?? "-"}</TableCell> |
|
|
<TableCell>{row.handlerName ?? "-"}</TableCell> |
|
|
<TableCell align="right">{row.numberOfFGItems ?? 0}</TableCell> |
|
|
|
|
|
|
|
|
<TableCell align="right" sx={{ minWidth: 100, width: "8%" }}> |
|
|
|
|
|
{row.numberOfFGItems ?? 0} |
|
|
|
|
|
</TableCell> |
|
|
<TableCell align="center"> |
|
|
<TableCell align="center"> |
|
|
{showDoPickOpsButtons(row) ? ( |
|
|
{showDoPickOpsButtons(row) ? ( |
|
|
<Stack direction="row" spacing={1} justifyContent="center" flexWrap="wrap" useFlexGap> |
|
|
<Stack direction="row" spacing={1} justifyContent="center" flexWrap="wrap" useFlexGap> |
|
|
|