Sfoglia il codice sorgente

Put away fix

production
CANCERYS\kw093 13 ore fa
parent
commit
cb0f899fc5
3 ha cambiato i file con 254 aggiunte e 127 eliminazioni
  1. +137
    -86
      src/components/PutAwayScan/PutAwayModal.tsx
  2. +91
    -28
      src/components/PutAwayScan/PutAwayScan.tsx
  3. +26
    -13
      src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx

+ 137
- 86
src/components/PutAwayScan/PutAwayModal.tsx Vedi File

@@ -15,7 +15,7 @@ import {
import { fetchItemForPutAway } from "@/app/api/stockIn/actions"; import { fetchItemForPutAway } from "@/app/api/stockIn/actions";
import { Result } from "@/app/api/settings/item"; // 只导入类型 import { Result } from "@/app/api/settings/item"; // 只导入类型


import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import ReactQrCodeScanner, { import ReactQrCodeScanner, {
ScannerConfig, ScannerConfig,
} from "../ReactQrCodeScanner/ReactQrCodeScanner"; } from "../ReactQrCodeScanner/ReactQrCodeScanner";
@@ -36,20 +36,24 @@ import LoadingComponent from "../General/LoadingComponent";
import StockInForm from "../StockIn/StockInForm"; import StockInForm from "../StockIn/StockInForm";
import { arrayToDateString, INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; import { arrayToDateString, INPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import { QrCodeScanner } from "../QrCodeScannerProvider/QrCodeScannerProvider"; import { QrCodeScanner } from "../QrCodeScannerProvider/QrCodeScannerProvider";
import { msg } from "../Swal/CustomAlerts";
import { msg, msgError } from "../Swal/CustomAlerts";
import { PutAwayRecord } from "."; import { PutAwayRecord } from ".";
import FgStockInForm from "../StockIn/FgStockInForm"; import FgStockInForm from "../StockIn/FgStockInForm";


import Swal from "sweetalert2"; import Swal from "sweetalert2";




interface Props extends Omit<ModalProps, "children"> {
interface Props extends Omit<ModalProps, "children" | "onClose"> {
warehouse: WarehouseResult[]; warehouse: WarehouseResult[];
stockInLineId: number; stockInLineId: number;
warehouseId: number; warehouseId: number;
scanner: QrCodeScanner; scanner: QrCodeScanner;
addPutAwayHistory: (putAwayData: PutAwayRecord) => void; addPutAwayHistory: (putAwayData: PutAwayRecord) => void;
onSetDefaultWarehouseId?: (warehouseId: number) => void; // 新增回调
onSetDefaultWarehouseId?: (warehouseId: number) => void;
/** Parent toggles lot vs warehouse scan routing. */
onScanPhaseChange?: (acceptWarehouse: boolean) => void;
/** When false, parent keeps scanner stopped (e.g. until alert is dismissed). */
onClose: (resumeScan?: boolean) => void;
} }
const style = { const style = {
position: "absolute", position: "absolute",
@@ -80,7 +84,7 @@ const scannerStyle = {
maxWidth: "600px", maxWidth: "600px",
}; };


const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId, warehouseId, scanner, addPutAwayHistory, onSetDefaultWarehouseId }) => {
const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId, warehouseId, scanner, addPutAwayHistory, onSetDefaultWarehouseId, onScanPhaseChange }) => {
const { t } = useTranslation("putAway"); const { t } = useTranslation("putAway");
const [serverError, setServerError] = useState(""); const [serverError, setServerError] = useState("");
const params = useSearchParams(); const params = useSearchParams();
@@ -101,6 +105,40 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
const [putQty, setPutQty] = useState<number>(itemDetail?.acceptedQty ?? 0); const [putQty, setPutQty] = useState<number>(itemDetail?.acceptedQty ?? 0);
const [verified, setVerified] = useState<boolean>(false); const [verified, setVerified] = useState<boolean>(false);
const [qtyError, setQtyError] = useState<string>(""); const [qtyError, setQtyError] = useState<string>("");
const fetchRequestIdRef = useRef(0);
const processedItemKeyRef = useRef<string | null>(null);
const onCloseRef = useRef(onClose);
const onScanPhaseChangeRef = useRef(onScanPhaseChange);
const scannerRef = useRef(scanner);
onCloseRef.current = onClose;
onScanPhaseChangeRef.current = onScanPhaseChange;
scannerRef.current = scanner;

const setWarehouseScanPhase = useCallback((accept: boolean) => {
onScanPhaseChangeRef.current?.(accept);
}, []);

const getRejectMessage = (status: string): string => {
switch (status) {
case "pending": return "此貨品有待品檢";
case "rejected": return "此貨品已被拒收";
case "escalated": return "此貨品已被上報";
case "partially_completed": return "此貨品已部分上架";
case "completed": return "此貨品已上架";
default: return "此貨品暫時無法上架";
}
};

const resetModalState = useCallback(() => {
fetchRequestIdRef.current += 1;
setVerified(false);
setItemDetail(undefined);
setTotalPutAwayQty(0);
setItemDefaultWarehouseId(null);
setFirstWarehouseId(null);
setFirstWarehouseInfo(null);
setWarehouseMismatchError("");
}, []);
const defaultNewValue = useMemo(() => { const defaultNewValue = useMemo(() => {
// console.log("%c ItemDetail", "color:purple", itemDetail); // console.log("%c ItemDetail", "color:purple", itemDetail);
@@ -128,54 +166,48 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
...defaultNewValue, ...defaultNewValue,
}, },
}); });
const { isSubmitting } = formProps.formState;
const { reset: resetForm, formState: { isSubmitting } } = formProps;
const errors = formProps.formState.errors; const errors = formProps.formState.errors;


useEffect(() => { useEffect(() => {
if (itemDetail) {
startScanner();
if (itemDetail?.status === "received") {
scannerRef.current.startScan();
console.log("%c Scanning started ", "color:cyan");
} }
}, [itemDetail])
}, [itemDetail?.id, itemDetail?.status]);


const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>( const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
(...args) => { (...args) => {
setVerified(false);
setItemDetail(undefined);
setTotalPutAwayQty(0);
setItemDefaultWarehouseId(null);
setFirstWarehouseId(null);
setFirstWarehouseInfo(null);
onClose?.(...args);
// reset();
setWarehouseScanPhase(false);
onCloseRef.current(true);
resetModalState();
}, },
[onClose],
[resetModalState, setWarehouseScanPhase],
); );


const scannerCloseHandler = useCallback<NonNullable<ModalProps["onClose"]>>( const scannerCloseHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
(...args) => { (...args) => {
setIsOpenScanner(false); setIsOpenScanner(false);
scanner.stopScan();
scannerRef.current.stopScan();
console.log("%c Scanning stopped ", "color:cyan"); console.log("%c Scanning stopped ", "color:cyan");
}, },
[], [],
); );


const startScanner = () => { const startScanner = () => {
// setIsOpenScanner(true);
scanner.startScan();
scannerRef.current.startScan();
console.log("%c Scanning started ", "color:cyan"); console.log("%c Scanning started ", "color:cyan");
}; };


const openScanner = () => { const openScanner = () => {
setIsOpenScanner(true); setIsOpenScanner(true);
scanner.startScan();
scannerRef.current.startScan();
console.log("%c Scanning started ", "color:cyan"); console.log("%c Scanning started ", "color:cyan");
}; };


// 根据 item 的 locationCode 设置默认 warehouseId
// 根据 item 的 locationCode 设置默认 warehouseId(仅 received 状态)
useEffect(() => { useEffect(() => {
// 直接使用 fetchStockInLineInfo 返回的 locationCode
// 只在第一次上架时(firstWarehouseId === null)设置默认值
if (itemDetail?.status !== "received") return;
if (itemDetail?.locationCode && warehouse.length > 0 && firstWarehouseId === null) { if (itemDetail?.locationCode && warehouse.length > 0 && firstWarehouseId === null) {
const locationCode = itemDetail.locationCode; const locationCode = itemDetail.locationCode;
@@ -198,9 +230,11 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
} }
} }
} }
}, [itemDetail?.locationCode, warehouse, firstWarehouseId]);
}, [itemDetail?.status, itemDetail?.locationCode, warehouse, firstWarehouseId]);


useEffect(() => { useEffect(() => {
if (itemDetail?.status !== "received") return;

// 只使用实际扫描的 warehouseId,不使用默认值进行验证 // 只使用实际扫描的 warehouseId,不使用默认值进行验证
if (warehouseId > 0 && firstWarehouseId !== null) { if (warehouseId > 0 && firstWarehouseId !== null) {
// 第二次及后续上架:必须使用第一次的仓库 // 第二次及后续上架:必须使用第一次的仓库
@@ -215,7 +249,7 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
setIsOpenScanner(false); setIsOpenScanner(false);
setVerified(true); setVerified(true);
msg("貨倉掃瞄成功!"); msg("貨倉掃瞄成功!");
scanner.resetScan();
scannerRef.current.resetScan();
} }
} }
} else if (warehouseId > 0 && firstWarehouseId === null) { } else if (warehouseId > 0 && firstWarehouseId === null) {
@@ -224,10 +258,10 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
setIsOpenScanner(false); setIsOpenScanner(false);
setVerified(true); setVerified(true);
msg("貨倉掃瞄成功!"); msg("貨倉掃瞄成功!");
scanner.resetScan();
scannerRef.current.resetScan();
} }
} }
}, [warehouseId, firstWarehouseId, scanner.isScanning]);
}, [warehouseId, firstWarehouseId, scanner.isScanning, itemDetail?.status, warehouse]);


const warehouseDisplay = useMemo(() => { const warehouseDisplay = useMemo(() => {
// 优先使用扫描的 warehouseId,如果没有扫描则显示默认值作为建议 // 优先使用扫描的 warehouseId,如果没有扫描则显示默认值作为建议
@@ -247,69 +281,86 @@ const PutAwayModal: React.FC<Props> = ({ open, onClose, warehouse, stockInLineId
// }, [isOpenScanner]) // }, [isOpenScanner])


useLayoutEffect(() => { useLayoutEffect(() => {
if (itemDetail !== undefined) {
if (itemDetail.status == "received") {
formProps.reset({
...defaultNewValue
})
const total = itemDetail.putAwayLines?.reduce((sum, p) => sum + (p.stockQty ?? p.qty ?? 0), 0) ?? 0;
setPutQty(itemDetail?.acceptedQty - total);
// ✅ Get first warehouse from existing put away lines
const firstPutAwayLine = itemDetail.putAwayLines?.[0];
if (firstPutAwayLine?.warehouseId) {
setFirstWarehouseId(firstPutAwayLine.warehouseId);
// ✅ Store first warehouse info for display
const firstWh = warehouse.find((w) => w.id == firstPutAwayLine.warehouseId);
if (firstWh) {
setFirstWarehouseInfo({
name: firstWh.name || "",
code: firstWh.code || ""
});
}
} else {
setFirstWarehouseId(null);
setFirstWarehouseInfo(null);
if (itemDetail === undefined) {
processedItemKeyRef.current = null;
return;
}

const itemKey = `${itemDetail.id}:${itemDetail.status}`;
if (processedItemKeyRef.current === itemKey) {
return;
}
processedItemKeyRef.current = itemKey;

if (itemDetail.status == "received") {
resetForm({
...defaultNewValue,
});
const total = itemDetail.putAwayLines?.reduce((sum, p) => sum + (p.stockQty ?? p.qty ?? 0), 0) ?? 0;
setPutQty(itemDetail?.acceptedQty - total);

const firstPutAwayLine = itemDetail.putAwayLines?.[0];
if (firstPutAwayLine?.warehouseId) {
setFirstWarehouseId(firstPutAwayLine.warehouseId);
const firstWh = warehouse.find((w) => w.id == firstPutAwayLine.warehouseId);
if (firstWh) {
setFirstWarehouseInfo({
name: firstWh.name || "",
code: firstWh.code || "",
});
} }
console.log("%c Loaded data:", "color:lime", defaultNewValue);
} else { } else {
switch (itemDetail.status) {
case "pending": alert("此貨品有待品檢"); break;
case "rejected": alert("此貨品已被拒收"); break;
case "escalated": alert("此貨品已被上報"); break;
case "partially_completed": alert("此貨品已部分上架"); break;
case "completed": alert("此貨品已上架"); break;
default: alert("此貨品暫時無法上架"); break;
}
closeHandler({}, "backdropClick");
setFirstWarehouseId(null);
setFirstWarehouseInfo(null);
} }
}
}, [open, itemDetail, defaultNewValue])

const fetchStockInLine = useCallback(
async (stockInLineId: number) => {
setUnavailableText(undefined);
try {
const res = await fetchStockInLineInfo(stockInLineId);
console.log("%c Fetched Stock In Line Info:", "color:gold", res);


const total = res.putAwayLines?.reduce((sum, p) => sum + (p.stockQty ?? p.qty ?? 0), 0) ?? 0;
setTotalPutAwayQty(total);
setItemDetail(res);
} catch (e) {
console.log("%c Error when fetching Stock In Line: ", "color:red", e);
alert("錯誤的二維碼");
closeHandler({}, "backdropClick");
}
},
[formProps, itemDetail, fetchStockInLineInfo],
);
console.log("%c Loaded data:", "color:lime", defaultNewValue);
setWarehouseScanPhase(true);
} else {
processedItemKeyRef.current = null;
setWarehouseScanPhase(false);
resetModalState();
onCloseRef.current(true);
msgError(getRejectMessage(itemDetail.status));
}
}, [itemDetail, defaultNewValue, warehouse, resetModalState, resetForm, setWarehouseScanPhase]);

const fetchStockInLine = useCallback(async (stockInLineId: number) => {
const requestId = ++fetchRequestIdRef.current;
processedItemKeyRef.current = null;
setWarehouseScanPhase(false);
setUnavailableText(undefined);
setItemDetail(undefined);
try {
const res = await fetchStockInLineInfo(stockInLineId);
if (requestId !== fetchRequestIdRef.current) return;

console.log("%c Fetched Stock In Line Info:", "color:gold", res);

const total = res.putAwayLines?.reduce((sum, p) => sum + (p.stockQty ?? p.qty ?? 0), 0) ?? 0;
setTotalPutAwayQty(total);
setItemDetail(res);
} catch (e) {
if (requestId !== fetchRequestIdRef.current) return;

console.log("%c Error when fetching Stock In Line: ", "color:red", e);
setWarehouseScanPhase(false);
resetModalState();
onCloseRef.current(true);
msgError("錯誤的二維碼");
}
}, [resetModalState, setWarehouseScanPhase]);


useEffect(() => { useEffect(() => {
if (stockInLineId) { fetchStockInLine(stockInLineId); }
}, [stockInLineId]);
if (stockInLineId) {
fetchStockInLine(stockInLineId);
return;
}
fetchRequestIdRef.current += 1;
processedItemKeyRef.current = null;
setWarehouseScanPhase(false);
setItemDetail(undefined);
}, [stockInLineId, fetchStockInLine, setWarehouseScanPhase]);


const validateQty = useCallback((qty : number = putQty) => { const validateQty = useCallback((qty : number = putQty) => {
// if (isNaN(putQty) || putQty === undefined || putQty === null || typeof(putQty) != "number") { // if (isNaN(putQty) || putQty === undefined || putQty === null || typeof(putQty) != "number") {


+ 91
- 28
src/components/PutAwayScan/PutAwayScan.tsx Vedi File

@@ -45,14 +45,21 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
const [scannedWareHouseId, setScannedWareHouseId] = useState<number>(0); // TODO use QR code info const [scannedWareHouseId, setScannedWareHouseId] = useState<number>(0); // TODO use QR code info
const [putAwayHistory, setPutAwayHistory] = useState<PutAwayRecord[]>([]); const [putAwayHistory, setPutAwayHistory] = useState<PutAwayRecord[]>([]);


const openPutAwayModalRef = useRef(false);
const scannedSilIdRef = useRef(0);
/** Only true after modal loaded a received item — gates warehouse vs lot routing. */
const acceptWarehouseScansRef = useRef(false);

// QR Code Scanner // QR Code Scanner
const scanner = useQrCodeScannerContext(); const scanner = useQrCodeScannerContext();
const scannerRef = useRef(scanner);
scannerRef.current = scanner;

useEffect(() => { useEffect(() => {
if (!scanner.isScanning) {
scanner.startScan();
} else if (scanner.isScanning) {
scanner.stopScan();
}
scannerRef.current.startScan();
return () => {
scannerRef.current.stopScan();
};
}, []); }, []);


const resetScan = (error : string = "") => { const resetScan = (error : string = "") => {
@@ -62,26 +69,49 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
} else { } else {
console.log("%c Scan reset", "color:red"); console.log("%c Scan reset", "color:red");
} }
scanner.resetScan();
scannerRef.current.resetScan();
}; };


const openModal = () => { const openModal = () => {
console.log("Scanned successfully and open modal"); console.log("Scanned successfully and open modal");
scanner.stopScan();
openPutAwayModalRef.current = true;
acceptWarehouseScansRef.current = false;
scannerRef.current.stopScan();
console.log("%c Scanning stopped ", "color:cyan"); console.log("%c Scanning stopped ", "color:cyan");
setOpenPutAwayModal(true); setOpenPutAwayModal(true);
setScanDisplay("pending"); setScanDisplay("pending");
}; };

const applyLotScan = useCallback((lotId: number) => {
acceptWarehouseScansRef.current = false;
scannedSilIdRef.current = lotId;
setScannedWareHouseId(0);
setScannedSilId(lotId);
}, []);

const handleScanPhaseChange = useCallback((acceptWarehouse: boolean) => {
acceptWarehouseScansRef.current = acceptWarehouse;
if (!acceptWarehouse) {
setScannedWareHouseId(0);
}
}, []);
const closeModal = () => {
const closeModal = useCallback((resumeScan = true) => {
openPutAwayModalRef.current = false;
acceptWarehouseScansRef.current = false;
scannedSilIdRef.current = 0;
setScannedSilId(0); setScannedSilId(0);
setScannedWareHouseId(0); setScannedWareHouseId(0);
setScanDisplay("pending"); setScanDisplay("pending");
console.log("Modal Closed");
scanner.startScan();
console.log("%c Scanning started ", "color:cyan");
setOpenPutAwayModal(false); setOpenPutAwayModal(false);
}
console.log("Modal Closed");
scannerRef.current.resetScan();
scannerRef.current.stopScan();
if (resumeScan) {
scannerRef.current.startScan();
console.log("%c Scanning started ", "color:cyan");
}
}, []);


const addPutAwayHistory = (putAwayData: PutAwayRecord) => { const addPutAwayHistory = (putAwayData: PutAwayRecord) => {
console.log("%c Added new data to Putaway history: ", "color:orange", putAwayData); console.log("%c Added new data to Putaway history: ", "color:orange", putAwayData);
@@ -92,6 +122,7 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {


// 处理默认 warehouseId 的回调 // 处理默认 warehouseId 的回调
const handleSetDefaultWarehouseId = useCallback((warehouseId: number) => { const handleSetDefaultWarehouseId = useCallback((warehouseId: number) => {
if (!acceptWarehouseScansRef.current) return;
if (scannedWareHouseId === 0) { if (scannedWareHouseId === 0) {
setScannedWareHouseId(warehouseId); setScannedWareHouseId(warehouseId);
console.log("%c Set default warehouseId from item locationCode:", "color:green", warehouseId); console.log("%c Set default warehouseId from item locationCode:", "color:green", warehouseId);
@@ -112,7 +143,11 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
const id = parseInt(stockInLineIdQ, 10); const id = parseInt(stockInLineIdQ, 10);
if (!Number.isFinite(id) || id <= 0) return; if (!Number.isFinite(id) || id <= 0) return;
deepLinkConsumedRef.current = true; deepLinkConsumedRef.current = true;
setScannedSilId((prev) => (prev === id ? prev : id));
setScannedSilId((prev) => {
if (prev === id) return prev;
scannedSilIdRef.current = id;
return id;
});


// Consume deep link once, then remove it from URL // Consume deep link once, then remove it from URL
const nextParams = new URLSearchParams(searchParams.toString()); const nextParams = new URLSearchParams(searchParams.toString());
@@ -121,24 +156,51 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
router.replace(nextQuery ? `${pathname}?${nextQuery}` : pathname); router.replace(nextQuery ? `${pathname}?${nextQuery}` : pathname);
}, [stockInLineIdQ, pathname, router, searchParams]); }, [stockInLineIdQ, pathname, router, searchParams]);


// Get Scanned Values
const parseLotId = useCallback((data: QrCodeInfo): number | null => {
const fromValue = Number(data.value);
if (Number.isFinite(fromValue) && fromValue > 0) return fromValue;
const fromField = Number(data.stockInLineId);
if (Number.isFinite(fromField) && fromField > 0) return fromField;
return null;
}, []);

const parseWarehouseId = useCallback((data: QrCodeInfo): number | null => {
const fromValue = Number(data.value);
if (Number.isFinite(fromValue) && fromValue > 0) return fromValue;
const fromField = Number(data.warehouseId);
if (Number.isFinite(fromField) && fromField > 0) return fromField;
return null;
}, []);

// Route scans: lot unless modal has a received item ready for warehouse scan.
useEffect(() => { useEffect(() => {
if (scanner.result) {
const data = scanner.result;
if (scannedSilId == 0) { // Initial State
if (!isNaN(Number(data.value))) { setScannedSilId(Number(data.value)); }
else if (data.stockInLineId) {
setScannedSilId(Number(data.stockInLineId));
} else resetScan("Cannot read Stock In Line Id");
} else { // Processing
if (!isNaN(Number(data.value))) { setScannedWareHouseId(Number(data.value)); }
else if (data.warehouseId) {
setScannedWareHouseId(Number(data.warehouseId));
} else resetScan("Cannot read Warehouse Id");
if (!scanner.result) return;

const data = scanner.result;
scannerRef.current.resetScan();

const modalOpen = openPutAwayModalRef.current;
const acceptWarehouse = acceptWarehouseScansRef.current;

// Lot scan when modal closed, or still loading / rejecting (not yet received).
if (!modalOpen || !acceptWarehouse) {
const lotId = parseLotId(data);
if (lotId != null) {
applyLotScan(lotId);
} else if (!modalOpen) {
resetScan("Cannot read Stock In Line Id");
} }
scanner.resetScan();
// Warehouse-only scan during loading/reject: silently discard.
return;
}

const whId = parseWarehouseId(data);
if (whId != null) {
setScannedWareHouseId(whId);
} else {
resetScan("Cannot read Warehouse Id");
} }
}, [scanner.result]);
}, [scanner.result, parseLotId, parseWarehouseId, applyLotScan]);


// Get Scanner State // Get Scanner State
useEffect(() => { useEffect(() => {
@@ -196,6 +258,7 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
scanner={scanner} scanner={scanner}
addPutAwayHistory={addPutAwayHistory} addPutAwayHistory={addPutAwayHistory}
onSetDefaultWarehouseId={handleSetDefaultWarehouseId} onSetDefaultWarehouseId={handleSetDefaultWarehouseId}
onScanPhaseChange={handleScanPhaseChange}
/> />
</>) </>)
} }


+ 26
- 13
src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx Vedi File

@@ -1,12 +1,13 @@
"use client"; "use client";
import { QrCodeInfo } from "@/app/api/qrcode"; import { QrCodeInfo } from "@/app/api/qrcode";
import { useRef } from "react";
import { import {
ReactNode, ReactNode,
createContext, createContext,
useCallback, useCallback,
useContext, useContext,
useEffect, useEffect,
useMemo,
useRef,
useState, useState,
startTransition, startTransition,
} from "react"; } from "react";
@@ -352,19 +353,31 @@ useEffect(() => {
} }
}, [qrCodeScannerValues]); }, [qrCodeScannerValues]);


const contextValue = useMemo(
() => ({
values: qrCodeScannerValues,
isScanning: isScanning,
startScan: startQrCodeScanner,
stopScan: endQrCodeScanner,
resetScan: resetQrCodeScanner,
result: scanResult,
state: scanState,
error: scanError,
}),
[
qrCodeScannerValues,
isScanning,
startQrCodeScanner,
endQrCodeScanner,
resetQrCodeScanner,
scanResult,
scanState,
scanError,
],
);

return ( return (
<QrCodeScannerContext.Provider
value={{
values: qrCodeScannerValues,
isScanning: isScanning,
startScan: startQrCodeScanner,
stopScan: endQrCodeScanner,
resetScan: resetQrCodeScanner,
result: scanResult,
state: scanState,
error: scanError,
}}
>
<QrCodeScannerContext.Provider value={contextValue}>
{children} {children}
</QrCodeScannerContext.Provider> </QrCodeScannerContext.Provider>
); );


Caricamento…
Annulla
Salva