import React, { useState, useEffect, useCallback } from 'react'; import { Modal, Box, Typography, TextField, Button, CircularProgress, Alert, FormControl, InputLabel, Select, MenuItem, RadioGroup, FormControlLabel, Radio, InputAdornment } from '@mui/material'; import type { NotaCreditoDebitoDto } from '../../../models/dtos/Contables/NotaCreditoDebitoDto'; import type { CreateNotaDto } from '../../../models/dtos/Contables/CreateNotaDto'; import type { UpdateNotaDto } from '../../../models/dtos/Contables/UpdateNotaDto'; import type { EmpresaDto } from '../../../models/dtos/Distribucion/EmpresaDto'; import type { DistribuidorDto } from '../../../models/dtos/Distribucion/DistribuidorDto'; import type { CanillaDto } from '../../../models/dtos/Distribucion/CanillaDto'; // Para el dropdown import empresaService from '../../../services/Distribucion/empresaService'; import distribuidorService from '../../../services/Distribucion/distribuidorService'; import canillaService from '../../../services/Distribucion/canillaService'; // Para cargar canillitas const modalStyle = { /* ... (mismo estilo) ... */ position: 'absolute' as 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', width: { xs: '90%', sm: 550 }, bgcolor: 'background.paper', border: '2px solid #000', boxShadow: 24, p: 4, maxHeight: '90vh', overflowY: 'auto' }; type DestinoType = 'Distribuidores' | 'Canillas'; type TipoNotaType = 'Credito' | 'Debito'; interface NotaCreditoDebitoFormModalProps { open: boolean; onClose: () => void; onSubmit: (data: CreateNotaDto | UpdateNotaDto, idNota?: number) => Promise; initialData?: NotaCreditoDebitoDto | null; errorMessage?: string | null; clearErrorMessage: () => void; } const NotaCreditoDebitoFormModal: React.FC = ({ open, onClose, onSubmit, initialData, errorMessage, clearErrorMessage }) => { const [destino, setDestino] = useState('Distribuidores'); const [idDestino, setIdDestino] = useState(''); const [referencia, setReferencia] = useState(''); const [tipo, setTipo] = useState('Credito'); const [fecha, setFecha] = useState(new Date().toISOString().split('T')[0]); const [monto, setMonto] = useState(''); const [observaciones, setObservaciones] = useState(''); const [idEmpresa, setIdEmpresa] = useState(''); const [destinatarios, setDestinatarios] = useState<(DistribuidorDto | CanillaDto)[]>([]); const [empresas, setEmpresas] = useState([]); const [loading, setLoading] = useState(false); const [loadingDropdowns, setLoadingDropdowns] = useState(false); const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({}); const isEditing = Boolean(initialData); const fetchEmpresas = useCallback(async () => { setLoadingDropdowns(true); try { const data = await empresaService.getAllEmpresas(); setEmpresas(data); } catch (error) { console.error("Error al cargar empresas", error); setLocalErrors(prev => ({...prev, dropdowns: 'Error al cargar empresas.'})); } finally { setLoadingDropdowns(false); } }, []); const fetchDestinatarios = useCallback(async (tipoDestino: DestinoType) => { setLoadingDropdowns(true); setIdDestino(''); // Resetear selección de destinatario al cambiar tipo setDestinatarios([]); try { if (tipoDestino === 'Distribuidores') { const data = await distribuidorService.getAllDistribuidores(); setDestinatarios(data); } else if (tipoDestino === 'Canillas') { const data = await canillaService.getAllCanillas(undefined, undefined, true); // Solo activos setDestinatarios(data); } } catch (error) { console.error(`Error al cargar ${tipoDestino}`, error); setLocalErrors(prev => ({...prev, dropdowns: `Error al cargar ${tipoDestino}.`})); } finally { setLoadingDropdowns(false); } }, []); useEffect(() => { if (open) { fetchEmpresas(); // Cargar destinatarios basados en el initialData o el default const initialDestinoType = initialData?.destino || 'Distribuidores'; setDestino(initialDestinoType as DestinoType); fetchDestinatarios(initialDestinoType as DestinoType); setIdDestino(initialData?.idDestino || ''); setReferencia(initialData?.referencia || ''); setTipo(initialData?.tipo as TipoNotaType || 'Credito'); setFecha(initialData?.fecha || new Date().toISOString().split('T')[0]); setMonto(initialData?.monto?.toString() || ''); setObservaciones(initialData?.observaciones || ''); setIdEmpresa(initialData?.idEmpresa || ''); setLocalErrors({}); clearErrorMessage(); } }, [open, initialData, clearErrorMessage, fetchEmpresas, fetchDestinatarios]); useEffect(() => { if(open && !isEditing) { // Solo cambiar destinatarios si es creación y cambia el tipo de Destino fetchDestinatarios(destino); } }, [destino, open, isEditing, fetchDestinatarios]); const validate = (): boolean => { const errors: { [key: string]: string | null } = {}; if (!destino) errors.destino = 'Seleccione un tipo de destino.'; if (!idDestino) errors.idDestino = 'Seleccione un destinatario.'; if (!tipo) errors.tipo = 'Seleccione el tipo de nota.'; 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.'; if (!monto.trim() || isNaN(parseFloat(monto)) || parseFloat(monto) <= 0) errors.monto = 'Monto debe ser un número positivo.'; if (!idEmpresa) errors.idEmpresa = 'Seleccione una empresa (para el saldo).'; 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) => { event.preventDefault(); clearErrorMessage(); if (!validate()) return; setLoading(true); try { const montoNum = parseFloat(monto); if (isEditing && initialData) { const dataToSubmit: UpdateNotaDto = { monto: montoNum, observaciones: observaciones || undefined, }; await onSubmit(dataToSubmit, initialData.idNota); } else { const dataToSubmit: CreateNotaDto = { destino, idDestino: Number(idDestino), referencia: referencia || undefined, tipo, fecha, monto: montoNum, observaciones: observaciones || undefined, idEmpresa: Number(idEmpresa), }; await onSubmit(dataToSubmit); } onClose(); } catch (error: any) { console.error("Error en submit de NotaCreditoDebitoFormModal:", error); } finally { setLoading(false); } }; return ( {isEditing ? 'Editar Nota de Crédito/Débito' : 'Registrar Nota de Crédito/Débito'} Destino {setDestino(e.target.value as DestinoType); handleInputChange('destino'); }}> } label="Distribuidor" disabled={loading || isEditing}/> } label="Canillita" disabled={loading || isEditing}/> Destinatario {localErrors.idDestino && {localErrors.idDestino}} Empresa (del Saldo) {localErrors.idEmpresa && {localErrors.idEmpresa}} {setFecha(e.target.value); handleInputChange('fecha');}} margin="dense" fullWidth error={!!localErrors.fecha} helperText={localErrors.fecha || ''} disabled={loading || isEditing} InputLabelProps={{ shrink: true }} autoFocus={!isEditing} /> setReferencia(e.target.value)} margin="dense" fullWidth disabled={loading || isEditing} /> Tipo de Nota {setTipo(e.target.value as TipoNotaType); handleInputChange('tipo');}} > } label="Crédito" disabled={loading || isEditing}/> } label="Débito" disabled={loading || isEditing}/> {localErrors.tipo && {localErrors.tipo}} {setMonto(e.target.value); handleInputChange('monto');}} margin="dense" fullWidth error={!!localErrors.monto} helperText={localErrors.monto || ''} disabled={loading} inputProps={{step: "0.01", min:0.05, lang:"es-AR" }} InputProps={{ startAdornment: $ }} /> setObservaciones(e.target.value)} margin="dense" fullWidth multiline rows={2} disabled={loading} /> {errorMessage && {errorMessage}} {localErrors.dropdowns && {localErrors.dropdowns}} ); }; export default NotaCreditoDebitoFormModal;