Add vehicle assignment to guard planning and improve dialog size
Integrate vehicle assignment into the general planning module by adding a `vehicleId` field to the `assign-guard` mutation and fetching available vehicles. Increase the dialog size for better usability and update related cache invalidations. Replit-Commit-Author: Agent Replit-Commit-Session-Id: e5565357-90e1-419f-b9a8-6ee8394636df Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/e5565357-90e1-419f-b9a8-6ee8394636df/KiuJzNf
This commit is contained in:
parent
d7c6136fcb
commit
a945abdb5d
4
.replit
4
.replit
@ -19,10 +19,6 @@ externalPort = 80
|
||||
localPort = 33035
|
||||
externalPort = 3001
|
||||
|
||||
[[ports]]
|
||||
localPort = 33123
|
||||
externalPort = 5173
|
||||
|
||||
[[ports]]
|
||||
localPort = 41343
|
||||
externalPort = 3000
|
||||
|
||||
@ -21,7 +21,7 @@ import {
|
||||
} from "@/components/ui/dialog";
|
||||
import { queryClient, apiRequest } from "@/lib/queryClient";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import type { GuardAvailability } from "@shared/schema";
|
||||
import type { GuardAvailability, Vehicle as VehicleDb } from "@shared/schema";
|
||||
|
||||
interface GuardWithHours {
|
||||
assignmentId: string;
|
||||
@ -98,6 +98,7 @@ export default function GeneralPlanning() {
|
||||
|
||||
// Form state per assegnazione guardia
|
||||
const [selectedGuardId, setSelectedGuardId] = useState<string>("");
|
||||
const [selectedVehicleId, setSelectedVehicleId] = useState<string>("");
|
||||
const [startTime, setStartTime] = useState<string>("06:00");
|
||||
const [durationHours, setDurationHours] = useState<number>(8);
|
||||
const [consecutiveDays, setConsecutiveDays] = useState<number>(1);
|
||||
@ -147,6 +148,19 @@ export default function GeneralPlanning() {
|
||||
staleTime: 0, // Dati sempre considerati stale, refetch ad ogni apertura dialog
|
||||
});
|
||||
|
||||
// Query per veicoli disponibili (solo quando dialog è aperto)
|
||||
const { data: availableVehicles, isLoading: isLoadingVehicles } = useQuery<VehicleDb[]>({
|
||||
queryKey: ["/api/vehicles/available", selectedLocation],
|
||||
queryFn: async () => {
|
||||
if (!selectedCell) return [];
|
||||
const response = await fetch(`/api/vehicles/available?location=${selectedLocation}`);
|
||||
if (!response.ok) throw new Error("Failed to fetch available vehicles");
|
||||
return response.json();
|
||||
},
|
||||
enabled: !!selectedCell,
|
||||
staleTime: 0,
|
||||
});
|
||||
|
||||
// Mutation per eliminare assegnazione guardia
|
||||
const deleteAssignmentMutation = useMutation({
|
||||
mutationFn: async (assignmentId: string) => {
|
||||
@ -172,13 +186,14 @@ export default function GeneralPlanning() {
|
||||
|
||||
// Mutation per assegnare guardia con orari (anche multi-giorno)
|
||||
const assignGuardMutation = useMutation({
|
||||
mutationFn: async (data: { siteId: string; date: string; guardId: string; startTime: string; durationHours: number; consecutiveDays: number }) => {
|
||||
mutationFn: async (data: { siteId: string; date: string; guardId: string; startTime: string; durationHours: number; consecutiveDays: number; vehicleId?: string }) => {
|
||||
return apiRequest("POST", "/api/general-planning/assign-guard", data);
|
||||
},
|
||||
onSuccess: async () => {
|
||||
// Invalida cache planning generale
|
||||
// Invalida cache planning generale, guardie e veicoli
|
||||
await queryClient.invalidateQueries({ queryKey: ["/api/general-planning"] });
|
||||
await queryClient.invalidateQueries({ queryKey: ["/api/guards/availability"] });
|
||||
await queryClient.invalidateQueries({ queryKey: ["/api/vehicles/available"] });
|
||||
|
||||
// Refetch immediatamente guardie disponibili per aggiornare lista
|
||||
await refetchGuards();
|
||||
@ -188,8 +203,9 @@ export default function GeneralPlanning() {
|
||||
description: "La guardia è stata assegnata con successo",
|
||||
});
|
||||
|
||||
// Reset solo guardia selezionata (NON chiudere dialog per vedere lista aggiornata)
|
||||
// Reset form (NON chiudere dialog per vedere lista aggiornata)
|
||||
setSelectedGuardId("");
|
||||
setSelectedVehicleId("");
|
||||
},
|
||||
onError: (error: any) => {
|
||||
// Parse error message from API response
|
||||
@ -228,6 +244,7 @@ export default function GeneralPlanning() {
|
||||
startTime,
|
||||
durationHours,
|
||||
consecutiveDays,
|
||||
...(selectedVehicleId && { vehicleId: selectedVehicleId }),
|
||||
});
|
||||
};
|
||||
|
||||
@ -526,8 +543,9 @@ export default function GeneralPlanning() {
|
||||
setStartTime("06:00");
|
||||
setDurationHours(8);
|
||||
setConsecutiveDays(1);
|
||||
setSelectedVehicleId("");
|
||||
}}>
|
||||
<DialogContent className="max-w-2xl max-h-[85vh] flex flex-col">
|
||||
<DialogContent className="max-w-6xl max-h-[90vh] flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<Calendar className="h-5 w-5" />
|
||||
@ -800,6 +818,38 @@ export default function GeneralPlanning() {
|
||||
);
|
||||
})()}
|
||||
|
||||
{/* Select veicolo (opzionale) */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="vehicle-select">Veicolo (opzionale)</Label>
|
||||
{isLoadingVehicles ? (
|
||||
<Skeleton className="h-10 w-full" />
|
||||
) : (
|
||||
<Select
|
||||
value={selectedVehicleId}
|
||||
onValueChange={setSelectedVehicleId}
|
||||
disabled={assignGuardMutation.isPending}
|
||||
>
|
||||
<SelectTrigger id="vehicle-select" data-testid="select-vehicle">
|
||||
<SelectValue placeholder="Nessun veicolo" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="">Nessun veicolo</SelectItem>
|
||||
{availableVehicles && availableVehicles.length > 0 ? (
|
||||
availableVehicles.map((vehicle) => (
|
||||
<SelectItem key={vehicle.id} value={vehicle.id}>
|
||||
{vehicle.licensePlate} - {vehicle.brand} {vehicle.model}
|
||||
</SelectItem>
|
||||
))
|
||||
) : (
|
||||
<SelectItem value="no-vehicles" disabled>
|
||||
Nessun veicolo disponibile
|
||||
</SelectItem>
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Bottone assegna */}
|
||||
<Button
|
||||
onClick={handleAssignGuard}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user