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