Files
zentral/frontend/src/pages/LocationPage.tsx
2025-11-30 00:34:56 +01:00

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>
);
}