144 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			144 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | import React, { useState, useEffect } from 'react'; | ||
|  | import { Modal, Box, Typography, TextField, Button, CircularProgress, Alert } from '@mui/material'; | ||
|  | import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto'; | ||
|  | import type { CreatePlantaDto } from '../../models/dtos/Impresion/CreatePlantaDto'; | ||
|  | import type { UpdatePlantaDto } from '../../models/dtos/Impresion/UpdatePlantaDto'; | ||
|  | 
 | ||
|  | const modalStyle = { /* ... (mismo estilo que otros modales) ... */ | ||
|  |     position: 'absolute' as 'absolute', | ||
|  |     top: '50%', | ||
|  |     left: '50%', | ||
|  |     transform: 'translate(-50%, -50%)', | ||
|  |     width: 400, | ||
|  |     bgcolor: 'background.paper', | ||
|  |     border: '2px solid #000', | ||
|  |     boxShadow: 24, | ||
|  |     p: 4, | ||
|  | }; | ||
|  | 
 | ||
|  | interface PlantaFormModalProps { | ||
|  |   open: boolean; | ||
|  |   onClose: () => void; | ||
|  |   onSubmit: (data: CreatePlantaDto | (UpdatePlantaDto & { idPlanta: number })) => Promise<void>; | ||
|  |   initialData?: PlantaDto | null; | ||
|  |   errorMessage?: string | null; | ||
|  |   clearErrorMessage: () => void; | ||
|  | } | ||
|  | 
 | ||
|  | const PlantaFormModal: React.FC<PlantaFormModalProps> = ({ | ||
|  |   open, | ||
|  |   onClose, | ||
|  |   onSubmit, | ||
|  |   initialData, | ||
|  |   errorMessage, | ||
|  |   clearErrorMessage | ||
|  | }) => { | ||
|  |   const [nombre, setNombre] = useState(''); | ||
|  |   const [detalle, setDetalle] = useState(''); // Detalle es string, no opcional según la BD
 | ||
|  |   const [loading, setLoading] = useState(false); | ||
|  |   const [localErrorNombre, setLocalErrorNombre] = useState<string | null>(null); | ||
|  |   const [localErrorDetalle, setLocalErrorDetalle] = useState<string | null>(null); | ||
|  | 
 | ||
|  |   const isEditing = Boolean(initialData); | ||
|  | 
 | ||
|  |   useEffect(() => { | ||
|  |     if (open) { | ||
|  |         setNombre(initialData?.nombre || ''); | ||
|  |         setDetalle(initialData?.detalle || ''); // Inicializar detalle
 | ||
|  |         setLocalErrorNombre(null); | ||
|  |         setLocalErrorDetalle(null); | ||
|  |         clearErrorMessage(); | ||
|  |     } | ||
|  |   }, [open, initialData, clearErrorMessage]); | ||
|  | 
 | ||
|  |    const handleInputChange = (field: 'nombre' | 'detalle') => { | ||
|  |       if (field === 'nombre' && localErrorNombre) setLocalErrorNombre(null); | ||
|  |       if (field === 'detalle' && localErrorDetalle) setLocalErrorDetalle(null); | ||
|  |       if (errorMessage) clearErrorMessage(); | ||
|  |   }; | ||
|  | 
 | ||
|  |   const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => { | ||
|  |     event.preventDefault(); | ||
|  |     setLocalErrorNombre(null); | ||
|  |     setLocalErrorDetalle(null); | ||
|  |     clearErrorMessage(); | ||
|  | 
 | ||
|  |     let hasError = false; | ||
|  |     if (!nombre.trim()) { | ||
|  |         setLocalErrorNombre('El nombre es obligatorio.'); | ||
|  |         hasError = true; | ||
|  |     } | ||
|  |     if (!detalle.trim()) { // Detalle también es requerido según la BD
 | ||
|  |         setLocalErrorDetalle('El detalle es obligatorio.'); | ||
|  |         hasError = true; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (hasError) return; | ||
|  | 
 | ||
|  |     setLoading(true); | ||
|  |     try { | ||
|  |       const dataToSubmit = { nombre, detalle }; // Detalle siempre se envía
 | ||
|  | 
 | ||
|  |       if (isEditing && initialData) { | ||
|  |         await onSubmit({ ...dataToSubmit, idPlanta: initialData.idPlanta }); | ||
|  |       } else { | ||
|  |         await onSubmit(dataToSubmit as CreatePlantaDto); | ||
|  |       } | ||
|  |       onClose(); | ||
|  |     } catch (error: any) { | ||
|  |       console.error("Error en submit de PlantaFormModal:", error); | ||
|  |       // El error API se muestra vía 'errorMessage'
 | ||
|  |     } finally { | ||
|  |        setLoading(false); | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   return ( | ||
|  |     <Modal open={open} onClose={onClose}> | ||
|  |       <Box sx={modalStyle}> | ||
|  |         <Typography variant="h6" component="h2"> | ||
|  |           {isEditing ? 'Editar Planta de Impresión' : 'Agregar Nueva Planta de Impresión'} | ||
|  |         </Typography> | ||
|  |         <Box component="form" onSubmit={handleSubmit} sx={{ mt: 2 }}> | ||
|  |           <TextField | ||
|  |             label="Nombre" | ||
|  |             fullWidth | ||
|  |             required | ||
|  |             value={nombre} | ||
|  |             onChange={(e) => { setNombre(e.target.value); handleInputChange('nombre'); }} | ||
|  |             margin="normal" | ||
|  |             error={!!localErrorNombre} | ||
|  |             helperText={localErrorNombre || ''} | ||
|  |             disabled={loading} | ||
|  |             autoFocus | ||
|  |           /> | ||
|  |           <TextField | ||
|  |             label="Detalle" // Ya no es opcional
 | ||
|  |             fullWidth | ||
|  |             required // Marcar como requerido
 | ||
|  |             value={detalle} | ||
|  |             onChange={(e) => { setDetalle(e.target.value); handleInputChange('detalle'); }} | ||
|  |             margin="normal" | ||
|  |             multiline | ||
|  |             rows={3} | ||
|  |             error={!!localErrorDetalle} // Añadir manejo de error para detalle
 | ||
|  |             helperText={localErrorDetalle || ''} // Mostrar error de detalle
 | ||
|  |             disabled={loading} | ||
|  |           /> | ||
|  |           {errorMessage && <Alert severity="error" sx={{ mt: 1 }}>{errorMessage}</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}> | ||
|  |               {loading ? <CircularProgress size={24} /> : (isEditing ? 'Guardar Cambios' : 'Agregar')} | ||
|  |             </Button> | ||
|  |           </Box> | ||
|  |         </Box> | ||
|  |       </Box> | ||
|  |     </Modal> | ||
|  |   ); | ||
|  | }; | ||
|  | 
 | ||
|  | export default PlantaFormModal; |