From d7dbb0bcce9eb35765326efcb1f8ef50f59f08cd Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Thu, 9 Oct 2025 08:25:13 +0000 Subject: [PATCH] Enable editing of scheduled posts with text and media previews Update the edit scheduled post dialog to allow modification of post content and associated media, incorporating fetched post data and a new text area component. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/ER8Naji --- .../components/edit-scheduled-post-dialog.tsx | 218 +++++++++++++++--- 1 file changed, 180 insertions(+), 38 deletions(-) diff --git a/client/src/components/edit-scheduled-post-dialog.tsx b/client/src/components/edit-scheduled-post-dialog.tsx index e93338e..f70732d 100644 --- a/client/src/components/edit-scheduled-post-dialog.tsx +++ b/client/src/components/edit-scheduled-post-dialog.tsx @@ -2,12 +2,14 @@ import { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { useQuery, useMutation } from "@tanstack/react-query"; import { useToast } from "@/hooks/use-toast"; import { apiRequest, queryClient } from "@/lib/queryClient"; -import type { SocialPage } from "@shared/schema"; +import type { SocialPage, Media, Post } from "@shared/schema"; import { format } from "date-fns"; +import { Image as ImageIcon, CheckCircle } from "lucide-react"; interface EditScheduledPostDialogProps { open: boolean; @@ -20,11 +22,23 @@ export default function EditScheduledPostDialog({ open, onOpenChange, scheduledP const [date, setDate] = useState(""); const [time, setTime] = useState(""); const [pageId, setPageId] = useState(""); + const [postText, setPostText] = useState(""); + const [selectedMediaIds, setSelectedMediaIds] = useState([]); const { data: pages = [] } = useQuery({ queryKey: ["/api/pages"], }); + const { data: postData } = useQuery<{ post: Post; media: Media[] }>({ + queryKey: ["/api/posts", scheduledPost?.postId], + enabled: !!scheduledPost?.postId && open, + }); + + const { data: allMedia = [] } = useQuery({ + queryKey: ["/api/media"], + enabled: open, + }); + useEffect(() => { if (scheduledPost && open) { const scheduledAt = new Date(scheduledPost.scheduledAt); @@ -34,27 +48,38 @@ export default function EditScheduledPostDialog({ open, onOpenChange, scheduledP } }, [scheduledPost, open]); - const updateMutation = useMutation({ + useEffect(() => { + if (postData && open) { + setPostText(postData.post.content); + setSelectedMediaIds(postData.media.map(m => m.id)); + } + }, [postData, open]); + + const updateScheduledMutation = useMutation({ mutationFn: (data: { scheduledAt: string; pageId: string }) => apiRequest('PATCH', `/api/scheduled-posts/${scheduledPost.id}`, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/api/scheduled-posts'] }); - toast({ - title: "Programmation modifiée", - description: "La date et l'heure ont été mises à jour avec succès", - }); - onOpenChange(false); - }, - onError: () => { - toast({ - title: "Erreur", - description: "Impossible de modifier la programmation", - variant: "destructive", - }); }, }); - const handleSave = () => { + const updatePostTextMutation = useMutation({ + mutationFn: (data: { content: string }) => + apiRequest('PATCH', `/api/posts/${scheduledPost?.postId}`, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/posts', scheduledPost?.postId] }); + }, + }); + + const updatePostMediaMutation = useMutation({ + mutationFn: (data: { mediaIds: string[] }) => + apiRequest('PATCH', `/api/posts/${scheduledPost?.postId}/media`, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/posts', scheduledPost?.postId] }); + }, + }); + + const handleSave = async () => { if (!date || !time || !pageId) { toast({ title: "Erreur", @@ -64,40 +89,157 @@ export default function EditScheduledPostDialog({ open, onOpenChange, scheduledP return; } - const scheduledAt = new Date(`${date}T${time}`); - updateMutation.mutate({ scheduledAt: scheduledAt.toISOString(), pageId }); + try { + const scheduledAt = new Date(`${date}T${time}`); + + await updateScheduledMutation.mutateAsync({ scheduledAt: scheduledAt.toISOString(), pageId }); + + if (postData && postText !== postData.post.content) { + await updatePostTextMutation.mutateAsync({ content: postText }); + } + + const currentMediaIds = postData?.media.map(m => m.id) || []; + if (JSON.stringify(selectedMediaIds) !== JSON.stringify(currentMediaIds)) { + await updatePostMediaMutation.mutateAsync({ mediaIds: selectedMediaIds }); + } + + toast({ + title: "Modifications enregistrées", + description: "Le post a été mis à jour avec succès", + }); + onOpenChange(false); + } catch (error) { + toast({ + title: "Erreur", + description: "Impossible de modifier le post", + variant: "destructive", + }); + } }; + const toggleMediaSelection = (mediaId: string) => { + setSelectedMediaIds(prev => { + if (prev.includes(mediaId)) { + return prev.filter(id => id !== mediaId); + } else { + if (prev.length >= 10) { + toast({ + title: "Limite atteinte", + description: "Maximum 10 photos par publication", + variant: "destructive", + }); + return prev; + } + return [...prev, mediaId]; + } + }); + }; + + const isPending = updateScheduledMutation.isPending || updatePostTextMutation.isPending || updatePostMediaMutation.isPending; + return ( - + - Modifier la programmation + Modifier le post
- - setDate(e.target.value)} - className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" - data-testid="input-scheduled-date" + +