|
- "use client";
- import React, { useState, useRef, useEffect } from 'react';
- import { Material, MaterialDatabase } from './types';
- import { Box, Typography, TextField, Paper, Stack, Button, IconButton, Chip } from '@mui/material';
- import CheckIcon from '@mui/icons-material/Check';
- import CloseIcon from '@mui/icons-material/Close';
-
- interface MaterialLotScannerProps {
- materials: Material[];
- onMaterialsChange: (materials: Material[]) => void;
- error?: string;
- }
-
-
- const MaterialLotScanner: React.FC<MaterialLotScannerProps> = ({
- materials,
- onMaterialsChange,
- error
- }) => {
- const [materialScanInput, setMaterialScanInput] = useState<string>('');
- const materialScanRef = useRef<HTMLInputElement>(null);
-
- useEffect(() => {
- if (materialScanRef.current) {
- materialScanRef.current.focus();
- }
- }, []);
-
- const handleMaterialInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- setMaterialScanInput(e.target.value.trim());
- };
-
- const handleMaterialInputKeyPress = async (e: React.KeyboardEvent<HTMLInputElement>) => {
- if (e.key === 'Enter') {
- const target = e.target as HTMLInputElement;
- const scannedLot = target.value.trim();
- if (scannedLot) {
- const response = await fetch('http://your-backend-url.com/validateLot', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({ lot: scannedLot })
- });
- const data = await response.json();
- if (data.suggestedLot) {
- const updatedMaterials = materials.map(material => {
- if (material.name === data.matchedMaterial.name) {
- const isAlreadyAdded = material.lotNumbers.includes(scannedLot);
- if (!isAlreadyAdded) {
- return {
- ...material,
- isUsed: true,
- lotNumbers: [...material.lotNumbers, scannedLot]
- };
- }
- }
- return material;
- });
- onMaterialsChange(updatedMaterials);
- setMaterialScanInput('');
- } else if (data.matchedMaterial) {
- setMaterialScanInput(scannedLot + ' (Invalid lot number format. Suggested lot number: ' + data.suggestedLot + ')');
- } else {
- setMaterialScanInput(scannedLot + ' (Invalid lot number format or material not recognized.)');
- }
- }
- }
- };
-
- const removeLotNumber = (materialName: string, lotNumber: string): void => {
- const updatedMaterials = materials.map(material => {
- if (material.name === materialName) {
- const updatedLotNumbers = material.lotNumbers.filter(lot => lot !== lotNumber);
- return {
- ...material,
- lotNumbers: updatedLotNumbers,
- isUsed: updatedLotNumbers.length > 0
- };
- }
- return material;
- });
- onMaterialsChange(updatedMaterials);
- };
-
- const requiredMaterials = materials.filter(m => m.required);
- const optionalMaterials = materials.filter(m => !m.required);
-
- return (
- <Box>
- <Typography variant="h6" fontWeight={600} mb={2}>
- Material Lot Numbers
- </Typography>
- <Paper elevation={2} sx={{ mb: 2, p: 2, bgcolor: 'yellow.50', border: '1px solid', borderColor: 'yellow.200' }}>
- <TextField
- inputRef={materialScanRef}
- type="text"
- value={materialScanInput}
- onChange={handleMaterialInputChange}
- onKeyPress={handleMaterialInputKeyPress}
- fullWidth
- label="Scan or enter material lot number (e.g., SS-240616-001)"
- variant="outlined"
- size="small"
- sx={{ bgcolor: 'white' }}
- />
- <Box mt={2}>
- <Typography variant="body2" color="warning.main">
- <strong>Lot Number Formats:</strong>
- </Typography>
- <Typography variant="body2" color="warning.main">
- Steel Sheet: SS-YYMMDD-XXX | Aluminum: AL-YYMMDD-XXX | Plastic: PP-YYMMDD-XXX
- </Typography>
- <Typography variant="body2" color="warning.main">
- Copper Wire: CW-YYMMDD-XXX | Rubber: RG-YYMMDD-XXX | Glass: GP-YYMMDD-XXX
- </Typography>
- </Box>
- </Paper>
- {error && <Typography color="error" variant="body2" mb={2}>{error}</Typography>}
- <Stack spacing={3}>
- {/* Required Materials */}
- <Box>
- <Stack direction="row" alignItems="center" spacing={1} mb={1}>
- <Typography variant="subtitle1" fontWeight={600} color="error.main">
- Required Materials
- </Typography>
- <Chip label="Must scan lot numbers" color="error" size="small" />
- </Stack>
- <Stack spacing={1}>
- {requiredMaterials.map((material) => (
- <Paper key={material.id} sx={{ p: 2, bgcolor: 'red.50', border: '1px solid', borderColor: 'red.200' }}>
- <Stack direction="row" alignItems="center" justifyContent="space-between" mb={1}>
- <Stack direction="row" alignItems="center" spacing={1}>
- {material.isUsed && <CheckIcon fontSize="small" color="success" />}
- <Typography fontWeight={500}>{material.name}</Typography>
- </Stack>
- <Typography variant="body2" color="text.secondary">
- {material.lotNumbers.length} lot(s)
- </Typography>
- </Stack>
- {material.lotNumbers.length > 0 && (
- <Stack spacing={1}>
- {material.lotNumbers.map((lotNumber, index) => (
- <Paper key={index} sx={{ p: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between', bgcolor: 'white', border: '1px solid', borderColor: 'grey.200' }}>
- <Typography variant="body2" fontFamily="monospace">{lotNumber}</Typography>
- <IconButton onClick={() => removeLotNumber(material.name, lotNumber)} color="error" size="small">
- <CloseIcon fontSize="small" />
- </IconButton>
- </Paper>
- ))}
- </Stack>
- )}
- </Paper>
- ))}
- </Stack>
- </Box>
- {/* Optional Materials */}
- <Box>
- <Stack direction="row" alignItems="center" spacing={1} mb={1}>
- <Typography variant="subtitle1" fontWeight={600} color="primary.main">
- Optional Materials
- </Typography>
- <Chip label="Lot numbers recommended" color="primary" size="small" />
- </Stack>
- <Stack spacing={1}>
- {optionalMaterials.map((material) => (
- <Paper key={material.id} sx={{ p: 2, bgcolor: 'blue.50', border: '1px solid', borderColor: 'blue.200' }}>
- <Stack direction="row" alignItems="center" justifyContent="space-between" mb={1}>
- <Stack direction="row" alignItems="center" spacing={1}>
- {material.isUsed && <CheckIcon fontSize="small" color="success" />}
- <Typography fontWeight={500}>{material.name}</Typography>
- </Stack>
- <Typography variant="body2" color="text.secondary">
- {material.lotNumbers.length} lot(s)
- </Typography>
- </Stack>
- {material.lotNumbers.length > 0 && (
- <Stack spacing={1}>
- {material.lotNumbers.map((lotNumber, index) => (
- <Paper key={index} sx={{ p: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between', bgcolor: 'white', border: '1px solid', borderColor: 'grey.200' }}>
- <Typography variant="body2" fontFamily="monospace">{lotNumber}</Typography>
- <IconButton onClick={() => removeLotNumber(material.name, lotNumber)} color="error" size="small">
- <CloseIcon fontSize="small" />
- </IconButton>
- </Paper>
- ))}
- </Stack>
- )}
- </Paper>
- ))}
- </Stack>
- </Box>
- </Stack>
- </Box>
- );
- };
-
- export default MaterialLotScanner;
|