mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-22 14:38:19 +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 { format, startOfMonth, endOfMonth, eachDayOfInterval, isSameDay, isSameMonth, isToday } from "date-fns";
|
||||||
import { fr } from "date-fns/locale";
|
import { fr } from "date-fns/locale";
|
||||||
import { safeDate } from "@/lib/dateUtils";
|
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 { Button } from "@/components/ui/button";
|
||||||
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import type { OrderWithRelations, DeliveryWithRelations } from "@shared/schema";
|
import type { OrderWithRelations, DeliveryWithRelations } from "@shared/schema";
|
||||||
|
|
||||||
interface CalendarGridProps {
|
interface CalendarGridProps {
|
||||||
@@ -11,6 +12,8 @@ interface CalendarGridProps {
|
|||||||
deliveries: DeliveryWithRelations[];
|
deliveries: DeliveryWithRelations[];
|
||||||
onDateClick: (date: Date) => void;
|
onDateClick: (date: Date) => void;
|
||||||
onItemClick: (item: any, type: 'order' | 'delivery') => void;
|
onItemClick: (item: any, type: 'order' | 'delivery') => void;
|
||||||
|
user?: { role: string } | null;
|
||||||
|
onOrderValidated?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CalendarGrid({
|
export default function CalendarGrid({
|
||||||
@@ -19,7 +22,10 @@ export default function CalendarGrid({
|
|||||||
deliveries,
|
deliveries,
|
||||||
onDateClick,
|
onDateClick,
|
||||||
onItemClick,
|
onItemClick,
|
||||||
|
user,
|
||||||
|
onOrderValidated,
|
||||||
}: CalendarGridProps) {
|
}: CalendarGridProps) {
|
||||||
|
const { toast } = useToast();
|
||||||
const monthStart = startOfMonth(currentDate);
|
const monthStart = startOfMonth(currentDate);
|
||||||
const monthEnd = endOfMonth(currentDate);
|
const monthEnd = endOfMonth(currentDate);
|
||||||
|
|
||||||
@@ -54,6 +60,41 @@ export default function CalendarGrid({
|
|||||||
|
|
||||||
const weekDays = ["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"];
|
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) => {
|
const getItemsForDate = (date: Date) => {
|
||||||
// Debug: Log des commandes reçues (seulement une fois)
|
// Debug: Log des commandes reçues (seulement une fois)
|
||||||
if (orders.length > 0 && date.getDate() === 1) {
|
if (orders.length > 0 && date.getDate() === 1) {
|
||||||
@@ -77,7 +118,7 @@ export default function CalendarGrid({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Essayer plusieurs champs de date possibles
|
// 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);
|
const matches = orderDate && isSameDay(orderDate, date);
|
||||||
|
|
||||||
if (matches) {
|
if (matches) {
|
||||||
@@ -100,7 +141,7 @@ export default function CalendarGrid({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Essayer plusieurs champs de date possibles
|
// 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);
|
const matches = deliveryDate && isSameDay(deliveryDate, date);
|
||||||
|
|
||||||
if (matches) {
|
if (matches) {
|
||||||
@@ -176,7 +217,7 @@ export default function CalendarGrid({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={`order-${order.id}`}
|
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) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onItemClick(order, 'order');
|
onItemClick(order, 'order');
|
||||||
@@ -186,6 +227,19 @@ export default function CalendarGrid({
|
|||||||
{order.supplier.name}
|
{order.supplier.name}
|
||||||
</span>
|
</span>
|
||||||
<div className="flex items-center ml-1 flex-shrink-0">
|
<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' && (
|
{order.status === 'planned' && (
|
||||||
<span className="w-2 h-2 bg-yellow-300 mr-1" title="Commande planifiée (liée à une livraison)" />
|
<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}
|
deliveries={deliveries}
|
||||||
onDateClick={handleDateClick}
|
onDateClick={handleDateClick}
|
||||||
onItemClick={handleItemClick}
|
onItemClick={handleItemClick}
|
||||||
|
user={user}
|
||||||
|
onOrderValidated={() => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['/api/orders'] });
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] });
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user