|
- "use client";
-
- import {
- Alert,
- Button,
- Chip,
- Paper,
- Stack,
- TextField,
- Typography,
- } from "@mui/material";
- import QrCodeScannerIcon from "@mui/icons-material/QrCodeScanner";
- import SearchIcon from "@mui/icons-material/Search";
- import { useCallback, useEffect, useState } from "react";
- import { useTranslation } from "react-i18next";
- import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider";
-
- type ScanBarProps = {
- onTrace: (params: {
- stockInLineId?: number;
- lotNo?: string;
- itemCode?: string;
- }) => void;
- loading: boolean;
- lastLotNo?: string;
- };
-
- /** FP-MTMS Version Checklist | Functions Ref. No. 12 | v1.0.0 | 2026-07-17 */
- const ItemTracingScanBar: React.FC<ScanBarProps> = ({
- onTrace,
- loading,
- lastLotNo,
- }) => {
- const { t } = useTranslation("itemTracing");
- const scanner = useQrCodeScannerContext();
- const [scanMode, setScanMode] = useState<"idle" | "wedge">("idle");
- const [itemCode, setItemCode] = useState("");
- const [lotNo, setLotNo] = useState("");
- const [scanError, setScanError] = useState<string | null>(null);
-
- const startWedgeScan = useCallback(() => {
- setScanError(null);
- setScanMode("wedge");
- scanner.resetScan();
- scanner.startScan();
- }, [scanner]);
-
- const stopWedgeScan = useCallback(() => {
- scanner.stopScan();
- scanner.resetScan();
- setScanMode("idle");
- }, [scanner]);
-
- useEffect(() => {
- if (scanMode !== "wedge") return;
- const itemId = scanner.result?.itemId;
- const stockInLineId = scanner.result?.stockInLineId;
- if (!itemId || !stockInLineId) return;
- setScanError(null);
- stopWedgeScan();
- onTrace({ stockInLineId: Number(stockInLineId) });
- }, [scanMode, scanner.result, onTrace, stopWedgeScan]);
-
- const handleManualSearch = () => {
- const code = itemCode.trim();
- const lot = lotNo.trim();
- if (!code || !lot) return;
- onTrace({ itemCode: code, lotNo: lot });
- };
-
- return (
- <Paper variant="outlined" sx={{ p: 2 }}>
- <Stack spacing={2}>
- <Stack
- direction={{ xs: "column", sm: "row" }}
- spacing={1}
- alignItems={{ sm: "center" }}
- >
- <Button
- variant={scanMode === "wedge" ? "contained" : "outlined"}
- startIcon={<QrCodeScannerIcon />}
- onClick={scanMode === "wedge" ? stopWedgeScan : startWedgeScan}
- disabled={loading}
- >
- {scanMode === "wedge" ? t("scanning") : t("scanAgain")}
- </Button>
- {lastLotNo && (
- <Chip
- label={lastLotNo}
- color="primary"
- variant="outlined"
- sx={{ ml: { sm: "auto" } }}
- />
- )}
- </Stack>
-
- {scanError && (
- <Alert severity="warning" onClose={() => setScanError(null)}>
- {scanError}
- </Alert>
- )}
-
- {scanMode === "wedge" && (
- <Alert severity="info" onClose={stopWedgeScan}>
- {t("scanReady")}
- </Alert>
- )}
-
- <Typography variant="subtitle2">{t("manualSearch")}</Typography>
- <Stack direction={{ xs: "column", sm: "row" }} spacing={1}>
- <TextField
- size="small"
- label={t("itemCode")}
- value={itemCode}
- onChange={(e) => setItemCode(e.target.value)}
- disabled={loading}
- fullWidth
- />
- <TextField
- size="small"
- label={t("lotNo")}
- value={lotNo}
- onChange={(e) => setLotNo(e.target.value)}
- disabled={loading}
- fullWidth
- />
- <Button
- variant="contained"
- startIcon={<SearchIcon />}
- onClick={handleManualSearch}
- disabled={loading || !itemCode.trim() || !lotNo.trim()}
- sx={{ minWidth: 120 }}
- >
- {loading ? t("searching") : t("search")}
- </Button>
- </Stack>
- </Stack>
- </Paper>
- );
- };
-
- export default ItemTracingScanBar;
|