Feat: Baja Lógica de Distribuidores (Selectores Dropdown)
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 8m32s
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 8m32s
This commit is contained in:
@@ -12,4 +12,6 @@ export interface DistribuidorDto {
|
||||
telefono?: string | null;
|
||||
email?: string | null;
|
||||
localidad?: string | null;
|
||||
baja?: boolean;
|
||||
fechaBaja?: string | null;
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
// src/pages/Distribucion/GestionarDistribuidoresPage.tsx
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import {
|
||||
Box, Typography, TextField, Button, Paper, IconButton, Menu, MenuItem,
|
||||
Box, Typography, TextField, Button, Paper, IconButton, Menu, MenuItem, Switch,
|
||||
Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TablePagination,
|
||||
CircularProgress, Alert
|
||||
CircularProgress, Alert, Chip, FormControlLabel, ListItemIcon, ListItemText
|
||||
} from '@mui/material';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import TrashIcon from '@mui/icons-material/Delete';
|
||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||
import ToggleOnIcon from '@mui/icons-material/ToggleOn';
|
||||
import ToggleOffIcon from '@mui/icons-material/ToggleOff';
|
||||
import distribuidorService from '../../services/Distribucion/distribuidorService';
|
||||
import type { DistribuidorDto } from '../../models/dtos/Distribucion/DistribuidorDto';
|
||||
import type { CreateDistribuidorDto } from '../../models/dtos/Distribucion/CreateDistribuidorDto';
|
||||
@@ -24,6 +26,7 @@ const GestionarDistribuidoresPage: React.FC = () => {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [filtroNombre, setFiltroNombre] = useState('');
|
||||
const [filtroNroDoc, setFiltroNroDoc] = useState('');
|
||||
const [filtroSoloActivos, setFiltroSoloActivos] = useState<boolean | undefined>(true);
|
||||
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [editingDistribuidor, setEditingDistribuidor] = useState<DistribuidorDto | null>(null);
|
||||
@@ -49,12 +52,12 @@ const GestionarDistribuidoresPage: React.FC = () => {
|
||||
}
|
||||
setLoading(true); setError(null); setApiErrorMessage(null);
|
||||
try {
|
||||
const data = await distribuidorService.getAllDistribuidores(filtroNombre, filtroNroDoc);
|
||||
const data = await distribuidorService.getAllDistribuidores(filtroNombre, filtroNroDoc, filtroSoloActivos);
|
||||
setDistribuidores(data);
|
||||
} catch (err) {
|
||||
console.error(err); setError('Error al cargar los distribuidores.');
|
||||
} finally { setLoading(false); }
|
||||
}, [filtroNombre, filtroNroDoc, puedeVer]);
|
||||
}, [filtroNombre, filtroNroDoc, filtroSoloActivos, puedeVer]);
|
||||
|
||||
useEffect(() => { cargarDistribuidores(); }, [cargarDistribuidores]);
|
||||
|
||||
@@ -94,6 +97,21 @@ const GestionarDistribuidoresPage: React.FC = () => {
|
||||
handleMenuClose();
|
||||
};
|
||||
|
||||
const handleToggleBaja = async (distribuidor: DistribuidorDto) => {
|
||||
setApiErrorMessage(null);
|
||||
const accion = distribuidor.baja ? "reactivar" : "dar de baja";
|
||||
if (window.confirm(`¿Está seguro de que desea ${accion} a ${distribuidor.nombre}?`)) {
|
||||
try {
|
||||
await distribuidorService.toggleBajaDistribuidor(distribuidor.idDistribuidor, { darDeBaja: !distribuidor.baja, fechaBaja: !distribuidor.baja ? new Date().toISOString() : null });
|
||||
cargarDistribuidores();
|
||||
} catch (err: any) {
|
||||
const message = axios.isAxiosError(err) && err.response?.data?.message ? err.response.data.message : `Error al ${accion} el distribuidor.`;
|
||||
setApiErrorMessage(message);
|
||||
}
|
||||
}
|
||||
handleMenuClose();
|
||||
};
|
||||
|
||||
const handleMenuOpen = (event: React.MouseEvent<HTMLElement>, distribuidor: DistribuidorDto) => {
|
||||
setAnchorEl(event.currentTarget); setSelectedDistribuidorRow(distribuidor);
|
||||
};
|
||||
@@ -132,7 +150,17 @@ const GestionarDistribuidoresPage: React.FC = () => {
|
||||
onChange={(e) => setFiltroNroDoc(e.target.value)}
|
||||
sx={{ flexGrow: 1, minWidth: '200px' }}
|
||||
/>
|
||||
{/* <Button variant="contained" onClick={cargarDistribuidores} size="small">Buscar</Button> */}
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={filtroSoloActivos === undefined ? true : filtroSoloActivos}
|
||||
onChange={(e) => setFiltroSoloActivos(e.target.checked)}
|
||||
size="small"
|
||||
/>
|
||||
}
|
||||
label="Ver Activos"
|
||||
sx={{ flexShrink: 0 }}
|
||||
/>
|
||||
</Box>
|
||||
{puedeCrear && (
|
||||
<Button variant="contained" startIcon={<AddIcon />} onClick={() => handleOpenModal()} sx={{ mb: 2 }}>Agregar Distribuidor</Button>
|
||||
@@ -150,6 +178,7 @@ const GestionarDistribuidoresPage: React.FC = () => {
|
||||
<TableCell>Nombre</TableCell><TableCell>Nro. Doc.</TableCell>
|
||||
<TableCell>Contacto</TableCell><TableCell>Zona</TableCell>
|
||||
<TableCell>Teléfono</TableCell><TableCell>Localidad</TableCell>
|
||||
<TableCell>Estado</TableCell>
|
||||
{(puedeModificar || puedeEliminar) && <TableCell align="right">Acciones</TableCell>}
|
||||
</TableRow></TableHead>
|
||||
<TableBody>
|
||||
@@ -157,10 +186,11 @@ const GestionarDistribuidoresPage: React.FC = () => {
|
||||
<TableRow><TableCell colSpan={7} align="center">No se encontraron distribuidores.</TableCell></TableRow>
|
||||
) : (
|
||||
displayData.map((d) => (
|
||||
<TableRow key={d.idDistribuidor} hover>
|
||||
<TableRow key={d.idDistribuidor} hover sx={{ backgroundColor: d.baja ? '#ffebee' : 'inherit' }}>
|
||||
<TableCell>{d.nombre}</TableCell><TableCell>{d.nroDoc}</TableCell>
|
||||
<TableCell>{d.contacto || '-'}</TableCell><TableCell>{d.nombreZona || '-'}</TableCell>
|
||||
<TableCell>{d.telefono || '-'}</TableCell><TableCell>{d.localidad || '-'}</TableCell>
|
||||
<TableCell>{d.baja ? <Chip label="Baja" color="error" size="small" /> : <Chip label="Activo" color="success" size="small" />}</TableCell>
|
||||
{(puedeModificar || puedeEliminar) && (
|
||||
<TableCell align="right">
|
||||
<IconButton onClick={(e) => handleMenuOpen(e, d)} disabled={!puedeModificar && !puedeEliminar}><MoreVertIcon /></IconButton>
|
||||
@@ -179,8 +209,24 @@ const GestionarDistribuidoresPage: React.FC = () => {
|
||||
)}
|
||||
|
||||
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleMenuClose}>
|
||||
{puedeModificar && (<MenuItem onClick={() => { handleOpenModal(selectedDistribuidorRow!); handleMenuClose(); }}><EditIcon fontSize="small" sx={{ mr: 1 }} />Modificar</MenuItem>)}
|
||||
{puedeEliminar && (<MenuItem onClick={() => handleDelete(selectedDistribuidorRow!.idDistribuidor)}><TrashIcon fontSize="small" sx={{ mr: 1 }} />Eliminar</MenuItem>)}
|
||||
{puedeModificar && selectedDistribuidorRow && (
|
||||
<MenuItem onClick={() => { handleOpenModal(selectedDistribuidorRow); handleMenuClose(); }}>
|
||||
<ListItemIcon><EditIcon fontSize="small" /></ListItemIcon>
|
||||
<ListItemText>Modificar</ListItemText>
|
||||
</MenuItem>
|
||||
)}
|
||||
{puedeEliminar && selectedDistribuidorRow && (
|
||||
<MenuItem onClick={() => handleToggleBaja(selectedDistribuidorRow)}>
|
||||
<ListItemIcon>{selectedDistribuidorRow.baja ? <ToggleOnIcon fontSize="small" /> : <ToggleOffIcon fontSize="small" />}</ListItemIcon>
|
||||
<ListItemText>{selectedDistribuidorRow.baja ? 'Reactivar' : 'Dar de Baja'}</ListItemText>
|
||||
</MenuItem>
|
||||
)}
|
||||
{puedeEliminar && selectedDistribuidorRow && (
|
||||
<MenuItem onClick={() => handleDelete(selectedDistribuidorRow.idDistribuidor)}>
|
||||
<ListItemIcon><TrashIcon fontSize="small" /></ListItemIcon>
|
||||
<ListItemText>Eliminar (Físico)</ListItemText>
|
||||
</MenuItem>
|
||||
)}
|
||||
{(!puedeModificar && !puedeEliminar) && <MenuItem disabled>Sin acciones</MenuItem>}
|
||||
</Menu>
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ import type { UpdateDistribuidorDto } from '../../models/dtos/Distribucion/Updat
|
||||
import type { DistribuidorDropdownDto } from '../../models/dtos/Distribucion/DistribuidorDropdownDto';
|
||||
import type { DistribuidorLookupDto } from '../../models/dtos/Distribucion/DistribuidorLookupDto';
|
||||
|
||||
const getAllDistribuidores = async (nombreFilter?: string, nroDocFilter?: string): Promise<DistribuidorDto[]> => {
|
||||
const params: Record<string, string> = {};
|
||||
const getAllDistribuidores = async (nombreFilter?: string, nroDocFilter?: string, soloActivos: boolean = true): Promise<DistribuidorDto[]> => {
|
||||
const params: Record<string, string | boolean> = {
|
||||
soloActivos: soloActivos
|
||||
};
|
||||
if (nombreFilter) params.nombre = nombreFilter;
|
||||
if (nroDocFilter) params.nroDoc = nroDocFilter;
|
||||
|
||||
@@ -37,11 +39,15 @@ const deleteDistribuidor = async (id: number): Promise<void> => {
|
||||
await apiClient.delete(`/distribuidores/${id}`);
|
||||
};
|
||||
|
||||
const getAllDistribuidoresDropdown = async (): Promise<DistribuidorDropdownDto[]> => {
|
||||
const response = await apiClient.get<DistribuidorDropdownDto[]>('/distribuidores/dropdown');
|
||||
const getAllDistribuidoresDropdown = async (soloActivos: boolean = true): Promise<DistribuidorDropdownDto[]> => {
|
||||
const response = await apiClient.get<DistribuidorDropdownDto[]>('/distribuidores/dropdown', { params: { soloActivos } });
|
||||
return response.data;
|
||||
};
|
||||
|
||||
const toggleBajaDistribuidor = async (id: number, data: { darDeBaja: boolean, fechaBaja: string | null }): Promise<void> => {
|
||||
await apiClient.put(`/distribuidores/${id}/toggle-baja`, data);
|
||||
};
|
||||
|
||||
const distribuidorService = {
|
||||
getAllDistribuidores,
|
||||
getDistribuidorById,
|
||||
@@ -50,6 +56,7 @@ const distribuidorService = {
|
||||
deleteDistribuidor,
|
||||
getAllDistribuidoresDropdown,
|
||||
getDistribuidorLookupById,
|
||||
toggleBajaDistribuidor,
|
||||
};
|
||||
|
||||
export default distribuidorService;
|
||||
Reference in New Issue
Block a user