mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Add button for admins to validate orders directly from the calendar
Adds a conditional "Validate Order" button (visible on hover to admins only) to the order cards in the calendar view, allowing for one-click status updates to 'delivered' and invalidating related data queries. Replit-Commit-Author: Agent Replit-Commit-Session-Id: a8a78c07-e900-425c-a577-5b4c5894379d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/a8a78c07-e900-425c-a577-5b4c5894379d/3ec1Xks
This commit is contained in:
1 parent
041891baf0
commit
a8ff4c0c73
3 files changed
+117
-4
No files matched your search
@@ -0,0 +1,54 @@
|
||||
# Fonctionnalité Bouton "Valider Commande" - Calendrier
|
||||
|
||||
## Nouvelle Fonctionnalité
|
||||
|
||||
J'ai ajouté un bouton de validation directement sur les cartes des commandes dans le calendrier, avec les caractéristiques suivantes :
|
||||
|
||||
### Fonctionnement
|
||||
|
||||
- **Visibilité** : Le bouton n'est visible que pour les utilisateurs avec le rôle `admin`
|
||||
- **Apparition** : Le bouton apparaît uniquement au survol de la carte de commande (effet hover)
|
||||
- **Cible** : Seules les commandes qui ne sont pas encore en statut `delivered` affichent le bouton
|
||||
- **Action** : Un clic sur le bouton marque immédiatement la commande comme `delivered`
|
||||
|
||||
### Interface Utilisateur
|
||||
|
||||
- **Icône** : CheckCircle (cercle avec coche)
|
||||
- **Position** : À droite de la carte, avant les autres indicateurs de statut
|
||||
- **Style** : Bouton fantôme semi-transparent qui devient visible au survol
|
||||
- **Feedback** : Toast de confirmation quand la validation réussit
|
||||
|
||||
### Avantages
|
||||
|
||||
1. **Accès Direct** : Plus besoin d'ouvrir le modal de détail pour valider une commande
|
||||
2. **Interface Propre** : Le bouton n'encombre pas l'interface car il n'apparaît qu'au survol
|
||||
3. **Sécurité** : Réservé aux administrateurs uniquement
|
||||
4. **Efficacité** : Validation en un clic avec feedback immédiat
|
||||
|
||||
### Utilisation
|
||||
|
||||
1. **Connexion Admin** : Connectez-vous avec un compte administrateur
|
||||
2. **Survol** : Passez la souris sur une commande non-delivered (orange ou bleue)
|
||||
3. **Validation** : Cliquez sur l'icône de cercle avec coche qui apparaît
|
||||
4. **Confirmation** : La commande passe en gris (delivered) avec un toast de confirmation
|
||||
|
||||
### Déploiement en Production
|
||||
|
||||
Les modifications ont été apportées aux fichiers :
|
||||
- `client/src/components/CalendarGrid.tsx` : Ajout du bouton et logique de validation
|
||||
- `client/src/pages/Calendar.tsx` : Passage des props user et callback de rafraîchissement
|
||||
|
||||
Pour déployer en production :
|
||||
1. Appliquer les modifications aux fichiers mentionnés
|
||||
2. Reconstruire le frontend (`npm run build`)
|
||||
3. Redémarrer l'application
|
||||
|
||||
### Résolution du Problème CMD-55
|
||||
|
||||
Avec cette fonctionnalité, vous pouvez maintenant :
|
||||
1. Trouver CMD-55 dans le calendrier
|
||||
2. Passer la souris dessus (si elle n'est pas déjà delivered)
|
||||
3. Cliquer sur le bouton de validation
|
||||
4. CMD-55 passera automatiquement en gris (delivered)
|
||||
|
||||
Cette solution est plus simple et directe que la synchronisation manuelle précédente.
|
||||
@@ -1,8 +1,9 @@
|
||||
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 } from "lucide-react";
|
||||
import { Plus, Check, CheckCircle } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import type { OrderWithRelations, DeliveryWithRelations } from "@shared/schema";
|
||||
|
||||
interface CalendarGridProps {
|
||||
@@ -11,6 +12,8 @@ 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({
|
||||
@@ -19,7 +22,10 @@ export default function CalendarGrid({
|
||||
deliveries,
|
||||
onDateClick,
|
||||
onItemClick,
|
||||
user,
|
||||
onOrderValidated,
|
||||
}: CalendarGridProps) {
|
||||
const { toast } = useToast();
|
||||
const monthStart = startOfMonth(currentDate);
|
||||
const monthEnd = endOfMonth(currentDate);
|
||||
|
||||
@@ -54,6 +60,41 @@ 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();
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/orders/${orderId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ status: 'delivered' })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Erreur ${response.status}: ${await response.text()}`);
|
||||
}
|
||||
|
||||
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('Erreur lors de la validation:', 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) {
|
||||
@@ -77,7 +118,7 @@ export default function CalendarGrid({
|
||||
}
|
||||
|
||||
// Essayer plusieurs champs de date possibles
|
||||
const orderDate = safeDate(order.plannedDate || order.orderDate || order.createdAt);
|
||||
const orderDate = safeDate(order.plannedDate || order.createdAt);
|
||||
const matches = orderDate && isSameDay(orderDate, date);
|
||||
|
||||
if (matches) {
|
||||
@@ -100,7 +141,7 @@ export default function CalendarGrid({
|
||||
}
|
||||
|
||||
// Essayer plusieurs champs de date possibles
|
||||
const deliveryDate = safeDate(delivery.scheduledDate || delivery.deliveryDate || delivery.createdAt);
|
||||
const deliveryDate = safeDate(delivery.scheduledDate || delivery.deliveredDate || delivery.createdAt);
|
||||
const matches = deliveryDate && isSameDay(deliveryDate, date);
|
||||
|
||||
if (matches) {
|
||||
@@ -176,7 +217,7 @@ export default function CalendarGrid({
|
||||
return (
|
||||
<div
|
||||
key={`order-${order.id}`}
|
||||
className={`text-xs px-2 py-1 flex items-center justify-between cursor-pointer ${colorClass}`}
|
||||
className={`text-xs px-2 py-1 flex items-center justify-between cursor-pointer group/order ${colorClass}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onItemClick(order, 'order');
|
||||
@@ -186,6 +227,19 @@ export default function CalendarGrid({
|
||||
{order.supplier.name}
|
||||
</span>
|
||||
<div className="flex items-center ml-1 flex-shrink-0">
|
||||
{/* Bouton de validation pour les admins si la commande n'est pas delivered */}
|
||||
{user?.role === 'admin' && order.status !== 'delivered' && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="h-5 w-5 p-0 hover:bg-white/20 opacity-0 group-hover/order:opacity-100 transition-opacity mr-1"
|
||||
onClick={(e) => handleValidateOrder(order.id, e)}
|
||||
title="Valider la commande"
|
||||
>
|
||||
<CheckCircle className="w-3 h-3 text-green-200" />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{order.status === 'planned' && (
|
||||
<span className="w-2 h-2 bg-yellow-300 mr-1" title="Commande planifiée (liée à une livraison)" />
|
||||
)}
|
||||
|
||||
@@ -228,6 +228,11 @@ export default function Calendar() {
|
||||
deliveries={deliveries}
|
||||
onDateClick={handleDateClick}
|
||||
onItemClick={handleItemClick}
|
||||
user={user}
|
||||
onOrderValidated={() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/orders'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user