163 lines
6.5 KiB
TypeScript
163 lines
6.5 KiB
TypeScript
|
|
import React, { useState, useEffect } from 'react';
|
||
|
|
import {
|
||
|
|
Box, Typography, TextField, Button, CircularProgress, Alert,
|
||
|
|
FormControl, InputLabel, Select, MenuItem, FormControlLabel, Checkbox
|
||
|
|
} from '@mui/material';
|
||
|
|
import type { PublicacionDto } from '../../models/dtos/Distribucion/PublicacionDto';
|
||
|
|
import publicacionService from '../../services/Distribucion/publicacionService';
|
||
|
|
import type { PlantaDto } from '../../models/dtos/Impresion/PlantaDto';
|
||
|
|
import plantaService from '../../services/Impresion/plantaService';
|
||
|
|
|
||
|
|
interface SeleccionaReporteTiradasPublicacionesSeccionesProps {
|
||
|
|
onGenerarReporte: (params: {
|
||
|
|
idPublicacion: number;
|
||
|
|
fechaDesde: string; // Primer día del mes
|
||
|
|
fechaHasta: string; // Último día del mes
|
||
|
|
idPlanta?: number | null;
|
||
|
|
consolidado: boolean;
|
||
|
|
}) => Promise<void>;
|
||
|
|
onCancel: () => void;
|
||
|
|
isLoading?: boolean;
|
||
|
|
apiErrorMessage?: string | null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const SeleccionaReporteTiradasPublicacionesSecciones: React.FC<SeleccionaReporteTiradasPublicacionesSeccionesProps> = ({
|
||
|
|
onGenerarReporte,
|
||
|
|
isLoading,
|
||
|
|
apiErrorMessage
|
||
|
|
}) => {
|
||
|
|
const [idPublicacion, setIdPublicacion] = useState<number | string>('');
|
||
|
|
const [mesAnio, setMesAnio] = useState<string>(new Date().toISOString().substring(0, 7)); // Formato "YYYY-MM"
|
||
|
|
const [idPlanta, setIdPlanta] = useState<number | string>('');
|
||
|
|
const [consolidado, setConsolidado] = useState<boolean>(false);
|
||
|
|
|
||
|
|
const [publicaciones, setPublicaciones] = useState<PublicacionDto[]>([]);
|
||
|
|
const [plantas, setPlantas] = useState<PlantaDto[]>([]);
|
||
|
|
const [loadingDropdowns, setLoadingDropdowns] = useState(false);
|
||
|
|
const [localErrors, setLocalErrors] = useState<{ [key: string]: string | null }>({});
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
const fetchData = async () => {
|
||
|
|
setLoadingDropdowns(true);
|
||
|
|
try {
|
||
|
|
const [pubData, plantaData] = await Promise.all([
|
||
|
|
publicacionService.getAllPublicaciones(undefined, undefined, true),
|
||
|
|
plantaService.getAllPlantas()
|
||
|
|
]);
|
||
|
|
setPublicaciones(pubData.map(p => p));
|
||
|
|
setPlantas(plantaData);
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Error al cargar datos:", error);
|
||
|
|
setLocalErrors(prev => ({ ...prev, dropdowns: 'Error al cargar publicaciones o plantas.' }));
|
||
|
|
} finally {
|
||
|
|
setLoadingDropdowns(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
fetchData();
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (consolidado) {
|
||
|
|
setIdPlanta(''); // Limpiar planta si es consolidado
|
||
|
|
}
|
||
|
|
}, [consolidado]);
|
||
|
|
|
||
|
|
const validate = (): boolean => {
|
||
|
|
const errors: { [key: string]: string | null } = {};
|
||
|
|
if (!idPublicacion) errors.idPublicacion = 'Debe seleccionar una publicación.';
|
||
|
|
if (!mesAnio) errors.mesAnio = 'Debe seleccionar un Mes/Año.';
|
||
|
|
if (!consolidado && !idPlanta) {
|
||
|
|
errors.idPlanta = 'Seleccione una planta si no es consolidado.';
|
||
|
|
}
|
||
|
|
setLocalErrors(errors);
|
||
|
|
return Object.keys(errors).length === 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleGenerar = () => {
|
||
|
|
if (!validate()) return;
|
||
|
|
const [year, month] = mesAnio.split('-').map(Number);
|
||
|
|
const fechaDesde = new Date(year, month - 1, 1).toISOString().split('T')[0];
|
||
|
|
const fechaHasta = new Date(year, month, 0).toISOString().split('T')[0];
|
||
|
|
|
||
|
|
onGenerarReporte({
|
||
|
|
idPublicacion: Number(idPublicacion),
|
||
|
|
fechaDesde,
|
||
|
|
fechaHasta,
|
||
|
|
idPlanta: consolidado ? null : Number(idPlanta),
|
||
|
|
consolidado
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Box sx={{ p: 2, border: '1px solid #ccc', borderRadius: '4px', minWidth: 380 }}>
|
||
|
|
<Typography variant="h6" gutterBottom>
|
||
|
|
Parámetros: Tiradas por Publicación y Secciones
|
||
|
|
</Typography>
|
||
|
|
<FormControl fullWidth margin="normal" error={!!localErrors.idPublicacion} disabled={isLoading || loadingDropdowns}>
|
||
|
|
<InputLabel id="publicacion-select-label-tir" required>Publicación</InputLabel>
|
||
|
|
<Select
|
||
|
|
labelId="publicacion-select-label-tir"
|
||
|
|
label="Publicación"
|
||
|
|
value={idPublicacion}
|
||
|
|
onChange={(e) => { setIdPublicacion(e.target.value as number); setLocalErrors(p => ({ ...p, idPublicacion: null })); }}
|
||
|
|
>
|
||
|
|
<MenuItem value="" disabled><em>Seleccione una publicación</em></MenuItem>
|
||
|
|
{publicaciones.map((p) => (
|
||
|
|
<MenuItem key={p.idPublicacion} value={p.idPublicacion}>{p.nombre}</MenuItem>
|
||
|
|
))}
|
||
|
|
</Select>
|
||
|
|
{localErrors.idPublicacion && <Typography color="error" variant="caption" sx={{ml:1.5}}>{localErrors.idPublicacion}</Typography>}
|
||
|
|
</FormControl>
|
||
|
|
<TextField
|
||
|
|
label="Mes y Año"
|
||
|
|
type="month"
|
||
|
|
value={mesAnio}
|
||
|
|
onChange={(e) => { setMesAnio(e.target.value); setLocalErrors(p => ({ ...p, mesAnio: null })); }}
|
||
|
|
margin="normal"
|
||
|
|
fullWidth
|
||
|
|
required
|
||
|
|
error={!!localErrors.mesAnio}
|
||
|
|
helperText={localErrors.mesAnio}
|
||
|
|
disabled={isLoading}
|
||
|
|
InputLabelProps={{ shrink: true }}
|
||
|
|
/>
|
||
|
|
<FormControlLabel
|
||
|
|
control={
|
||
|
|
<Checkbox
|
||
|
|
checked={consolidado}
|
||
|
|
onChange={(e) => setConsolidado(e.target.checked)}
|
||
|
|
disabled={isLoading}
|
||
|
|
/>
|
||
|
|
}
|
||
|
|
label="Consolidado (Todas las Plantas)"
|
||
|
|
sx={{ mt: 1, mb: 1 }}
|
||
|
|
/>
|
||
|
|
<FormControl fullWidth margin="normal" error={!!localErrors.idPlanta} disabled={isLoading || loadingDropdowns || consolidado}>
|
||
|
|
<InputLabel id="planta-select-label-tir" required={!consolidado}>Planta</InputLabel>
|
||
|
|
<Select
|
||
|
|
labelId="planta-select-label-tir"
|
||
|
|
label="Planta"
|
||
|
|
value={consolidado ? '' : idPlanta}
|
||
|
|
onChange={(e) => { setIdPlanta(e.target.value as number); setLocalErrors(p => ({ ...p, idPlanta: null })); }}
|
||
|
|
>
|
||
|
|
<MenuItem value="" disabled><em>{consolidado ? 'N/A (Consolidado)' : 'Seleccione una planta'}</em></MenuItem>
|
||
|
|
{plantas.map((p) => (
|
||
|
|
<MenuItem key={p.idPlanta} value={p.idPlanta}>{p.nombre}</MenuItem>
|
||
|
|
))}
|
||
|
|
</Select>
|
||
|
|
{localErrors.idPlanta && <Typography color="error" variant="caption" sx={{ml:1.5}}>{localErrors.idPlanta}</Typography>}
|
||
|
|
</FormControl>
|
||
|
|
|
||
|
|
{apiErrorMessage && <Alert severity="error" sx={{ mt: 2 }}>{apiErrorMessage}</Alert>}
|
||
|
|
{localErrors.dropdowns && <Alert severity="warning" sx={{ mt: 1 }}>{localErrors.dropdowns}</Alert>}
|
||
|
|
|
||
|
|
<Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end', gap: 1 }}>
|
||
|
|
<Button onClick={handleGenerar} variant="contained" disabled={isLoading || loadingDropdowns}>
|
||
|
|
{isLoading ? <CircularProgress size={24} /> : 'Generar Reporte'}
|
||
|
|
</Button>
|
||
|
|
</Box>
|
||
|
|
</Box>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default SeleccionaReporteTiradasPublicacionesSecciones;
|