FPSMS-frontend
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 

143 rindas
4.0 KiB

  1. "use client";
  2. import {
  3. Alert,
  4. Button,
  5. Chip,
  6. Paper,
  7. Stack,
  8. TextField,
  9. Typography,
  10. } from "@mui/material";
  11. import QrCodeScannerIcon from "@mui/icons-material/QrCodeScanner";
  12. import SearchIcon from "@mui/icons-material/Search";
  13. import { useCallback, useEffect, useState } from "react";
  14. import { useTranslation } from "react-i18next";
  15. import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider";
  16. type ScanBarProps = {
  17. onTrace: (params: {
  18. stockInLineId?: number;
  19. lotNo?: string;
  20. itemCode?: string;
  21. }) => void;
  22. loading: boolean;
  23. lastLotNo?: string;
  24. };
  25. /** FP-MTMS Version Checklist | Functions Ref. No. 12 | v1.0.0 | 2026-07-17 */
  26. const ItemTracingScanBar: React.FC<ScanBarProps> = ({
  27. onTrace,
  28. loading,
  29. lastLotNo,
  30. }) => {
  31. const { t } = useTranslation("itemTracing");
  32. const scanner = useQrCodeScannerContext();
  33. const [scanMode, setScanMode] = useState<"idle" | "wedge">("idle");
  34. const [itemCode, setItemCode] = useState("");
  35. const [lotNo, setLotNo] = useState("");
  36. const [scanError, setScanError] = useState<string | null>(null);
  37. const startWedgeScan = useCallback(() => {
  38. setScanError(null);
  39. setScanMode("wedge");
  40. scanner.resetScan();
  41. scanner.startScan();
  42. }, [scanner]);
  43. const stopWedgeScan = useCallback(() => {
  44. scanner.stopScan();
  45. scanner.resetScan();
  46. setScanMode("idle");
  47. }, [scanner]);
  48. useEffect(() => {
  49. if (scanMode !== "wedge") return;
  50. const itemId = scanner.result?.itemId;
  51. const stockInLineId = scanner.result?.stockInLineId;
  52. if (!itemId || !stockInLineId) return;
  53. setScanError(null);
  54. stopWedgeScan();
  55. onTrace({ stockInLineId: Number(stockInLineId) });
  56. }, [scanMode, scanner.result, onTrace, stopWedgeScan]);
  57. const handleManualSearch = () => {
  58. const code = itemCode.trim();
  59. const lot = lotNo.trim();
  60. if (!code || !lot) return;
  61. onTrace({ itemCode: code, lotNo: lot });
  62. };
  63. return (
  64. <Paper variant="outlined" sx={{ p: 2 }}>
  65. <Stack spacing={2}>
  66. <Stack
  67. direction={{ xs: "column", sm: "row" }}
  68. spacing={1}
  69. alignItems={{ sm: "center" }}
  70. >
  71. <Button
  72. variant={scanMode === "wedge" ? "contained" : "outlined"}
  73. startIcon={<QrCodeScannerIcon />}
  74. onClick={scanMode === "wedge" ? stopWedgeScan : startWedgeScan}
  75. disabled={loading}
  76. >
  77. {scanMode === "wedge" ? t("scanning") : t("scanAgain")}
  78. </Button>
  79. {lastLotNo && (
  80. <Chip
  81. label={lastLotNo}
  82. color="primary"
  83. variant="outlined"
  84. sx={{ ml: { sm: "auto" } }}
  85. />
  86. )}
  87. </Stack>
  88. {scanError && (
  89. <Alert severity="warning" onClose={() => setScanError(null)}>
  90. {scanError}
  91. </Alert>
  92. )}
  93. {scanMode === "wedge" && (
  94. <Alert severity="info" onClose={stopWedgeScan}>
  95. {t("scanReady")}
  96. </Alert>
  97. )}
  98. <Typography variant="subtitle2">{t("manualSearch")}</Typography>
  99. <Stack direction={{ xs: "column", sm: "row" }} spacing={1}>
  100. <TextField
  101. size="small"
  102. label={t("itemCode")}
  103. value={itemCode}
  104. onChange={(e) => setItemCode(e.target.value)}
  105. disabled={loading}
  106. fullWidth
  107. />
  108. <TextField
  109. size="small"
  110. label={t("lotNo")}
  111. value={lotNo}
  112. onChange={(e) => setLotNo(e.target.value)}
  113. disabled={loading}
  114. fullWidth
  115. />
  116. <Button
  117. variant="contained"
  118. startIcon={<SearchIcon />}
  119. onClick={handleManualSearch}
  120. disabled={loading || !itemCode.trim() || !lotNo.trim()}
  121. sx={{ minWidth: 120 }}
  122. >
  123. {loading ? t("searching") : t("search")}
  124. </Button>
  125. </Stack>
  126. </Stack>
  127. </Paper>
  128. );
  129. };
  130. export default ItemTracingScanBar;