231 lines
7.7 KiB
TypeScript
231 lines
7.7 KiB
TypeScript
import { useState } from 'react';
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import {
|
|
Box,
|
|
Typography,
|
|
Button,
|
|
Paper,
|
|
IconButton,
|
|
Dialog,
|
|
DialogTitle,
|
|
DialogContent,
|
|
DialogActions,
|
|
TextField,
|
|
Grid,
|
|
} from '@mui/material';
|
|
import { DataGrid, GridColDef } from '@mui/x-data-grid';
|
|
import { Add as AddIcon, Edit as EditIcon, Delete as DeleteIcon } from '@mui/icons-material';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { locationService } from '../services/lookupService';
|
|
import { Location } from '../types';
|
|
|
|
export default function LocationPage() {
|
|
const queryClient = useQueryClient();
|
|
const { t } = useTranslation();
|
|
const [openDialog, setOpenDialog] = useState(false);
|
|
const [editingId, setEditingId] = useState<number | null>(null);
|
|
const [formData, setFormData] = useState<Partial<Location>>({ attivo: true });
|
|
|
|
const { data: locations = [], isLoading } = useQuery({
|
|
queryKey: ['location'],
|
|
queryFn: () => locationService.getAll(),
|
|
});
|
|
|
|
const createMutation = useMutation({
|
|
mutationFn: (data: Partial<Location>) => locationService.create(data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['location'] });
|
|
handleCloseDialog();
|
|
},
|
|
});
|
|
|
|
const updateMutation = useMutation({
|
|
mutationFn: ({ id, data }: { id: number; data: Partial<Location> }) => locationService.update(id, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['location'] });
|
|
handleCloseDialog();
|
|
},
|
|
});
|
|
|
|
const deleteMutation = useMutation({
|
|
mutationFn: (id: number) => locationService.delete(id),
|
|
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['location'] }),
|
|
});
|
|
|
|
const handleCloseDialog = () => {
|
|
setOpenDialog(false);
|
|
setEditingId(null);
|
|
setFormData({ attivo: true });
|
|
};
|
|
|
|
const handleEdit = (location: Location) => {
|
|
setFormData(location);
|
|
setEditingId(location.id);
|
|
setOpenDialog(true);
|
|
};
|
|
|
|
const handleSubmit = () => {
|
|
if (editingId) {
|
|
updateMutation.mutate({ id: editingId, data: formData });
|
|
} else {
|
|
createMutation.mutate(formData);
|
|
}
|
|
};
|
|
|
|
const columns: GridColDef[] = [
|
|
{ field: 'nome', headerName: t('location.name'), flex: 1, minWidth: 200 },
|
|
{ field: 'citta', headerName: t('location.city'), width: 150 },
|
|
{ field: 'provincia', headerName: t('location.province'), width: 80 },
|
|
{ field: 'distanzaKm', headerName: t('location.distance'), width: 120, type: 'number' },
|
|
{ field: 'referente', headerName: t('location.contact'), width: 150 },
|
|
{ field: 'telefono', headerName: t('location.phone'), width: 130 },
|
|
{
|
|
field: 'actions',
|
|
headerName: t('common.actions'),
|
|
width: 120,
|
|
sortable: false,
|
|
renderCell: (params) => (
|
|
<Box>
|
|
<IconButton size="small" onClick={() => handleEdit(params.row)}>
|
|
<EditIcon />
|
|
</IconButton>
|
|
<IconButton
|
|
size="small"
|
|
color="error"
|
|
onClick={() => {
|
|
if (confirm(t('location.deleteConfirm'))) {
|
|
deleteMutation.mutate(params.row.id);
|
|
}
|
|
}}
|
|
>
|
|
<DeleteIcon />
|
|
</IconButton>
|
|
</Box>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<Box>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
|
<Typography variant="h4">{t('location.title')}</Typography>
|
|
<Button variant="contained" startIcon={<AddIcon />} onClick={() => setOpenDialog(true)}>
|
|
{t('location.newLocation')}
|
|
</Button>
|
|
</Box>
|
|
|
|
<Paper sx={{ height: 600, width: '100%' }}>
|
|
<DataGrid
|
|
rows={locations}
|
|
columns={columns}
|
|
loading={isLoading}
|
|
pageSizeOptions={[10, 25, 50]}
|
|
initialState={{
|
|
pagination: { paginationModel: { pageSize: 25 } },
|
|
}}
|
|
disableRowSelectionOnClick
|
|
/>
|
|
</Paper>
|
|
|
|
<Dialog open={openDialog} onClose={handleCloseDialog} maxWidth="md" fullWidth>
|
|
<DialogTitle>{editingId ? t('location.editLocation') : t('location.newLocation')}</DialogTitle>
|
|
<DialogContent>
|
|
<Grid container spacing={2} sx={{ mt: 1 }}>
|
|
<Grid size={{ xs: 12 }}>
|
|
<TextField
|
|
label={t('location.name')}
|
|
fullWidth
|
|
required
|
|
value={formData.nome || ''}
|
|
onChange={(e) => setFormData({ ...formData, nome: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12, md: 8 }}>
|
|
<TextField
|
|
label={t('location.address')}
|
|
fullWidth
|
|
value={formData.indirizzo || ''}
|
|
onChange={(e) => setFormData({ ...formData, indirizzo: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12, md: 4 }}>
|
|
<TextField
|
|
label={t('location.zip')}
|
|
fullWidth
|
|
value={formData.cap || ''}
|
|
onChange={(e) => setFormData({ ...formData, cap: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12, md: 6 }}>
|
|
<TextField
|
|
label={t('location.city')}
|
|
fullWidth
|
|
value={formData.citta || ''}
|
|
onChange={(e) => setFormData({ ...formData, citta: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12, md: 3 }}>
|
|
<TextField
|
|
label={t('location.province')}
|
|
fullWidth
|
|
value={formData.provincia || ''}
|
|
onChange={(e) => setFormData({ ...formData, provincia: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12, md: 3 }}>
|
|
<TextField
|
|
label={t('location.distance')}
|
|
fullWidth
|
|
type="number"
|
|
value={formData.distanzaKm || ''}
|
|
onChange={(e) => setFormData({ ...formData, distanzaKm: parseFloat(e.target.value) || undefined })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12, md: 6 }}>
|
|
<TextField
|
|
label={t('location.phone')}
|
|
fullWidth
|
|
value={formData.telefono || ''}
|
|
onChange={(e) => setFormData({ ...formData, telefono: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12, md: 6 }}>
|
|
<TextField
|
|
label={t('location.email')}
|
|
fullWidth
|
|
type="email"
|
|
value={formData.email || ''}
|
|
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12 }}>
|
|
<TextField
|
|
label={t('location.contact')}
|
|
fullWidth
|
|
value={formData.referente || ''}
|
|
onChange={(e) => setFormData({ ...formData, referente: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
<Grid size={{ xs: 12 }}>
|
|
<TextField
|
|
label={t('common.notes')}
|
|
fullWidth
|
|
multiline
|
|
rows={3}
|
|
value={formData.note || ''}
|
|
onChange={(e) => setFormData({ ...formData, note: e.target.value })}
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button onClick={handleCloseDialog}>{t('common.cancel')}</Button>
|
|
<Button variant="contained" onClick={handleSubmit}>
|
|
{editingId ? t('common.save') : t('common.create')}
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
</Box>
|
|
);
|
|
}
|