From eec5e397fe5952a662131b0b3fe857f54c43f86b Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Tue, 28 Oct 2025 12:43:14 +0000 Subject: [PATCH] Improve calendar view and add scheduling conflict warnings Enhance the calendar list view to prioritize today's date and introduce visual indicators for optimal posting times and existing scheduled posts on the new post page. 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/VJoXNjs --- client/src/components/calendar-list-view.tsx | 11 ++- client/src/pages/new-post.tsx | 82 +++++++++++++++++++- replit.md | 1 + 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/client/src/components/calendar-list-view.tsx b/client/src/components/calendar-list-view.tsx index 0ca4a3e..2ddbce7 100644 --- a/client/src/components/calendar-list-view.tsx +++ b/client/src/components/calendar-list-view.tsx @@ -42,8 +42,15 @@ export default function CalendarListView({ scheduledPosts, onEditPost, onDeleteP return acc; }, {}); - // Sort dates - const sortedDates = Object.keys(groupedPosts).sort(); + // Sort dates - put today first, then chronological order + const today = format(new Date(), "yyyy-MM-dd"); + const sortedDates = Object.keys(groupedPosts).sort((a, b) => { + // Today always comes first + if (a === today && b !== today) return -1; + if (b === today && a !== today) return 1; + // Otherwise chronological order + return a.localeCompare(b); + }); const toggleDate = (date: string) => { const newExpanded = new Set(expandedDates); diff --git a/client/src/pages/new-post.tsx b/client/src/pages/new-post.tsx index 83fd9dc..7a1cdb2 100644 --- a/client/src/pages/new-post.tsx +++ b/client/src/pages/new-post.tsx @@ -32,7 +32,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import { Dialog, DialogContent } from "@/components/ui/dialog"; import { useToast } from "@/hooks/use-toast"; import { apiRequest, queryClient } from "@/lib/queryClient"; -import type { SocialPage, Media } from "@shared/schema"; +import type { SocialPage, Media, ScheduledPost } from "@shared/schema"; import { PreviewModal } from "@/components/preview-modal"; function SortableMediaItem({ @@ -127,6 +127,10 @@ export default function NewPost() { queryKey: ['/api/media'], }); + const { data: scheduledPosts = [] } = useQuery({ + queryKey: ['/api/scheduled-posts'], + }); + const uploadMutation = useMutation({ mutationFn: async (file: File) => { const formData = new FormData(); @@ -707,7 +711,7 @@ export default function NewPost() { Programmez la publication (optionnel) -
+
Laissez vide pour publier immédiatement

+ + {(() => { + // Get dates with scheduled posts + const datesWithPosts = scheduledPosts + .filter(post => post.scheduledAt) + .map(post => { + const date = new Date(post.scheduledAt!); + return date.toISOString().split('T')[0]; + }) + .filter((date, index, self) => self.indexOf(date) === index) + .sort(); + + if (datesWithPosts.length > 0) { + return ( +
+
+
+ + Dates avec publications programmées + +
+
+ {datesWithPosts.slice(0, 5).map((date) => { + const dateObj = new Date(date + 'T00:00:00'); + const formatted = dateObj.toLocaleDateString('fr-FR', { + day: '2-digit', + month: 'short' + }); + return ( + + {formatted} + + ); + })} + {datesWithPosts.length > 5 && ( + + +{datesWithPosts.length - 5} autre{datesWithPosts.length - 5 > 1 ? 's' : ''} + + )} +
+

+ Ces dates ont déjà des publications planifiées +

+
+ ); + } + return null; + })()} + +
+
+
+ + Heures optimales pour l'audience + +
+
+ + 8h - 9h + + + 12h - 14h + + + 18h - 21h + +
+

+ Ces créneaux maximisent la portée de vos publications +

+
diff --git a/replit.md b/replit.md index 0062e4e..213f6a1 100644 --- a/replit.md +++ b/replit.md @@ -11,6 +11,7 @@ Preferred communication style: Simple, everyday language. ## Recent Changes ### October 28, 2025 +- **Calendar Mobile UX Improvements**: Enhanced mobile calendar and publication planning interface with three visual improvements: (1) Mobile calendar list now displays today's date at the top, before chronological ordering, for quick access to current day's publications; (2) Added green visual indicators in new-post page showing optimal posting times (8h-9h, 12h-14h, 18h-21h) to maximize audience reach; (3) Added red visual indicators showing dates with existing scheduled posts to prevent scheduling conflicts. Both indicators appear dynamically below the datetime selector, displaying up to 5 dates with option to view more. - **Facebook Video Story Publishing Fix**: Fixed critical bug preventing video story publication. Facebook Graph API requires a 3-phase upload process for video stories: (1) START phase - initialize upload session and get `video_id` + `upload_url`, (2) UPLOAD phase - POST video to rupload.facebook.com endpoint with `file_url` header and OAuth authorization, (3) FINISH phase - finalize and publish story with `video_id`. Previous implementation incorrectly attempted direct upload to `/video_stories` endpoint with `file_url` parameter, causing "#100 The parameter upload_phase is required" error. Fixed by implementing proper 3-phase workflow using remote URL upload method (file_url header), avoiding need for binary chunked uploads. ### October 17, 2025