CANCERYS\kw093 3 maanden geleden
bovenliggende
commit
8fb4c0cd86
10 gewijzigde bestanden met toevoegingen van 362 en 194 verwijderingen
  1. +1
    -1
      src/app/api/qc/index.ts
  2. +2
    -1
      src/app/api/qrcode/index.ts
  3. +0
    -4
      src/app/global.css
  4. +53
    -27
      src/components/PoDetail/PutAwayForm.tsx
  5. +18
    -8
      src/components/PoDetail/QcComponent.tsx
  6. +99
    -49
      src/components/PoDetail/StockInForm.tsx
  7. +10
    -10
      src/components/PoDetail/dummyQcTemplate.tsx
  8. +13
    -75
      src/components/PutAwayScan/PutAwayScan.tsx
  9. +121
    -19
      src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx
  10. +45
    -0
      src/theme/devias-material-kit/components.ts

+ 1
- 1
src/app/api/qc/index.ts Bestand weergeven

@@ -20,7 +20,7 @@ export interface QcData {
qcItemId: number,
code: string,
name: string,
qcDescription: string,
description: string,
qcPassed: boolean | undefined
failQty: number | undefined
remarks: string | undefined


+ 2
- 1
src/app/api/qrcode/index.ts Bestand weergeven

@@ -6,10 +6,11 @@ import { serverFetchJson } from "../../utils/fetchUtil";
import { BASE_API_URL } from "../../../config/api";

export interface QrCodeInfo {
value: string;
// warehouse qrcode
warehouseId?: number;
// item qrcode
stockInLineId?: number;
itemId: number;
itemId?: number;
lotNo?: string;
}

+ 0
- 4
src/app/global.css Bestand weergeven

@@ -4,8 +4,4 @@

html, body {
overscroll-behavior: none;
}

.swal2-custom-zindex {
z-index: 10000 !important;
}

+ 53
- 27
src/components/PoDetail/PutAwayForm.tsx Bestand weergeven

@@ -229,7 +229,9 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM
flex: 0.2,
editable: false,
renderCell(params) {
return `${params.api.getRowIndexRelativeToVisibleRows(params.id) + 1}.`
return <span style={{fontSize:18}}>
{`${params.api.getRowIndexRelativeToVisibleRows(params.id) + 1}.`}
</span>
},
},
{
@@ -238,7 +240,9 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM
flex: 1,
editable: false,
renderCell(params) {
return `${(arrayToDateTimeString(params.value))}`;
return <span style={{fontSize:24}}>
{`${(arrayToDateTimeString(params.value))}`}
</span>
},
},
{
@@ -246,6 +250,11 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM
headerName: t("putawayUser"),
flex: 1,
editable: false,
renderCell(params) {
return <span style={{fontSize:24}}>
{params.value}
</span>
}
},
{
field: "qty",
@@ -254,38 +263,55 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM
editable: false,
headerAlign: "right",
align: "right",
renderCell(params) {
return <span style={{fontSize:24}}>
{params.value}
</span>
}
},
{
field: "warehouse",
headerName: t("warehouse"),
flex: 2,
editable: false,
renderEditCell: (params) => {
const index = params.api.getRowIndexRelativeToVisibleRows(params.row.id)
// console.log(index)
// console.log(watch(`putAwayLines.${index}.warehouse`))
return <Autocomplete
fullWidth
disableClearable
options={options}
// defaultValue={options.find((o) => o.value === itemDetail.defaultWarehouseId)}
// value={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))}
defaultValue={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))}
onChange={(event, value) => {
params.api.setEditCellValue({ id: params.id, field: params.field, value: options.find((o) => o.value === value.value)?.label ?? ""})
params.api.setEditCellValue({ id: params.id, field: "warehouseId", value: value.value})
// setValue(`putAwayLines.${index}.warehouseId`, value.value)
// setValue(`putAwayLines.${index}.warehouse`, options.find((o) => o.value === value.value)?.label ?? "")
}}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
// label={t("Warehouse")}
/>
)}
/>
renderCell(params) {
return <span style={{fontSize:24}}>
{params.value}
</span>
}
// renderEditCell: (params) => {
// const index = params.api.getRowIndexRelativeToVisibleRows(params.row.id)
// // console.log(index)
// // console.log(watch(`putAwayLines.${index}.warehouse`))
// return <Autocomplete
// fullWidth
// disableClearable
// options={options}
// // defaultValue={options.find((o) => o.value === itemDetail.defaultWarehouseId)}
// // value={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))}
// defaultValue={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))}
// onChange={(event, value) => {
// params.api.setEditCellValue({ id: params.id, field: params.field, value: options.find((o) => o.value === value.value)?.label ?? ""})
// params.api.setEditCellValue({ id: params.id, field: "warehouseId", value: value.value})
// // setValue(`putAwayLines.${index}.warehouseId`, value.value)
// // setValue(`putAwayLines.${index}.warehouse`, options.find((o) => o.value === value.value)?.label ?? "")
// }}
// sx={{
// // Style the dropdown options
// "& .MuiAutocomplete-option": {
// fontSize: 24,
// },
// }}
// renderInput={(params) => (
// <TextField
// {...params}
// variant="outlined"
// InputProps={{style: {fontSize: 24}}}
// // label={t("Warehouse")}
// />
// )}
// />
// }
// renderCell(params) {
// return <>{filteredWarehouse[0].name}</>
// },


+ 18
- 8
src/components/PoDetail/QcComponent.tsx Bestand weergeven

@@ -237,10 +237,10 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {

const qcColumns: GridColDef[] = useMemo(() => [
{
field: "code",
field: "name",
headerName: t("qcItem"),
wrapText: true,
flex: 2,
flex: 2.5,
renderCell: (params) => {
const index = params.api.getRowIndexRelativeToVisibleRows(params.id) + 1;
return (
@@ -248,17 +248,18 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
sx={{
lineHeight: 1.5,
padding: "4px",
fontSize: 18,
}}
>
<b>{`${index}. ${params.value}`}</b><br/>
{params.row.name}
{params.row.description}
</Box>
)},
},
{
field: 'qcResult',
headerName: t("qcResult"),
flex: 1.5,
flex: 1,
renderCell: (params) => {
const rowValue = params.row;
const index = Number(params.id);//params.api.getRowIndexRelativeToVisibleRows(params.id);
@@ -307,14 +308,13 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
{
field: "failQty",
headerName: t("failedQty"),
flex: 1,
flex: 0.5,
// editable: true,
renderCell: (params) => {
const index = Number(params.id);//params.api.getRowIndexRelativeToVisibleRows(params.id);
return (
<TextField
type="number"
size="small"
value={!params.row.qcPassed? params.value : '0'}
disabled={params.row.qcPassed || qcDisabled(params.row)}
/* TODO improve */
@@ -335,7 +335,12 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
onMouseDown={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
inputProps={{ min: 0 }}
sx={{ width: '100%' }}
sx={{ width: '100%',
"& .MuiInputBase-input": {
padding: "0.75rem",
fontSize: 24,
},
}}
/>
);
},
@@ -369,7 +374,12 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
onClick={(e) => e.stopPropagation()}
onMouseDown={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
sx={{ width: '100%' }}
sx={{ width: '100%',
"& .MuiInputBase-input": {
padding: "0.75rem",
fontSize: 24,
},
}}
/>
);
},


+ 99
- 49
src/components/PoDetail/StockInForm.tsx Bestand weergeven

@@ -54,6 +54,35 @@ type EntryError =

// type PoQcRow = TableRow<Partial<PurchaseQcResult>, EntryError>;

const textfieldSx = {
width: "100%",
"& .MuiInputBase-root": {
// height: "120", // Scales with root font size
height: "5rem", // Scales with root font size
},
"& .MuiInputBase-input": {
height: "100%",
boxSizing: "border-box",
padding: "0.75rem",
fontSize: 24,
},
"& .MuiInputLabel-root": {
fontSize: 24,
transform: "translate(14px, 1.5rem) scale(1)",
"&.MuiInputLabel-shrink": {
fontSize: 18,
transform: "translate(14px, -9px) scale(1)",
},
// [theme.breakpoints.down("sm")]: {
// fontSize: "1rem",
// transform: "translate(14px, 1.5rem) scale(1)",
// "&.MuiInputLabel-shrink": {
// fontSize: "0.875rem",
// },
// },
},
};

const StockInForm: React.FC<Props> = ({
// qc,
itemDetail,
@@ -136,6 +165,7 @@ const StockInForm: React.FC<Props> = ({
{...register("dnNo", {
// required: "productLotNo required!",
})}
sx={textfieldSx}
disabled={disabled}
// error={Boolean(errors.productLotNo)}
// helperText={errors.productLotNo?.message}
@@ -148,6 +178,7 @@ const StockInForm: React.FC<Props> = ({
{...register("itemName", {
// required: "productLotNo required!",
})}
sx={textfieldSx}
disabled={true}
// error={Boolean(errors.productLotNo)}
// helperText={errors.productLotNo?.message}
@@ -160,6 +191,7 @@ const StockInForm: React.FC<Props> = ({
{...register("poCode", {
// required: "productLotNo required!",
})}
sx={textfieldSx}
disabled={true}
// error={Boolean(errors.productLotNo)}
// helperText={errors.productLotNo?.message}
@@ -180,7 +212,7 @@ const StockInForm: React.FC<Props> = ({
>
<DatePicker
{...field}
sx={{ width: "100%" }}
sx={textfieldSx}
label={t("receiptDate")}
value={dayjs(watch("receiptDate"))}
disabled={true}
@@ -210,6 +242,7 @@ const StockInForm: React.FC<Props> = ({
{...register("supplier", {
// required: "productLotNo required!",
})}
sx={textfieldSx}
disabled={true}
/>
</Grid>
@@ -222,51 +255,52 @@ const StockInForm: React.FC<Props> = ({
{...register("productLotNo", {
// required: "productLotNo required!",
})}
sx={textfieldSx}
disabled={disabled}
error={Boolean(errors.productLotNo)}
helperText={errors.productLotNo?.message}
/>
</Grid>
<Grid item xs={6}>
<Controller
control={control}
name="productionDate"
// rules={{ required: !Boolean(expiryDate) }}
render={({ field }) => {
return (
<LocalizationProvider
dateAdapter={AdapterDayjs}
adapterLocale={`${language}-hk`}
>
<DatePicker
{...field}
sx={{ width: "100%" }}
label={t("productionDate")}
value={productionDate ? dayjs(productionDate) : undefined}
disabled={disabled}
onChange={(date) => {
if (!date) return;
setValue(
"productionDate",
date.format(INPUT_DATE_FORMAT),
);
// field.onChange(date);
}}
inputRef={field.ref}
slotProps={{
textField: {
// required: true,
error: Boolean(errors.productionDate?.message),
helperText: errors.productionDate?.message,
},
}}
/>
</LocalizationProvider>
);
}}
/>
</Grid>
{putawayMode || (
{putawayMode || (<>
<Grid item xs={6}>
<Controller
control={control}
name="productionDate"
// rules={{ required: !Boolean(expiryDate) }}
render={({ field }) => {
return (
<LocalizationProvider
dateAdapter={AdapterDayjs}
adapterLocale={`${language}-hk`}
>
<DatePicker
{...field}
sx={textfieldSx}
label={t("productionDate")}
value={productionDate ? dayjs(productionDate) : undefined}
disabled={disabled}
onChange={(date) => {
if (!date) return;
setValue(
"productionDate",
date.format(INPUT_DATE_FORMAT),
);
// field.onChange(date);
}}
inputRef={field.ref}
slotProps={{
textField: {
// required: true,
error: Boolean(errors.productionDate?.message),
helperText: errors.productionDate?.message,
},
}}
/>
</LocalizationProvider>
);
}}
/>
</Grid>
<Grid item xs={6}>
<TextField
label={t("qty")}
@@ -274,9 +308,10 @@ const StockInForm: React.FC<Props> = ({
{...register("qty", {
required: "qty required!",
})}
sx={textfieldSx}
disabled={true}
/>
</Grid>
</Grid></>
)}
<Grid item xs={6}>
<Controller
@@ -291,7 +326,7 @@ const StockInForm: React.FC<Props> = ({
>
<DatePicker
{...field}
sx={{ width: "100%" }}
sx={textfieldSx}
label={t("expiryDate")}
value={expiryDate ? dayjs(expiryDate) : undefined}
disabled={disabled}
@@ -323,6 +358,7 @@ const StockInForm: React.FC<Props> = ({
{...register("receivedQty", {
required: "receivedQty required!",
})}
sx={textfieldSx}
disabled={true}
/>
</Grid>
@@ -331,33 +367,47 @@ const StockInForm: React.FC<Props> = ({
<TextField
label={t("uom")}
fullWidth
{...register("uom.code", {
{...register("uom.udfudesc", {
required: "uom required!",
})}
// value={uom?.code}
sx={textfieldSx}
disabled={true}
/>
</Grid>
{putawayMode ? (
{putawayMode ? (<>
<Grid item xs={6}>
<TextField
label={`${t("processedQty")} / ${t("acceptedQty")}`}
label={t("acceptedQty")}
fullWidth
sx={textfieldSx}
disabled={true}
value={
`${itemDetail.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0} / ${itemDetail.acceptedQty}`
}
value={itemDetail.acceptedQty}
// disabled={true}
// disabled={disabled}
// error={Boolean(errors.acceptedQty)}
// helperText={errors.acceptedQty?.message}
/>
</Grid>
<Grid item xs={6}>
<TextField
label={t("processedQty")}
fullWidth
sx={textfieldSx}
disabled={true}
value={itemDetail.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0}
// disabled={true}
// disabled={disabled}
// error={Boolean(errors.acceptedQty)}
// helperText={errors.acceptedQty?.message}
/>
</Grid></>
) : (
<Grid item xs={6}>
<TextField
label={t("acceptedQty")}
fullWidth
sx={textfieldSx}
disabled={true}
{...register("acceptedQty", {
required: "acceptedQty required!",


+ 10
- 10
src/components/PoDetail/dummyQcTemplate.tsx Bestand weergeven

@@ -15,8 +15,8 @@ export const dummyQCData: QcData[] = [
id: 1,
qcItemId: 4,
code: "包裝",
qcDescription: "有破爛、污糟、脹袋、積水、與實物不符等任何一種情況,則不合格",
name: "有破爛、污糟、脹袋、積水、與實物不符等任何一種情況,則不合格",
description: "有破爛、污糟、脹袋、積水、與實物不符等任何一種情況,則不合格",
name: "包裝",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
@@ -25,8 +25,8 @@ export const dummyQCData: QcData[] = [
id: 2,
qcItemId: 5,
code: "肉質",
qcDescription: "肉質鬆散,則不合格",
name: "肉質鬆散,則不合格",
description: "肉質鬆散,則不合格",
name: "肉質",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
@@ -35,8 +35,8 @@ export const dummyQCData: QcData[] = [
id: 3,
qcItemId: 6,
code: "顔色",
qcDescription: "不是食材應有的顔色、顔色不均匀、出現其他顔色、腌料/醬顔色不均匀,油脂部分變綠色、黃色,則不合格",
name: "不是食材應有的顔色、顔色不均匀、出現其他顔色、腌料/醬顔色不均匀,油脂部分變綠色、黃色,則不合格",
description: "不是食材應有的顔色、顔色不均匀、出現其他顔色、腌料/醬顔色不均匀,油脂部分變綠色、黃色,則不合格",
name: "顔色",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
@@ -45,8 +45,8 @@ export const dummyQCData: QcData[] = [
id: 4,
qcItemId: 7,
code: "狀態",
qcDescription: "有結晶、結霜、解凍跡象、發霉、散發異味等任何一種情況,則不合格",
name: "有結晶、結霜、解凍跡象、發霉、散發異味等任何一種情況,則不合格",
description: "有結晶、結霜、解凍跡象、發霉、散發異味等任何一種情況,則不合格",
name: "狀態",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
@@ -55,8 +55,8 @@ export const dummyQCData: QcData[] = [
id: 5,
qcItemId: 8,
code: "異物",
qcDescription: "有不屬於本食材的雜質,則不合格",
name: "有不屬於本食材的雜質,則不合格",
description: "有不屬於本食材的雜質,則不合格",
name: "異物",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,


+ 13
- 75
src/components/PutAwayScan/PutAwayScan.tsx Bestand weergeven

@@ -52,10 +52,8 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
useEffect(() => {
if (!scanner.isScanning) {
scanner.startScan();
console.log("%c Scanning started ", "color:cyan");
} else if (scanner.isScanning) {
scanner.stopScan();
console.log("%c Scanning stopped ", "color:cyan");
}
}, []);

@@ -87,37 +85,6 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {
setOpenPutAwayModal(false);
}


const findIdByRoughMatch = (inputString : string, keyword : string) => {
const keywordIndex = inputString.indexOf(keyword);
if (keywordIndex === -1) {
return {
keywordFound: false,
number: null,
message: `${keyword} not found in the input`,
};
}
const substringAfterKeyword = inputString.slice(keywordIndex + keyword.length);
const numberMatch = substringAfterKeyword.match(/\d+/);
if (!numberMatch) {
return {
keywordFound: true,
number: null,
message: `No valid number found after ${keyword}`,
};
}
return {
keywordFound: true,
number: parseInt(numberMatch[0], 10),
message: `Found ${keyword} at index ${keywordIndex}, first number found after is: ${numberMatch[0]}`,
};
}

const addPutAwayHistory = (putAwayData: PutAwayRecord) => {
console.log("%c Added new data to Putaway history: ", "color:orange", putAwayData);
const newPutaway = { ...putAwayData, id: putAwayHistory.length + 1 };
@@ -133,51 +100,22 @@ const PutAwayScan: React.FC<Props> = ({ warehouse }) => {

// Get Scanned Values
useEffect(() => {
if (scanner.values.length > 0) {//} && !Boolean(itemDetail)) {
const scannedValues = scanner.values[0];
console.log("%c Scanned: ", "color:cyan", scannedValues);

if (scannedValues.substring(0, 8) == "{2fitest") { // DEBUGGING
const number = scannedValues.substring(8, scannedValues.length - 1);
if (/^\d+$/.test(number)) { // Check if number contains only digits
console.log("%c DEBUG: Testing SIL ID: ", "color:cyan", number);
if (scannedSilId === 0) {
setScannedSilId(Number(number));
} else setScannedWareHouseId(Number(number));
} else {
console.error("%c DEBUG: Invalid number format: ", "color:red", number);
resetScan();
}
return;
}
try {
const data: QrCodeInfo = JSON.parse(scannedValues);
console.log("%c Scanned with data", "color:green", data);
if (scannedSilId == 0) { // Initial State
if (data.stockInLineId !== undefined) {
setScannedSilId(Number(data.stockInLineId));
} else resetScan("Cannot read Stock In Line Id");
} else { // Processing
if (data.warehouseId !== undefined) {
setScannedWareHouseId(Number(data.warehouseId));
} else resetScan("Cannot read Warehouse Id");
}
} catch (error) { // Rought match for other scanner -- Pending Review
if (scannedSilId == 0) {
const silId = findIdByRoughMatch(scannedValues, "StockInLine").number ?? 0;
setScannedSilId(silId);

} else {
const whId = findIdByRoughMatch(scannedValues, "warehouseId").number ?? 0;
setScannedWareHouseId(whId);
}

resetScan(String(error));
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");
}
scanner.resetScan();
}
}, [scanner.values]);
}, [scanner.result]);

return (<>
<Paper sx={{


+ 121
- 19
src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx Bestand weergeven

@@ -1,4 +1,5 @@
"use client";
import { QrCodeInfo } from "@/app/api/qrcode";
import {
ReactNode,
createContext,
@@ -14,6 +15,7 @@ export interface QrCodeScanner {
startScan: () => void;
stopScan: () => void;
resetScan: () => void;
result: QrCodeInfo | undefined;
}

interface QrCodeScannerProviderProps {
@@ -32,19 +34,73 @@ const QrCodeScannerProvider: React.FC<QrCodeScannerProviderProps> = ({
const [keys, setKeys] = useState<string[]>([]);
const [leftCurlyBraceCount, setLeftCurlyBraceCount] = useState<number>(0);
const [rightCurlyBraceCount, setRightCurlyBraceCount] = useState<number>(0);
const resetQrCodeScanner = useCallback(() => {
const [scanResult, setScanResult] = useState<QrCodeInfo | undefined>()

const resetScannerInput = useCallback(() => {
setKeys(() => []);
setLeftCurlyBraceCount(() => 0);
setRightCurlyBraceCount(() => 0);
}, []);

const resetQrCodeScanner = useCallback((error : string = "") => {
setQrCodeScannerValues(() => []);
setScanResult(undefined);
resetScannerInput();

console.log("%c Scanner Reset", "color:cyan");
if (error.length > 0) {
console.log("%c Error:", "color:red", error);
}
}, []);

const startQrCodeScanner = useCallback(() => {
resetQrCodeScanner();
setIsScanning(() => true);
console.log("%c Scanning started ", "color:cyan");
}, []);

const endQrCodeScanner = useCallback(() => {
setIsScanning(() => false);
console.log("%c Scanning stopped ", "color:cyan");
}, []);

// Find by rough match, return 0 if not found
const findIdByRoughMatch = (inputString : string, keyword : string) => {
console.log(`%c Performed rough match for ${keyword} within ${inputString}`, "color:brown");
const keywordIndex = inputString.indexOf(keyword);
let result : {keywordFound: boolean; number: number | null; message: string} = {
keywordFound: false,
number: null,
message: `${keyword} not found in the input`,
};

if (keywordIndex !== -1) {
const substringAfterKeyword = inputString.slice(keywordIndex + keyword.length);
const numberMatch = substringAfterKeyword.match(/\d+/);
if (!numberMatch) {
result = {
keywordFound: true,
number: null,
message: `No valid number found after ${keyword}`,
};
} else {
result = {
keywordFound: true,
number: parseInt(numberMatch[0], 10),
message: `Found ${keyword} at index ${keywordIndex}, first number found after is: ${numberMatch[0]}`,
};
}
}

console.log(`%c ${result.message}`, "color:brown");
return result;
};

// Check the KeyDown
useEffect(() => {
if (isScanning) {
@@ -70,27 +126,72 @@ const QrCodeScannerProvider: React.FC<QrCodeScannerProviderProps> = ({

// Update Qr Code Scanner Values
useEffect(() => {
if (
leftCurlyBraceCount !== 0 &&
rightCurlyBraceCount !== 0 &&
leftCurlyBraceCount === rightCurlyBraceCount
) {
const startBrace = keys.indexOf("{");
const endBrace = keys.lastIndexOf("}");
setQrCodeScannerValues((value) => [
...value,
keys.join("").substring(startBrace, endBrace + 1),
]);
console.log(keys);
console.log("%c QR Scanner Values:", "color:cyan", qrCodeScannerValues);

// reset
setKeys(() => []);
setLeftCurlyBraceCount(() => 0);
setRightCurlyBraceCount(() => 0);
if (rightCurlyBraceCount > leftCurlyBraceCount || leftCurlyBraceCount > 1) { // Prevent multiple scan
resetQrCodeScanner("Too many scans at once");
} else {
if (leftCurlyBraceCount == 1 && keys.length == 1)
{ console.log("%c Scan detected, waiting for inputs...", "color:cyan"); }
if (
leftCurlyBraceCount !== 0 &&
rightCurlyBraceCount !== 0 &&
leftCurlyBraceCount === rightCurlyBraceCount
) {
const startBrace = keys.indexOf("{");
const endBrace = keys.lastIndexOf("}");
setQrCodeScannerValues((value) => [
...value,
keys.join("").substring(startBrace, endBrace + 1),
]);
// console.log(keys);
// console.log("%c QR Scanner Values:", "color:cyan", qrCodeScannerValues);
resetScannerInput();
}
}
}, [keys, leftCurlyBraceCount, rightCurlyBraceCount]);

useEffect(() => {
if (qrCodeScannerValues.length > 0) {
const scannedValues = qrCodeScannerValues[0];
console.log("%c Scanned Result: ", "color:cyan", scannedValues);

if (scannedValues.substring(0, 8) == "{2fitest") { // DEBUGGING
const number = scannedValues.substring(8, scannedValues.length - 1);
if (/^\d+$/.test(number)) { // Check if number contains only digits
console.log("%c DEBUG: detected ID: ", "color:pink", number);
const debugValue = {
value: number
}
setScanResult(debugValue);
} else {
resetQrCodeScanner("DEBUG -- Invalid number format: " + number);
}
return;
}

try {
const data: QrCodeInfo = JSON.parse(scannedValues);
console.log("%c Parsed scan data", "color:green", data);
const content = scannedValues.substring(1, scannedValues.length - 1);
data.value = content;
setScanResult(data);

} catch (error) { // Rought match for other scanner input -- Pending Review
const silId = findIdByRoughMatch(scannedValues, "StockInLine").number ?? 0;
if (silId == 0) {
const whId = findIdByRoughMatch(scannedValues, "warehouseId").number ?? 0;
setScanResult({...scanResult, stockInLineId: whId, value: whId.toString()});
} else { setScanResult({...scanResult, stockInLineId: silId, value: silId.toString()}); }

resetQrCodeScanner(String(error));
}

// resetQrCodeScanner();
}
}, [qrCodeScannerValues]);

return (
<QrCodeScannerContext.Provider
value={{
@@ -99,6 +200,7 @@ const QrCodeScannerProvider: React.FC<QrCodeScannerProviderProps> = ({
startScan: startQrCodeScanner,
stopScan: endQrCodeScanner,
resetScan: resetQrCodeScanner,
result: scanResult,
}}
>
{children}


+ 45
- 0
src/theme/devias-material-kit/components.ts Bestand weergeven

@@ -150,10 +150,37 @@ const components: ThemeOptions["components"] = {
width: "100%",
zIndex: 2000,
},
".swal2-custom-zindex": {
zIndex: 10000, // Set z-index for SweetAlert2 modals
},
},
},
MuiInputBase: {
styleOverrides: {
root: {
"&:not(.Mui-disabled)": {
backgroundColor: "rgba(200, 230, 255, 0.2)", // Slightly cyan-ish background
"&:hover": {
backgroundColor: "rgba(200, 230, 255, 0.25)", // Slightly darker on hover
},
"&.Mui-focused": {
backgroundColor: "rgba(200, 230, 255, 0.3)", // More pronounced on focus
},
},
"&.Mui-disabled": {
backgroundColor: "#ffffff", // White background
opacity: 1, // Remove MUI's default opacity reduction
"& .MuiInputBase-input": {
color: "#000", // Black text
cursor: "default", // Default cursor
WebkitTextFillColor: "#000", // Ensure text color isn't grayed out in WebKit browsers
},
"& fieldset": {
backgroundColor: "transparent", // Ensure no extra background effects
boxShadow: "none", // Remove any box-shadow
},
},
},
input: {
"&::placeholder": {
opacity: 1,
@@ -244,6 +271,17 @@ const components: ThemeOptions["components"] = {
boxShadow: `${palette.error.main} 0 0 0 2px`,
},
},
"&:not(.Mui-disabled)": {
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: "rgba(0, 0, 0, 0.6)", // Darker border on hover
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: "rgba(0, 0, 0, 0.7)", // Darkest border when focused
},
},
"&.Mui-disabled .MuiOutlinedInput-notchedOutline": {
border: "1px solid #ccc", // Simple gray border for disabled
},
},
input: {
fontSize: defaultFontSize,
@@ -278,6 +316,13 @@ const components: ThemeOptions["components"] = {
background: palette.primary.contrastText,
},
},
"&.Mui-disabled": {
color: "rgba(0, 0, 0, 0.6)", // Black label
transform: "translate(14px, 16px) scale(1)", // Position like placeholder
"&.Mui-focused": {
transform: "translate(14px, 16px) scale(1)", // Keep label in place when "focused"
},
},
},
},
},


Laden…
Annuleren
Opslaan