| 
									
										
										
										
											2025-05-23 15:47:39 -03:00
										 |  |  | import React, { useState, useEffect } from 'react'; | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |     Modal, Box, Typography, TextField, Button, CircularProgress, Alert, | 
					
						
							|  |  |  |     FormControl, InputLabel, Select, MenuItem | 
					
						
							|  |  |  | } from '@mui/material'; | 
					
						
							|  |  |  | import type { ControlDevolucionesDto } from '../../../models/dtos/Distribucion/ControlDevolucionesDto'; | 
					
						
							|  |  |  | import type { CreateControlDevolucionesDto } from '../../../models/dtos/Distribucion/CreateControlDevolucionesDto'; | 
					
						
							|  |  |  | import type { UpdateControlDevolucionesDto } from '../../../models/dtos/Distribucion/UpdateControlDevolucionesDto'; | 
					
						
							|  |  |  | import type { EmpresaDto } from '../../../models/dtos/Distribucion/EmpresaDto'; // DTO de Empresa
 | 
					
						
							|  |  |  | import empresaService from '../../../services//Distribucion/empresaService'; // Servicio de Empresa
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const modalStyle = { /* ... (mismo estilo) ... */ | 
					
						
							|  |  |  |     position: 'absolute' as 'absolute', | 
					
						
							|  |  |  |     top: '50%', | 
					
						
							|  |  |  |     left: '50%', | 
					
						
							|  |  |  |     transform: 'translate(-50%, -50%)', | 
					
						
							|  |  |  |     width: { xs: '90%', sm: 500 }, | 
					
						
							|  |  |  |     bgcolor: 'background.paper', | 
					
						
							|  |  |  |     border: '2px solid #000', | 
					
						
							|  |  |  |     boxShadow: 24, | 
					
						
							|  |  |  |     p: 4, | 
					
						
							|  |  |  |     maxHeight: '90vh', | 
					
						
							|  |  |  |     overflowY: 'auto' | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface ControlDevolucionesFormModalProps { | 
					
						
							|  |  |  |   open: boolean; | 
					
						
							|  |  |  |   onClose: () => void; | 
					
						
							|  |  |  |   onSubmit: (data: CreateControlDevolucionesDto | UpdateControlDevolucionesDto, idControl?: number) => Promise<void>; | 
					
						
							|  |  |  |   initialData?: ControlDevolucionesDto | null; | 
					
						
							|  |  |  |   errorMessage?: string | null; | 
					
						
							|  |  |  |   clearErrorMessage: () => void; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ControlDevolucionesFormModal: React.FC<ControlDevolucionesFormModalProps> = ({ | 
					
						
							|  |  |  |   open, | 
					
						
							|  |  |  |   onClose, | 
					
						
							|  |  |  |   onSubmit, | 
					
						
							|  |  |  |   initialData, | 
					
						
							|  |  |  |   errorMessage, | 
					
						
							|  |  |  |   clearErrorMessage | 
					
						
							|  |  |  | }) => { | 
					
						
							|  |  |  |   const [idEmpresa, setIdEmpresa] = useState<number | string>(''); | 
					
						
							|  |  |  |   const [fecha, setFecha] = useState<string>(new Date().toISOString().split('T')[0]); | 
					
						
							|  |  |  |   const [entrada, setEntrada] = useState<string>(''); | 
					
						
							|  |  |  |   const [sobrantes, setSobrantes] = useState<string>(''); | 
					
						
							|  |  |  |   const [detalle, setDetalle] = useState(''); | 
					
						
							|  |  |  |   const [sinCargo, setSinCargo] = useState<string>('0'); // Default 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const [empresas, setEmpresas] = useState<EmpresaDto[]>([]); | 
					
						
							|  |  |  |   const [loading, setLoading] = useState(false); | 
					
						
							|  |  |  |   const [loadingEmpresas, setLoadingEmpresas] = useState(false); | 
					
						
							|  |  |  |   const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const isEditing = Boolean(initialData); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     const fetchEmpresas = async () => { | 
					
						
							|  |  |  |         setLoadingEmpresas(true); | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             const data = await empresaService.getAllEmpresas(); | 
					
						
							|  |  |  |             setEmpresas(data); | 
					
						
							|  |  |  |         } catch (error) { | 
					
						
							|  |  |  |             console.error("Error al cargar empresas", error); | 
					
						
							|  |  |  |             setLocalErrors(prev => ({...prev, empresas: 'Error al cargar empresas.'})); | 
					
						
							|  |  |  |         } finally { | 
					
						
							|  |  |  |             setLoadingEmpresas(false); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (open) { | 
					
						
							|  |  |  |         fetchEmpresas(); | 
					
						
							|  |  |  |         setIdEmpresa(initialData?.idEmpresa || ''); | 
					
						
							|  |  |  |         setFecha(initialData?.fecha || new Date().toISOString().split('T')[0]); | 
					
						
							|  |  |  |         setEntrada(initialData?.entrada?.toString() || '0'); | 
					
						
							|  |  |  |         setSobrantes(initialData?.sobrantes?.toString() || '0'); | 
					
						
							|  |  |  |         setDetalle(initialData?.detalle || ''); | 
					
						
							|  |  |  |         setSinCargo(initialData?.sinCargo?.toString() || '0'); | 
					
						
							|  |  |  |         setLocalErrors({}); | 
					
						
							|  |  |  |         clearErrorMessage(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }, [open, initialData, clearErrorMessage]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const validate = (): boolean => { | 
					
						
							|  |  |  |     const errors: { [key: string]: string | null } = {}; | 
					
						
							|  |  |  |     if (!idEmpresa) errors.idEmpresa = 'Seleccione una empresa.'; | 
					
						
							|  |  |  |     if (!fecha.trim()) errors.fecha = 'La fecha es obligatoria.'; | 
					
						
							|  |  |  |     else if (!/^\d{4}-\d{2}-\d{2}$/.test(fecha)) errors.fecha = 'Formato de fecha inválido.'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const entradaNum = parseInt(entrada, 10); | 
					
						
							|  |  |  |     const sobrantesNum = parseInt(sobrantes, 10); | 
					
						
							|  |  |  |     const sinCargoNum = parseInt(sinCargo, 10); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (entrada.trim() === '' || isNaN(entradaNum) || entradaNum < 0) errors.entrada = 'Entrada debe ser un número >= 0.'; | 
					
						
							|  |  |  |     if (sobrantes.trim() === '' || isNaN(sobrantesNum) || sobrantesNum < 0) errors.sobrantes = 'Sobrantes debe ser un número >= 0.'; | 
					
						
							|  |  |  |     if (sinCargo.trim() === '' || isNaN(sinCargoNum) || sinCargoNum < 0) errors.sinCargo = 'Sin Cargo debe ser un número >= 0.'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setLocalErrors(errors); | 
					
						
							|  |  |  |     return Object.keys(errors).length === 0; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleInputChange = (fieldName: string) => { | 
					
						
							|  |  |  |     if (localErrors[fieldName]) setLocalErrors(prev => ({ ...prev, [fieldName]: null })); | 
					
						
							|  |  |  |     if (errorMessage) clearErrorMessage(); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => { | 
					
						
							|  |  |  |     event.preventDefault(); | 
					
						
							|  |  |  |     clearErrorMessage(); | 
					
						
							|  |  |  |     if (!validate()) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setLoading(true); | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       const commonData = { | 
					
						
							|  |  |  |         entrada: parseInt(entrada, 10), | 
					
						
							|  |  |  |         sobrantes: parseInt(sobrantes, 10), | 
					
						
							|  |  |  |         detalle: detalle || undefined, | 
					
						
							|  |  |  |         sinCargo: parseInt(sinCargo, 10), | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (isEditing && initialData) { | 
					
						
							|  |  |  |         const dataToSubmit: UpdateControlDevolucionesDto = { ...commonData }; | 
					
						
							|  |  |  |         await onSubmit(dataToSubmit, initialData.idControl); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         const dataToSubmit: CreateControlDevolucionesDto = { | 
					
						
							|  |  |  |             ...commonData, | 
					
						
							|  |  |  |             idEmpresa: Number(idEmpresa), | 
					
						
							|  |  |  |             fecha, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         await onSubmit(dataToSubmit); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       onClose(); | 
					
						
							|  |  |  |     } catch (error: any) { | 
					
						
							|  |  |  |       console.error("Error en submit de ControlDevolucionesFormModal:", error); | 
					
						
							|  |  |  |     } finally { | 
					
						
							|  |  |  |        setLoading(false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <Modal open={open} onClose={onClose}> | 
					
						
							|  |  |  |       <Box sx={modalStyle}> | 
					
						
							|  |  |  |         <Typography variant="h6" component="h2" gutterBottom> | 
					
						
							|  |  |  |           {isEditing ? 'Editar Control de Devoluciones' : 'Registrar Control de Devoluciones'} | 
					
						
							|  |  |  |         </Typography> | 
					
						
							|  |  |  |         <Box component="form" onSubmit={handleSubmit} sx={{ mt: 1 }}> | 
					
						
							|  |  |  |             <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}> | 
					
						
							|  |  |  |                 <FormControl fullWidth margin="dense" error={!!localErrors.idEmpresa} required> | 
					
						
							|  |  |  |                     <InputLabel id="empresa-cd-select-label">Empresa</InputLabel> | 
					
						
							|  |  |  |                     <Select labelId="empresa-cd-select-label" label="Empresa" value={idEmpresa} | 
					
						
							|  |  |  |                         onChange={(e) => {setIdEmpresa(e.target.value as number); handleInputChange('idEmpresa');}} | 
					
						
							|  |  |  |                         disabled={loading || loadingEmpresas || isEditing} | 
					
						
							|  |  |  |                     > | 
					
						
							|  |  |  |                         <MenuItem value="" disabled><em>Seleccione</em></MenuItem> | 
					
						
							|  |  |  |                         {empresas.map((e) => (<MenuItem key={e.idEmpresa} value={e.idEmpresa}>{e.nombre}</MenuItem>))} | 
					
						
							|  |  |  |                     </Select> | 
					
						
							|  |  |  |                     {localErrors.idEmpresa && <Typography color="error" variant="caption">{localErrors.idEmpresa}</Typography>} | 
					
						
							|  |  |  |                 </FormControl> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 <TextField label="Fecha" type="date" value={fecha} required | 
					
						
							|  |  |  |                     onChange={(e) => {setFecha(e.target.value); handleInputChange('fecha');}} | 
					
						
							|  |  |  |                     margin="dense" fullWidth error={!!localErrors.fecha} helperText={localErrors.fecha || ''} | 
					
						
							|  |  |  |                     disabled={loading || isEditing} InputLabelProps={{ shrink: true }} autoFocus={!isEditing} | 
					
						
							|  |  |  |                 /> | 
					
						
							| 
									
										
										
										
											2025-06-03 13:45:20 -03:00
										 |  |  |                 <TextField label="Entrada (Por Remito)" type="number" value={entrada} required | 
					
						
							| 
									
										
										
										
											2025-05-23 15:47:39 -03:00
										 |  |  |                     onChange={(e) => {setEntrada(e.target.value); handleInputChange('entrada');}} | 
					
						
							|  |  |  |                     margin="dense" fullWidth error={!!localErrors.entrada} helperText={localErrors.entrada || ''} | 
					
						
							|  |  |  |                     disabled={loading} inputProps={{min:0}} | 
					
						
							|  |  |  |                 /> | 
					
						
							|  |  |  |                  <TextField label="Sobrantes" type="number" value={sobrantes} required | 
					
						
							|  |  |  |                     onChange={(e) => {setSobrantes(e.target.value); handleInputChange('sobrantes');}} | 
					
						
							|  |  |  |                     margin="dense" fullWidth error={!!localErrors.sobrantes} helperText={localErrors.sobrantes || ''} | 
					
						
							|  |  |  |                     disabled={loading} inputProps={{min:0}} | 
					
						
							|  |  |  |                 /> | 
					
						
							| 
									
										
										
										
											2025-06-03 13:45:20 -03:00
										 |  |  |                  <TextField label="Ejemplares Sin Cargo" type="number" value={sinCargo} required | 
					
						
							| 
									
										
										
										
											2025-05-23 15:47:39 -03:00
										 |  |  |                     onChange={(e) => {setSinCargo(e.target.value); handleInputChange('sinCargo');}} | 
					
						
							|  |  |  |                     margin="dense" fullWidth error={!!localErrors.sinCargo} helperText={localErrors.sinCargo || ''} | 
					
						
							|  |  |  |                     disabled={loading} inputProps={{min:0}} | 
					
						
							|  |  |  |                 /> | 
					
						
							|  |  |  |                 <TextField label="Detalle (Opcional)" value={detalle} | 
					
						
							|  |  |  |                     onChange={(e) => setDetalle(e.target.value)} | 
					
						
							|  |  |  |                     margin="dense" fullWidth multiline rows={2} disabled={loading} | 
					
						
							|  |  |  |                 /> | 
					
						
							|  |  |  |             </Box> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           {errorMessage && <Alert severity="error" sx={{ mt: 2, width: '100%' }}>{errorMessage}</Alert>} | 
					
						
							|  |  |  |           {localErrors.empresas && <Alert severity="warning" sx={{ mt: 1 }}>{localErrors.empresas}</Alert>} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end', gap: 1 }}> | 
					
						
							|  |  |  |             <Button onClick={onClose} color="secondary" disabled={loading}>Cancelar</Button> | 
					
						
							|  |  |  |             <Button type="submit" variant="contained" disabled={loading || loadingEmpresas}> | 
					
						
							|  |  |  |               {loading ? <CircularProgress size={24} /> : (isEditing ? 'Guardar Cambios' : 'Registrar Control')} | 
					
						
							|  |  |  |             </Button> | 
					
						
							|  |  |  |           </Box> | 
					
						
							|  |  |  |         </Box> | 
					
						
							|  |  |  |       </Box> | 
					
						
							|  |  |  |     </Modal> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default ControlDevolucionesFormModal; |