diff --git a/CLEAN-VALIDATE-ORDER-BUTTON.md b/CLEAN-VALIDATE-ORDER-BUTTON.md new file mode 100644 index 0000000..0d4cc09 --- /dev/null +++ b/CLEAN-VALIDATE-ORDER-BUTTON.md @@ -0,0 +1,65 @@ +# Bouton de Validation Propre - Dans le Modal de Détail + +## Modifications Apportées + +J'ai nettoyé le code et déplacé le bouton de validation dans le modal de détail de commande pour une interface plus propre. + +### 1. Nettoyage du CalendarGrid +- ✅ Supprimé tout le code de debug (textes rouges, boutons de test) +- ✅ Retiré les props `user` et `onOrderValidated` non nécessaires +- ✅ Interface calendrier propre et sans encombrement + +### 2. Ajout du Bouton dans OrderDetailModal +- ✅ Nouveau bouton "Valider Commande" vert dans les actions du modal +- ✅ Visible uniquement pour les admins (`user?.role === 'admin'`) +- ✅ Apparaît seulement sur les commandes non-delivered (`item?.status !== 'delivered'`) +- ✅ État de chargement pendant la validation +- ✅ Toasts de confirmation/erreur + +### 3. Fonctionnement +Quand vous cliquez sur une commande dans le calendrier : +1. **Modal s'ouvre** avec les détails de la commande +2. **Si vous êtes admin** et que la commande n'est pas delivered +3. **Bouton vert "Valider Commande"** apparaît en bas à droite +4. **Un clic** marque la commande comme delivered +5. **Modal se ferme** automatiquement après validation + +### 4. Avantages de cette Approche +- **Interface propre** : Le calendrier n'est pas encombré +- **Actions centralisées** : Toutes les actions (modifier, supprimer, valider) au même endroit +- **Plus visible** : Le bouton est bien visible dans le modal +- **Meilleure UX** : L'utilisateur voit les détails avant de valider + +## Déploiement en Production + +### Fichiers Modifiés : +1. **`client/src/components/CalendarGrid.tsx`** - Nettoyé, code de debug supprimé +2. **`client/src/pages/Calendar.tsx`** - Props simplifiées +3. **`client/src/components/modals/OrderDetailModal.tsx`** - Bouton de validation ajouté + +### Commandes : +```bash +# Sauvegarder +cp -r client/src client/src.backup.clean + +# Appliquer les modifications +# (copiez le contenu des fichiers modifiés) + +# Reconstruire +npm run build + +# Redémarrer +pm2 restart your-app-name +``` + +## Test Final + +1. **Connectez-vous en admin** +2. **Cliquez sur CMD-55** dans le calendrier +3. **Vérifiez** que le bouton vert "Valider Commande" apparaît dans le modal +4. **Cliquez** sur le bouton pour valider +5. **Confirmez** que CMD-55 devient gris (delivered) dans le calendrier + +--- + +**Résultat** : Interface propre avec bouton de validation facilement accessible dans le modal de détail des commandes. \ No newline at end of file diff --git a/attached_assets/image_1754946503284.png b/attached_assets/image_1754946503284.png new file mode 100644 index 0000000..1a66a98 Binary files /dev/null and b/attached_assets/image_1754946503284.png differ diff --git a/client/src/components/CalendarGrid.tsx b/client/src/components/CalendarGrid.tsx index e0753c0..64f3210 100644 --- a/client/src/components/CalendarGrid.tsx +++ b/client/src/components/CalendarGrid.tsx @@ -1,9 +1,7 @@ import { format, startOfMonth, endOfMonth, eachDayOfInterval, isSameDay, isSameMonth, isToday } from "date-fns"; import { fr } from "date-fns/locale"; import { safeDate } from "@/lib/dateUtils"; -import { Plus, Check, CheckCircle } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { useToast } from "@/hooks/use-toast"; +import { Plus, Check } from "lucide-react"; import type { OrderWithRelations, DeliveryWithRelations } from "@shared/schema"; interface CalendarGridProps { @@ -12,8 +10,6 @@ interface CalendarGridProps { deliveries: DeliveryWithRelations[]; onDateClick: (date: Date) => void; onItemClick: (item: any, type: 'order' | 'delivery') => void; - user?: { role: string } | null; - onOrderValidated?: () => void; } export default function CalendarGrid({ @@ -22,10 +18,7 @@ export default function CalendarGrid({ deliveries, onDateClick, onItemClick, - user, - onOrderValidated, }: CalendarGridProps) { - const { toast } = useToast(); const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); @@ -60,47 +53,6 @@ export default function CalendarGrid({ const weekDays = ["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"]; - // Fonction pour valider une commande - const handleValidateOrder = async (orderId: number, event: React.MouseEvent) => { - event.stopPropagation(); - - console.log('🔥 DEBUG: Validation clicked for order', orderId, 'User role:', user?.role); - - try { - const response = await fetch(`/api/orders/${orderId}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - credentials: 'include', - body: JSON.stringify({ status: 'delivered' }) - }); - - console.log('🔥 DEBUG: Response status:', response.status); - - if (!response.ok) { - const errorText = await response.text(); - console.error('🔥 DEBUG: Response error:', errorText); - throw new Error(`Erreur ${response.status}: ${errorText}`); - } - - toast({ - title: "Commande validée", - description: `La commande CMD-${orderId} a été marquée comme livrée.`, - }); - - // Rafraîchir les données - if (onOrderValidated) { - onOrderValidated(); - } - } catch (error) { - console.error('🔥 DEBUG: Validation error:', error); - toast({ - title: "Erreur", - description: "Impossible de valider la commande.", - variant: "destructive" - }); - } - }; - const getItemsForDate = (date: Date) => { // Debug: Log des commandes reçues (seulement une fois) if (orders.length > 0 && date.getDate() === 1) { @@ -233,32 +185,6 @@ export default function CalendarGrid({ {order.supplier.name}
- {/* DEBUG: Affichage info utilisateur sur première commande */} - {order.id === orders[0]?.id && ( -
- User: {user?.role || 'null'} | Status: {order.status} -
- )} - - {/* Bouton de validation pour les admins - VERSION VISIBLE POUR DEBUG */} - {user?.role === 'admin' && order.status !== 'delivered' && ( - - )} - - {/* Bouton de test TOUJOURS VISIBLE */} - {order.status !== 'delivered' && ( -
- V -
- )} {order.status === 'planned' && ( diff --git a/client/src/components/modals/OrderDetailModal.tsx b/client/src/components/modals/OrderDetailModal.tsx index d0002c9..50c664f 100644 --- a/client/src/components/modals/OrderDetailModal.tsx +++ b/client/src/components/modals/OrderDetailModal.tsx @@ -11,7 +11,7 @@ import { safeFormat } from "@/lib/dateUtils"; import EditOrderModal from "./EditOrderModal"; import EditDeliveryModal from "./EditDeliveryModal"; import ValidateDeliveryModal from "./ValidateDeliveryModal"; -import { Package, Truck, Edit, Trash2, Check, X } from "lucide-react"; +import { Package, Truck, Edit, Trash2, Check, X, CheckCircle } from "lucide-react"; interface OrderDetailModalProps { isOpen: boolean; @@ -33,6 +33,39 @@ export default function OrderDetailModal({ const isOrder = item?.type === 'order'; const isDelivery = item?.type === 'delivery'; + const validateOrderMutation = useMutation({ + mutationFn: async (orderId: number) => { + await apiRequest(`/api/orders/${orderId}`, "PUT", { status: 'delivered' }); + }, + onSuccess: () => { + toast({ + title: "Succès", + description: "Commande validée avec succès", + }); + queryClient.invalidateQueries({ queryKey: ['/api/orders'] }); + queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] }); + 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 valider la commande", + variant: "destructive", + }); + }, + }); + const validateDeliveryMutation = useMutation({ mutationFn: async (data: { id: number; blNumber: string; blAmount: number }) => { await apiRequest(`/api/deliveries/${data.id}/validate`, "POST", data); @@ -354,6 +387,18 @@ export default function OrderDetailModal({ Modifier )} + {/* Bouton de validation pour les commandes (admin seulement) */} + {isOrder && user?.role === 'admin' && item?.status !== 'delivered' && ( + + )} + {canValidate && (