Ya perdí el hilo de los cambios pero ahi van.
This commit is contained in:
		| @@ -0,0 +1,201 @@ | ||||
| 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} | ||||
|                 /> | ||||
|                 <TextField label="Entrada (Devolución Total)" type="number" value={entrada} required | ||||
|                     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}} | ||||
|                 /> | ||||
|                  <TextField label="Sin Cargo" type="number" value={sinCargo} required | ||||
|                     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; | ||||
		Reference in New Issue
	
	Block a user