FPSMS-frontend
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

138 lines
4.6 KiB

  1. "use client";
  2. import React, { useState, useRef } from 'react';
  3. import { Operator } from './types';
  4. import { Button, TextField, Typography, Paper, Box, IconButton, Stack } from '@mui/material';
  5. import CloseIcon from '@mui/icons-material/Close';
  6. interface OperatorScannerProps {
  7. operators: Operator[];
  8. onOperatorsChange: (operators: Operator[]) => void;
  9. error?: string;
  10. }
  11. const operatorDatabase: Operator[] = [
  12. { id: 1, name: 'John Smith', employeeId: 'EMP001', cardId: '12345678' },
  13. { id: 2, name: 'Maria Garcia', employeeId: 'EMP002', cardId: '23456789' },
  14. { id: 3, name: 'David Chen', employeeId: 'EMP003', cardId: '34567890' },
  15. { id: 4, name: 'Sarah Johnson', employeeId: 'EMP004', cardId: '45678901' },
  16. { id: 5, name: 'Mike Wilson', employeeId: 'EMP005', cardId: '56789012' }
  17. ];
  18. const OperatorScanner: React.FC<OperatorScannerProps> = ({
  19. operators,
  20. onOperatorsChange,
  21. error
  22. }) => {
  23. const [scanningMode, setScanningMode] = useState<boolean>(false);
  24. const operatorScanRef = useRef<HTMLInputElement>(null);
  25. const startScanning = (): void => {
  26. setScanningMode(true);
  27. setTimeout(() => {
  28. if (operatorScanRef.current) {
  29. operatorScanRef.current.focus();
  30. }
  31. }, 100);
  32. };
  33. const stopScanning = (): void => {
  34. setScanningMode(false);
  35. };
  36. const handleOperatorScan = (e: React.KeyboardEvent<HTMLInputElement>): void => {
  37. if (e.key === 'Enter') {
  38. const target = e.target as HTMLInputElement;
  39. const scannedId = target.value.trim();
  40. const operator = operatorDatabase.find(op =>
  41. op.cardId === scannedId || op.employeeId === scannedId
  42. );
  43. if (operator) {
  44. const isAlreadyAdded = operators.some(op => op.id === operator.id);
  45. if (!isAlreadyAdded) {
  46. onOperatorsChange([...operators, operator]);
  47. }
  48. target.value = '';
  49. stopScanning();
  50. } else {
  51. alert('Operator not found. Please check the ID and try again.');
  52. target.value = '';
  53. }
  54. }
  55. };
  56. const removeOperator = (operatorId: number): void => {
  57. onOperatorsChange(operators.filter(op => op.id !== operatorId));
  58. };
  59. return (
  60. <Box>
  61. <Stack direction="row" alignItems="center" justifyContent="space-between" mb={2}>
  62. <Typography variant="h6" fontWeight={600}>
  63. Operators *
  64. </Typography>
  65. <Button
  66. variant={scanningMode ? 'contained' : 'outlined'}
  67. color={scanningMode ? 'success' : 'primary'}
  68. onClick={startScanning}
  69. >
  70. {scanningMode ? 'Scanning...' : 'Scan ID Card'}
  71. </Button>
  72. </Stack>
  73. {scanningMode && (
  74. <Paper elevation={2} sx={{ mb: 2, p: 2, bgcolor: 'green.50', border: '1px solid', borderColor: 'green.200' }}>
  75. <Stack direction="row" alignItems="center" spacing={2}>
  76. <TextField
  77. inputRef={operatorScanRef}
  78. type="text"
  79. onKeyPress={handleOperatorScan}
  80. fullWidth
  81. label="Scan operator ID card or enter manually..."
  82. variant="outlined"
  83. size="small"
  84. sx={{ bgcolor: 'white' }}
  85. />
  86. <Button
  87. variant="contained"
  88. color="inherit"
  89. onClick={stopScanning}
  90. >
  91. Cancel
  92. </Button>
  93. </Stack>
  94. <Typography variant="body2" color="success.main" mt={1}>
  95. Position the ID card scanner and scan, or type the employee ID manually
  96. </Typography>
  97. </Paper>
  98. )}
  99. {error && <Typography color="error" variant="body2" mb={1}>{error}</Typography>}
  100. <Stack spacing={1}>
  101. {operators.map((operator) => (
  102. <Paper key={operator.id} sx={{ p: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', bgcolor: 'blue.50', border: '1px solid', borderColor: 'blue.200' }}>
  103. <Box>
  104. <Typography fontWeight={500} color="primary.dark">{operator.name}</Typography>
  105. <Typography variant="body2" color="primary.main">{operator.employeeId}</Typography>
  106. </Box>
  107. <IconButton onClick={() => removeOperator(operator.id)} color="error">
  108. <CloseIcon />
  109. </IconButton>
  110. </Paper>
  111. ))}
  112. {operators.length === 0 && (
  113. <Paper sx={{ p: 2, bgcolor: 'grey.100', border: '1px solid', borderColor: 'grey.200' }}>
  114. <Typography color="text.secondary" fontStyle="italic" variant="body2">
  115. No operators added yet. Use the scan button to add operators.
  116. </Typography>
  117. </Paper>
  118. )}
  119. </Stack>
  120. </Box>
  121. );
  122. };
  123. export default OperatorScanner;