import { useState, useEffect, useMemo } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { useStore } from "@/contexts/StoreContext"; import { useToast } from "@/hooks/use-toast"; import { apiRequest } from "@/lib/queryClient"; import { isUnauthorizedError } from "@/lib/authUtils"; import { format } from "date-fns"; import { safeFormat } from "@/lib/dateUtils"; import type { Group, Supplier, OrderWithRelations } from "@shared/schema"; // Référence stable tant que les magasins ne sont pas chargés const NO_GROUPS: Group[] = []; interface CreateDeliveryModalProps { isOpen: boolean; onClose: () => void; selectedDate: Date | null; } export default function CreateDeliveryModal({ isOpen, onClose, selectedDate, }: CreateDeliveryModalProps) { const { user } = useAuthUnified(); const { selectedStoreId } = useStore(); const { toast } = useToast(); const queryClient = useQueryClient(); const [formData, setFormData] = useState({ orderId: "", supplierId: "", groupId: "", scheduledDate: selectedDate ? format(selectedDate, 'yyyy-MM-dd') : "", quantity: "", unit: "palettes", notes: "", }); const { data: suppliers = [] } = useQuery({ queryKey: ['/api/suppliers'], }); const { data: groupsData = NO_GROUPS } = useQuery({ queryKey: ['/api/groups'], }); // Filtrer les groupes selon le magasin sélectionné pour les admins // (mémorisé : la liste est une dépendance de l'effet ci-dessous, qui // tournait sinon à chaque rendu, donc à chaque frappe dans le formulaire) const groups = useMemo(() => Array.isArray(groupsData) ? ( user?.role === 'admin' && selectedStoreId ? groupsData.filter(g => g.id === selectedStoreId) : groupsData ) : NO_GROUPS, [groupsData, user?.role, selectedStoreId]); // Commandes du magasin du formulaire uniquement (paramètre storeId, dont // l'accès est contrôlé par le serveur) au lieu de tout l'historique de tous // les magasins ; filtrées ensuite par fournisseur const { data: allOrders = [] } = useQuery({ queryKey: ['/api/orders', 'store', formData.groupId], queryFn: async () => { const data = await apiRequest(`/api/orders?storeId=${formData.groupId}`); return Array.isArray(data) ? data : []; }, enabled: !!formData.groupId, }); // Filtrer les commandes par fournisseur ET magasin sélectionnés - montrer toutes les commandes non livrées const availableOrders = allOrders.filter(order => { if (!formData.supplierId || !formData.groupId) return false; return ( order.supplierId === parseInt(formData.supplierId) && order.groupId === parseInt(formData.groupId) && order.status !== 'delivered' ); }); // Auto-sélectionner le magasin selon les règles useEffect(() => { // Reset le formulaire si le magasin sélectionné change if (user?.role === 'admin' && selectedStoreId && formData.groupId && formData.groupId !== selectedStoreId.toString()) { setFormData(prev => ({ ...prev, groupId: "", orderId: "" })); return; } if (groups.length > 0 && !formData.groupId) { let defaultGroupId = ""; if (user?.role === 'admin') { // Pour l'admin : utiliser le magasin sélectionné dans le header (filtré), sinon le premier de la liste if (selectedStoreId && groups.find(g => g.id === selectedStoreId)) { defaultGroupId = selectedStoreId.toString(); } else { defaultGroupId = groups[0].id.toString(); } } else { // Pour les autres rôles : prendre le premier magasin attribué // (La logique existante filtre déjà les groupes selon les permissions) defaultGroupId = groups[0].id.toString(); } if (defaultGroupId) { setFormData(prev => ({ ...prev, groupId: defaultGroupId })); } } }, [groups, selectedStoreId, user?.role, formData.groupId]); // Réinitialiser la commande sélectionnée quand on change de fournisseur useEffect(() => { if (formData.supplierId) { setFormData(prev => ({ ...prev, orderId: "" })); } }, [formData.supplierId]); // Réinitialiser la commande sélectionnée quand on change de magasin useEffect(() => { if (formData.groupId) { setFormData(prev => ({ ...prev, orderId: "" })); } }, [formData.groupId]); const createDeliveryMutation = useMutation({ mutationFn: async (data: any) => { await apiRequest("/api/deliveries", "POST", data); }, onSuccess: () => { toast({ title: "Succès", description: "Livraison créée avec succès", }); // Invalider toutes les variantes de queryKey pour assurer cohérence queryClient.invalidateQueries({ predicate: (query) => { const key = query.queryKey; const firstKey = key[0]?.toString() || ''; return firstKey.includes('/api/orders') || firstKey.includes('/api/deliveries') || firstKey.includes('/api/stats/monthly'); }}); onClose(); }, onError: (error) => { if (isUnauthorizedError(error)) { toast({ title: "Non autorisé", description: "Vous êtes déconnecté. Reconnexion...", variant: "destructive", }); setTimeout(() => { window.location.href = "/api/login"; }, 500); return; } toast({ title: "Erreur", description: "Impossible de créer la livraison", variant: "destructive", }); }, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!formData.supplierId || !formData.groupId || !formData.scheduledDate || !formData.quantity) { toast({ title: "Erreur", description: "Veuillez remplir tous les champs obligatoires", variant: "destructive", }); return; } createDeliveryMutation.mutate({ orderId: formData.orderId && formData.orderId !== "none" ? parseInt(formData.orderId) : undefined, supplierId: parseInt(formData.supplierId), groupId: parseInt(formData.groupId), scheduledDate: formData.scheduledDate, quantity: parseInt(formData.quantity), unit: formData.unit, status: "planned", notes: formData.notes || undefined, createdBy: user?.id, }); }; const handleChange = (field: string, value: string) => { setFormData(prev => ({ ...prev, [field]: value })); }; // Afficher toutes les commandes du fournisseur sélectionné (pas de filtrage supplémentaire) const finalFilteredOrders = availableOrders; return ( Nouvelle Livraison

Créer une nouvelle livraison pour un fournisseur

{formData.supplierId && (
)} {/* Affichage du magasin sélectionné */} {formData.groupId && (
{(() => { const selectedGroup = groups.find(g => g.id.toString() === formData.groupId); return selectedGroup ? ( <>
{selectedGroup.name} ) : null; })()}
)}
handleChange('scheduledDate', e.target.value)} required />
handleChange('quantity', e.target.value)} required />