From 9b9d31e4c42132389ff9843b6b3ff826e35a9ff1 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Tue, 19 May 2026 16:33:36 +0800 Subject: [PATCH] doworkbench ticket select keep --- .../DoWorkbench/DoWorkbenchPickShell.tsx | 11 ++++++- .../DoWorkbench/DoWorkbenchTabs.tsx | 19 +++++++++-- .../DoWorkbench/WorkbenchFloorLanePanel.tsx | 33 +++++++++++++++---- .../DoWorkbench/workbenchLanePanelPrefs.ts | 23 +++++++++++++ src/i18n/en/inventory.json | 2 ++ src/i18n/zh/inventory.json | 2 ++ 6 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 src/components/DoWorkbench/workbenchLanePanelPrefs.ts diff --git a/src/components/DoWorkbench/DoWorkbenchPickShell.tsx b/src/components/DoWorkbench/DoWorkbenchPickShell.tsx index ed643b5..078a782 100644 --- a/src/components/DoWorkbench/DoWorkbenchPickShell.tsx +++ b/src/components/DoWorkbench/DoWorkbenchPickShell.tsx @@ -10,18 +10,25 @@ import { } from "@/app/api/pickOrder/actions"; import WorkbenchFloorLanePanel from "./WorkbenchFloorLanePanel"; import WorkbenchGoodPickExecutionDetail from "./WorkbenchGoodPickExecutionDetail"; +import type { WorkbenchLanePanelPrefs } from "./workbenchLanePanelPrefs"; export type DoWorkbenchPickShellLaneMode = "normal" | "etra"; type DoWorkbenchPickShellProps = { /** Tab 0: normal 2F/4F lane grid; tab 1: Etra-only lane grid */ laneMode?: DoWorkbenchPickShellLaneMode; + lanePanelPrefs: WorkbenchLanePanelPrefs; + onLanePanelPrefsChange: (prefs: WorkbenchLanePanelPrefs) => void; }; /** * FG workbench: 未指派顯示樓層/車線指派;已指派顯示揀貨明細(workbench API)。 */ -const DoWorkbenchPickShell: React.FC = ({ laneMode = "normal" }) => { +const DoWorkbenchPickShell: React.FC = ({ + laneMode = "normal", + lanePanelPrefs, + onLanePanelPrefsChange, +}) => { const { data: session, status } = useSession() as { data: SessionWithTokens | null; status: "loading" | "authenticated" | "unauthenticated"; @@ -104,6 +111,8 @@ const DoWorkbenchPickShell: React.FC = ({ laneMode = onPickOrderAssigned={() => void refreshWorkbenchView()} etraOnly={laneMode === "etra"} onRequestNormalLaneTab={laneMode === "etra" ? goNormalAssignTab : undefined} + lanePanelPrefs={lanePanelPrefs} + onLanePanelPrefsChange={onLanePanelPrefsChange} /> ) : ( = ({ defaultTabIndex = 0, printerCom : null; const [tab, setTab] = React.useState(defaultTabIndex); + const [lanePanelPrefs, setLanePanelPrefs] = React.useState( + DEFAULT_WORKBENCH_LANE_PANEL_PREFS, + ); const [a4Printer, setA4Printer] = React.useState(null); const [labelPrinter, setLabelPrinter] = React.useState(null); const [releasedOrderCount, setReleasedOrderCount] = React.useState(0); @@ -356,10 +363,18 @@ const DoWorkbenchTabsInner: React.FC = ({ defaultTabIndex = 0, printerCom - + - + void; @@ -27,6 +31,9 @@ interface Props { etraOnly?: boolean; /** With [etraOnly], navigates to normal assign tab (tab 0). */ onRequestNormalLaneTab?: () => void; + /** Lifted from DoWorkbenchTabs — persists date/floor/release across workbench tab switches. */ + lanePanelPrefs?: WorkbenchLanePanelPrefs; + onLanePanelPrefsChange?: (prefs: WorkbenchLanePanelPrefs) => void; } type LaneSlot4F = { truckDepartureTime: string; lane: LaneBtn }; @@ -38,6 +45,8 @@ const WorkbenchFloorLanePanel: React.FC = ({ initialReleaseType = "batch", etraOnly = false, onRequestNormalLaneTab, + lanePanelPrefs: lanePanelPrefsProp, + onLanePanelPrefsChange, }) => { const { t } = useTranslation("pickOrder"); const { data: session } = useSession() as { data: SessionWithTokens | null }; @@ -54,9 +63,21 @@ const WorkbenchFloorLanePanel: React.FC = ({ const [isAssigning, setIsAssigning] = useState(false); const [isDefaultTruck, setIsDefaultTruck] = useState(false); const [beforeTodayTruckXCount, setBeforeTodayTruckXCount] = useState(0); - const [selectedDate, setSelectedDate] = useState("today"); - const [releaseType, setReleaseType] = useState(initialReleaseType); - const [ticketFloor, setTicketFloor] = useState<"2/F" | "4/F">("2/F"); + const [internalLanePrefs, setInternalLanePrefs] = useState(() => ({ + ...DEFAULT_WORKBENCH_LANE_PANEL_PREFS, + releaseType: initialReleaseType, + })); + const lanePanelPrefs = lanePanelPrefsProp ?? internalLanePrefs; + const setLanePanelPrefs = onLanePanelPrefsChange ?? setInternalLanePrefs; + const selectedDate = lanePanelPrefs.selectedDate; + const releaseType = lanePanelPrefs.releaseType; + const ticketFloor = lanePanelPrefs.ticketFloor; + const patchLanePanelPrefs = useCallback( + (patch: Partial) => { + setLanePanelPrefs({ ...lanePanelPrefs, ...patch }); + }, + [lanePanelPrefs, setLanePanelPrefs], + ); const [isExtraView, setisExtraView] = useState(false); const [etraGroups, setEtraGroups] = useState([]); const [isLoadingEtra, setIsLoadingEtra] = useState(false); @@ -364,7 +385,7 @@ const WorkbenchFloorLanePanel: React.FC = ({ {t("Select Date")} - patchLanePanelPrefs({ selectedDate: e.target.value as WorkbenchLanePanelPrefs["selectedDate"] })}> {t("Today")} ({getDateLabel(0)}) {t("Tomorrow")} ({getDateLabel(1)}) {t("Day After Tomorrow")} ({getDateLabel(2)}) @@ -376,7 +397,7 @@ const WorkbenchFloorLanePanel: React.FC = ({ {t("Release Type")} - patchLanePanelPrefs({ releaseType: e.target.value })}> {t("Batch")} {t("Single")} @@ -385,7 +406,7 @@ const WorkbenchFloorLanePanel: React.FC = ({ {t("Floor ticket")} - patchLanePanelPrefs({ ticketFloor: e.target.value as WorkbenchLanePanelPrefs["ticketFloor"] })}> {t("2F ticket")} {t("4F ticket")} diff --git a/src/components/DoWorkbench/workbenchLanePanelPrefs.ts b/src/components/DoWorkbench/workbenchLanePanelPrefs.ts new file mode 100644 index 0000000..5e83df9 --- /dev/null +++ b/src/components/DoWorkbench/workbenchLanePanelPrefs.ts @@ -0,0 +1,23 @@ +export type WorkbenchLaneDateKey = "today" | "tomorrow" | "dayAfterTomorrow"; +export type WorkbenchLaneFloor = "2/F" | "4/F"; + +/** Tab 0/1 lane assignment filters — lifted to DoWorkbenchTabs so they survive tab switches. */ +export type WorkbenchLanePanelPrefs = { + selectedDate: WorkbenchLaneDateKey; + ticketFloor: WorkbenchLaneFloor; + releaseType: string; +}; + +export const DEFAULT_WORKBENCH_LANE_PANEL_PREFS: WorkbenchLanePanelPrefs = { + selectedDate: "today", + ticketFloor: "2/F", + releaseType: "batch", +}; + +export function isWorkbenchLaneDateKey(v: string): v is WorkbenchLaneDateKey { + return v === "today" || v === "tomorrow" || v === "dayAfterTomorrow"; +} + +export function isWorkbenchLaneFloor(v: string): v is WorkbenchLaneFloor { + return v === "2/F" || v === "4/F"; +} diff --git a/src/i18n/en/inventory.json b/src/i18n/en/inventory.json index 748bbbe..1939d18 100644 --- a/src/i18n/en/inventory.json +++ b/src/i18n/en/inventory.json @@ -15,6 +15,8 @@ "Remove": "Remove", "Create Stock Take (Select Sections)": "Create stock take (select sections)", "Select stock take sections to create hint": "Choose warehouse stock take sections to start a new round (selected sections share one new round id in this batch).", + "Stock take round name": "Stock take round name", + "Stock take round name placeholder": "Optional, e.g. May full-site stock take", "Select sections placeholder": "Select one or more", "Select all sections": "Select all sections", "Clear selection": "Clear selection", diff --git a/src/i18n/zh/inventory.json b/src/i18n/zh/inventory.json index 57e78c8..9e80f0e 100644 --- a/src/i18n/zh/inventory.json +++ b/src/i18n/zh/inventory.json @@ -131,6 +131,8 @@ "Create Stock Take for All Sections": "為所有區域創建盤點", "Create Stock Take (Select Sections)": "建立盤點(選擇區域)", "Select stock take sections to create hint": "請選擇要建立新盤點輪次的盤點區域(同一批次將共用同一輪次編號)。", + "Stock take round name": "盤點輪次名稱", + "Stock take round name placeholder": "選填,例如:五月全廠盤點", "Select sections placeholder": "可多選", "Select all sections": "全選區域", "Clear selection": "清除選取",