mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Simplify comment system by removing type and message functionality
Remove comment type, associated icons, labels, and related UI elements. Update API calls and database schema to reflect these changes, simplifying the comment submission and management process. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 95e8aab4-f39f-4b48-aa57-a759ec15ba3d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/95e8aab4-f39f-4b48-aa57-a759ec15ba3d/2QB13hj
This commit is contained in:
1 parent
edbf082c8d
commit
deb01d1a81
4 files changed
+54
-140
No files matched your search
@@ -1,16 +1,14 @@
|
||||
import React, { useState } from "react";
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
import { safeFormat } from "@/lib/dateUtils";
|
||||
import { MessageSquare, Plus, Edit2, Trash2, Save, X, AlertCircle, CheckCircle, AlertTriangle } from "lucide-react";
|
||||
import { MessageSquare, Plus, Edit2, Trash2, Save, X } from "lucide-react";
|
||||
|
||||
interface ReconciliationCommentsProps {
|
||||
deliveryId: number;
|
||||
@@ -20,7 +18,6 @@ interface ReconciliationCommentsProps {
|
||||
interface ReconciliationComment {
|
||||
id: number;
|
||||
content: string;
|
||||
type: 'warning' | 'error' | 'success';
|
||||
deliveryId: number;
|
||||
authorId: string;
|
||||
groupId: number;
|
||||
@@ -33,44 +30,14 @@ interface ReconciliationComment {
|
||||
};
|
||||
}
|
||||
|
||||
const typeColors = {
|
||||
warning: "bg-yellow-50 border-yellow-200 text-yellow-800",
|
||||
error: "bg-red-50 border-red-200 text-red-800",
|
||||
success: "bg-green-50 border-green-200 text-green-800",
|
||||
};
|
||||
|
||||
const typeIcons = {
|
||||
warning: AlertTriangle,
|
||||
error: AlertCircle,
|
||||
success: CheckCircle,
|
||||
};
|
||||
|
||||
const typeLabels = {
|
||||
warning: "Attention",
|
||||
error: "Erreur",
|
||||
success: "Succès",
|
||||
};
|
||||
|
||||
export default function ReconciliationComments({ deliveryId, className = "" }: ReconciliationCommentsProps) {
|
||||
const { toast } = useToast();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const [isAdding, setIsAdding] = useState(false);
|
||||
const [editingId, setEditingId] = useState<number | null>(null);
|
||||
const [newComment, setNewComment] = useState<{
|
||||
content: string;
|
||||
type: 'warning' | 'error' | 'success';
|
||||
}>({
|
||||
content: "",
|
||||
type: "warning",
|
||||
});
|
||||
const [editComment, setEditComment] = useState<{
|
||||
content: string;
|
||||
type: 'warning' | 'error' | 'success';
|
||||
}>({
|
||||
content: "",
|
||||
type: "warning",
|
||||
});
|
||||
const [newComment, setNewComment] = useState("");
|
||||
const [editComment, setEditComment] = useState("");
|
||||
|
||||
// Récupérer les commentaires
|
||||
const { data: comments = [], isLoading } = useQuery({
|
||||
@@ -81,8 +48,8 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
|
||||
// Créer un commentaire
|
||||
const createCommentMutation = useMutation({
|
||||
mutationFn: async (data: { content: string; type: string }) => {
|
||||
return apiRequest(`/api/deliveries/${deliveryId}/reconciliation-comments`, "POST", data);
|
||||
mutationFn: async (content: string) => {
|
||||
return apiRequest(`/api/deliveries/${deliveryId}/reconciliation-comments`, "POST", { content });
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast({
|
||||
@@ -91,7 +58,7 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: [`/api/deliveries/${deliveryId}/reconciliation-comments`] });
|
||||
setIsAdding(false);
|
||||
setNewComment({ content: "", type: "warning" });
|
||||
setNewComment("");
|
||||
},
|
||||
onError: (error: any) => {
|
||||
toast({
|
||||
@@ -104,8 +71,8 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
|
||||
// Modifier un commentaire
|
||||
const updateCommentMutation = useMutation({
|
||||
mutationFn: async ({ id, data }: { id: number; data: { content: string; type: string } }) => {
|
||||
return apiRequest(`/api/reconciliation-comments/${id}`, "PUT", data);
|
||||
mutationFn: async ({ id, content }: { id: number; content: string }) => {
|
||||
return apiRequest(`/api/reconciliation-comments/${id}`, "PUT", { content });
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast({
|
||||
@@ -147,31 +114,28 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
|
||||
const handleAddComment = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!newComment.content.trim()) return;
|
||||
if (!newComment.trim()) return;
|
||||
|
||||
createCommentMutation.mutate(newComment);
|
||||
};
|
||||
|
||||
const handleEditComment = (comment: ReconciliationComment) => {
|
||||
setEditingId(comment.id);
|
||||
setEditComment({
|
||||
content: comment.content,
|
||||
type: comment.type,
|
||||
});
|
||||
setEditComment(comment.content);
|
||||
};
|
||||
|
||||
const handleSaveEdit = () => {
|
||||
if (!editComment.content.trim() || !editingId) return;
|
||||
if (!editComment.trim() || !editingId) return;
|
||||
|
||||
updateCommentMutation.mutate({
|
||||
id: editingId,
|
||||
data: editComment,
|
||||
content: editComment,
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancelEdit = () => {
|
||||
setEditingId(null);
|
||||
setEditComment({ content: "", type: "warning" });
|
||||
setEditComment("");
|
||||
};
|
||||
|
||||
const handleDeleteComment = (id: number) => {
|
||||
@@ -194,7 +158,7 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h4 className="font-medium text-gray-900 flex items-center">
|
||||
<MessageSquare className="w-4 h-4 mr-2" />
|
||||
Commentaires de rapprochement
|
||||
Commentaires
|
||||
{comments.length > 0 && (
|
||||
<Badge variant="secondary" className="ml-2">
|
||||
{comments.length}
|
||||
@@ -202,52 +166,31 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
)}
|
||||
</h4>
|
||||
|
||||
{!isAdding && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => setIsAdding(true)}
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-1" />
|
||||
Ajouter
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => setIsAdding(true)}
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="text-xs"
|
||||
>
|
||||
<Plus className="w-3 h-3 mr-1" />
|
||||
Ajouter
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Formulaire d'ajout */}
|
||||
{isAdding && (
|
||||
<Card className="mb-4 border-dashed">
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm text-gray-600">Nouveau commentaire</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Card className="mb-4 border-blue-200 bg-blue-50">
|
||||
<CardContent className="p-4">
|
||||
<form onSubmit={handleAddComment} className="space-y-3">
|
||||
<div>
|
||||
<Label htmlFor="comment-type">Type</Label>
|
||||
<Select
|
||||
value={newComment.type}
|
||||
onValueChange={(value: any) => setNewComment(prev => ({ ...prev, type: value }))}
|
||||
>
|
||||
<SelectTrigger id="comment-type">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
|
||||
<SelectItem value="warning">Attention</SelectItem>
|
||||
<SelectItem value="error">Erreur</SelectItem>
|
||||
<SelectItem value="success">Succès</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="comment-content">Commentaire</Label>
|
||||
<Label htmlFor="new-comment">Nouveau commentaire</Label>
|
||||
<Textarea
|
||||
id="comment-content"
|
||||
value={newComment.content}
|
||||
onChange={(e) => setNewComment(prev => ({ ...prev, content: e.target.value }))}
|
||||
placeholder="Saisissez votre commentaire..."
|
||||
id="new-comment"
|
||||
value={newComment}
|
||||
onChange={(e) => setNewComment(e.target.value)}
|
||||
placeholder="Tapez votre commentaire..."
|
||||
rows={3}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -258,18 +201,18 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setIsAdding(false);
|
||||
setNewComment({ content: "", type: "warning" });
|
||||
setNewComment("");
|
||||
}}
|
||||
>
|
||||
<X className="w-4 h-4 mr-1" />
|
||||
<X className="w-3 h-3 mr-1" />
|
||||
Annuler
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
size="sm"
|
||||
disabled={!newComment.content.trim() || createCommentMutation.isPending}
|
||||
disabled={createCommentMutation.isPending || !newComment.trim()}
|
||||
>
|
||||
<Save className="w-4 h-4 mr-1" />
|
||||
<Save className="w-3 h-3 mr-1" />
|
||||
{createCommentMutation.isPending ? "Ajout..." : "Ajouter"}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -287,38 +230,19 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
</div>
|
||||
) : (
|
||||
comments.map((comment: ReconciliationComment) => {
|
||||
const TypeIcon = typeIcons[comment.type];
|
||||
const isEditing = editingId === comment.id;
|
||||
|
||||
return (
|
||||
<Card key={comment.id} className={`border ${typeColors[comment.type]}`}>
|
||||
<Card key={comment.id} className="border">
|
||||
<CardContent className="p-4">
|
||||
{isEditing ? (
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<Label htmlFor={`edit-type-${comment.id}`}>Type</Label>
|
||||
<Select
|
||||
value={editComment.type}
|
||||
onValueChange={(value: any) => setEditComment(prev => ({ ...prev, type: value }))}
|
||||
>
|
||||
<SelectTrigger id={`edit-type-${comment.id}`}>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
|
||||
<SelectItem value="warning">Attention</SelectItem>
|
||||
<SelectItem value="error">Erreur</SelectItem>
|
||||
<SelectItem value="success">Succès</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor={`edit-content-${comment.id}`}>Commentaire</Label>
|
||||
<Textarea
|
||||
id={`edit-content-${comment.id}`}
|
||||
value={editComment.content}
|
||||
onChange={(e) => setEditComment(prev => ({ ...prev, content: e.target.value }))}
|
||||
value={editComment}
|
||||
onChange={(e) => setEditComment(e.target.value)}
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
@@ -330,56 +254,49 @@ export default function ReconciliationComments({ deliveryId, className = "" }: R
|
||||
size="sm"
|
||||
onClick={handleCancelEdit}
|
||||
>
|
||||
<X className="w-4 h-4 mr-1" />
|
||||
<X className="w-3 h-3 mr-1" />
|
||||
Annuler
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={handleSaveEdit}
|
||||
disabled={!editComment.content.trim() || updateCommentMutation.isPending}
|
||||
disabled={updateCommentMutation.isPending || !editComment.trim()}
|
||||
>
|
||||
<Save className="w-4 h-4 mr-1" />
|
||||
{updateCommentMutation.isPending ? "Sauvegarde..." : "Sauvegarder"}
|
||||
<Save className="w-3 h-3 mr-1" />
|
||||
{updateCommentMutation.isPending ? "Enregistrement..." : "Enregistrer"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className="flex items-start justify-between mb-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<TypeIcon className="w-4 h-4" />
|
||||
<Badge variant="outline">
|
||||
{typeLabels[comment.type]}
|
||||
</Badge>
|
||||
<div className="flex-1">
|
||||
<p className="text-gray-900 mb-2">{comment.content}</p>
|
||||
<div className="text-xs text-gray-500">
|
||||
Par {comment.author.email} • {safeFormat(comment.createdAt, "dd/MM/yyyy 'à' HH:mm")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-1">
|
||||
<div className="flex space-x-1 ml-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleEditComment(comment)}
|
||||
className="h-6 w-6 p-0"
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<Edit2 className="w-3 h-3" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleDeleteComment(comment.id)}
|
||||
className="h-6 w-6 p-0 text-red-500 hover:text-red-700"
|
||||
className="h-8 w-8 p-0 text-red-600 hover:text-red-700"
|
||||
>
|
||||
<Trash2 className="w-3 h-3" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-sm mb-2">{comment.content}</p>
|
||||
|
||||
<div className="text-xs text-gray-500 flex items-center justify-between">
|
||||
<span>Par {comment.author.email}</span>
|
||||
<span>{safeFormat(new Date(comment.createdAt), 'dd/MM/yyyy HH:mm')}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
|
||||
@@ -147,8 +147,7 @@ export default function BLReconciliation() {
|
||||
const createCommentMutation = useMutation({
|
||||
mutationFn: async ({ deliveryId, content }: { deliveryId: number; content: string }) => {
|
||||
const response = await apiRequest(`/api/deliveries/${deliveryId}/reconciliation-comments`, 'POST', {
|
||||
content,
|
||||
type: 'warning'
|
||||
content
|
||||
});
|
||||
return response;
|
||||
},
|
||||
|
||||
@@ -2585,7 +2585,6 @@ export class DatabaseStorage implements IStorage {
|
||||
deliveryId: reconciliationComments.deliveryId,
|
||||
groupId: reconciliationComments.groupId,
|
||||
content: reconciliationComments.content,
|
||||
type: reconciliationComments.type,
|
||||
authorId: reconciliationComments.authorId,
|
||||
createdAt: reconciliationComments.createdAt,
|
||||
updatedAt: reconciliationComments.updatedAt,
|
||||
|
||||
@@ -183,7 +183,6 @@ export const reconciliationComments = pgTable("reconciliation_comments", {
|
||||
deliveryId: integer("delivery_id").notNull(), // Référence vers la livraison concernée
|
||||
groupId: integer("group_id").notNull(), // Magasin/groupe pour filtrage
|
||||
content: text("content").notNull(), // Contenu du commentaire
|
||||
type: varchar("type", { length: 50 }).notNull().default("warning"), // warning, error, success
|
||||
authorId: varchar("author_id").notNull(), // Utilisateur auteur du commentaire
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
updatedAt: timestamp("updated_at").defaultNow(),
|
||||
|
||||
Reference in new issue
Block a user