"use client";
import {
Autocomplete,
Badge,
Box,
Button,
CircularProgress,
Tab,
Tabs,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import React, { Suspense } from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import DoWorkbenchPickShell from "./DoWorkbenchPickShell";
import type { PrinterCombo } from "@/app/api/settings/printer";
import GoodPickExecutionWorkbenchRecord from "./GoodPickExecutionWorkbenchRecord";
import { useTranslation } from "react-i18next";
import WorkbenchTicketReleaseTableTab from "./WorkbenchTicketReleaseTable";
import { Stack } from "@mui/system";
import Swal from "sweetalert2";
import { printDNWorkbench } from "@/app/api/do/actions";
import {
fetchWorkbenchEtraLaneSummary,
fetchWorkbenchReleasedDoPickOrdersForSelectionToday,
type WorkbenchEtraShopLaneGroup,
} from "@/app/api/doworkbench/actions";
import FinishedGoodCartonDashboardTab from "../FinishedGoodSearch/FinishedGoodCartonDashboardTab";
import TruckRoutingSummaryTabWorkbench from "./TruckRoutingSummaryTabWorkbench";
const ALLOWED_WORKBENCH_TABS = new Set([0, 1, 2, 3, 4, 5, 6]);
/** Backend Etra summary: each lane `total` = distinct incomplete (`pending`/`released`) `delivery_order_pick_order` rows for that day. */
function sumIncompleteEtraDopoTickets(groups: WorkbenchEtraShopLaneGroup[]): number {
let n = 0;
for (const g of groups) {
for (const lane of g.lanes) {
n += Number(lane.total) || 0;
}
}
return n;
}
type Props = {
defaultTabIndex?: 0 | 1;
printerCombo?: PrinterCombo[];
};
function TabPanel(props: { value: number; index: number; children: React.ReactNode }) {
const { value, index, children } = props;
if (value !== index) return null;
return {children};
}
const DoWorkbenchTabsInner: React.FC = ({ defaultTabIndex = 0, printerCombo = [] }) => {
const searchParams = useSearchParams();
const router = useRouter();
const pathname = usePathname();
const urlTabStr = searchParams.get("tab");
const urlTicketRaw = searchParams.get("ticketNo");
const urlTicketNo =
urlTicketRaw && urlTicketRaw.trim() !== ""
? decodeURIComponent(urlTicketRaw.trim())
: null;
const urlTargetDateRaw = searchParams.get("targetDate");
const urlTargetDate =
urlTargetDateRaw && urlTargetDateRaw.trim() !== ""
? decodeURIComponent(urlTargetDateRaw.trim())
: null;
const [tab, setTab] = React.useState(defaultTabIndex);
const [a4Printer, setA4Printer] = React.useState(null);
const [labelPrinter, setLabelPrinter] = React.useState(null);
const [releasedOrderCount, setReleasedOrderCount] = React.useState(0);
const [etraIncompleteDopoCount, setEtraIncompleteDopoCount] = React.useState(0);
const { t } = useTranslation( );
const a4Printers = React.useMemo(
() => (printerCombo || []).filter((printer) => printer.type === "A4"),
[printerCombo],
);
const labelPrinters = React.useMemo(
() => (printerCombo || []).filter((printer) => printer.type === "Label"),
[printerCombo],
);
const refreshWorkbenchCounts = React.useCallback(async () => {
const [releasedRes, etraRes] = await Promise.allSettled([
fetchWorkbenchReleasedDoPickOrdersForSelectionToday(),
fetchWorkbenchEtraLaneSummary(),
]);
if (releasedRes.status === "fulfilled") {
setReleasedOrderCount(releasedRes.value.length);
} else {
console.error("Error fetching workbench released order count:", releasedRes.reason);
setReleasedOrderCount(0);
}
if (etraRes.status === "fulfilled") {
setEtraIncompleteDopoCount(sumIncompleteEtraDopoTickets(etraRes.value));
} else {
console.error("Error fetching workbench Etra incomplete count:", etraRes.reason);
setEtraIncompleteDopoCount(0);
}
}, []);
React.useEffect(() => {
void refreshWorkbenchCounts();
}, [refreshWorkbenchCounts]);
React.useEffect(() => {
const onAssigned = () => {
void refreshWorkbenchCounts();
};
window.addEventListener("pickOrderAssigned", onAssigned);
return () => window.removeEventListener("pickOrderAssigned", onAssigned);
}, [refreshWorkbenchCounts]);
/** Opening Etra tab refreshes badge (completion does not always dispatch `pickOrderAssigned`). */
const etraTabMountSkipRef = React.useRef(false);
React.useEffect(() => {
if (!etraTabMountSkipRef.current) {
etraTabMountSkipRef.current = true;
return;
}
if (tab === 1) void refreshWorkbenchCounts();
}, [tab, refreshWorkbenchCounts]);
React.useEffect(() => {
if (urlTabStr == null || urlTabStr === "") return;
const n = parseInt(urlTabStr, 10);
if (!Number.isNaN(n) && ALLOWED_WORKBENCH_TABS.has(n)) {
setTab(n);
}
}, [urlTabStr]);
const handleTabChange = React.useCallback(
(_: React.SyntheticEvent, newTab: number) => {
setTab(newTab);
const params = new URLSearchParams(searchParams.toString());
params.set("tab", String(newTab));
/* ticketNo / targetDate deep-link only for "Finished Good Record" (mine) */
if (newTab !== 2) {
params.delete("ticketNo");
params.delete("targetDate");
}
const qs = params.toString();
router.replace(qs ? `${pathname}?${qs}` : pathname, { scroll: false });
},
[pathname, router, searchParams],
);
const handleAllDraft = React.useCallback(async () => {
try {
if (!a4Printer) {
await Swal.fire({
position: "bottom-end",
icon: "warning",
text: t("Please select a printer first"),
showConfirmButton: false,
timer: 1500,
});
return;
}
const releasedOrders = await fetchWorkbenchReleasedDoPickOrdersForSelectionToday();
if (releasedOrders.length === 0) {
await Swal.fire({
title: "",
text: t("No released pick order records found."),
icon: "info",
});
return;
}
const confirmResult = await Swal.fire({
title: t("Batch Print"),
text: `${t("Confirm print: (")}${releasedOrders.length}${t("piece(s))")}`,
icon: "question",
showCancelButton: true,
confirmButtonText: t("Confirm"),
cancelButtonText: t("Cancel"),
confirmButtonColor: "#8dba00",
cancelButtonColor: "#F04438",
});
if (!confirmResult.isConfirmed) return;
Swal.fire({
title: t("Printing..."),
text: t("Please wait..."),
allowOutsideClick: false,
allowEscapeKey: false,
didOpen: () => Swal.showLoading(),
});
for (const order of releasedOrders) {
const printRequest = {
printerId: a4Printer.id,
printQty: 1,
isDraft: true,
numOfCarton: 0,
deliveryOrderPickOrderId: order.id,
};
const response = await printDNWorkbench(printRequest);
if (!response.success) {
console.error(`Workbench print draft failed for deliveryOrderPickOrderId ${order.id}:`, response.message);
}
}
Swal.close();
await Swal.fire({
position: "bottom-end",
icon: "success",
text: t("Printed Successfully."),
showConfirmButton: false,
timer: 1500,
});
await refreshWorkbenchCounts();
} catch (error) {
Swal.close();
console.error("Error in workbench handleAllDraft:", error);
await Swal.fire({
icon: "error",
text: t("An error occurred during batch print"),
});
}
}, [a4Printer, t, refreshWorkbenchCounts]);
return (
{t("A4 Printer")}:
option.name || option.label || option.code || `Printer ${option.id}`}
value={a4Printer}
onChange={(_, newValue) => setA4Printer(newValue)}
sx={{ minWidth: 200 }}
size="small"
renderInput={(params) => (
)}
/>
{t("Label Printer")}:
option.name || option.label || option.code || `Printer ${option.id}`}
value={labelPrinter}
onChange={(_, newValue) => setLabelPrinter(newValue)}
sx={{ minWidth: 200 }}
size="small"
renderInput={(params) => (
)}
/>
99 ? 5 : etraIncompleteDopoCount > 0 ? 4 : 2,
}}
label={
0
? t("Etra incomplete badge tooltip", { count: etraIncompleteDopoCount })
: t("Etra incomplete badge tooltip none")
}
>
99 ? "99+" : etraIncompleteDopoCount}
invisible={etraIncompleteDopoCount === 0}
sx={{
"& .MuiBadge-badge": {
fontWeight: 800,
fontSize: "0.7rem",
minWidth: 18,
height: 18,
lineHeight: "18px",
px: 0.5,
right: -8,
top: 2,
},
}}
>
0 ? 1 : 0 }}
>
{t("Etra Pick Order Detail")}
}
/>
);
};
const DoWorkbenchTabs: React.FC = (props) => (
}
>
);
export default DoWorkbenchTabs;