diff --git a/.replit b/.replit index d51ca2b..998c030 100644 --- a/.replit +++ b/.replit @@ -22,6 +22,10 @@ externalPort = 3003 localPort = 35357 externalPort = 3002 +[[ports]] +localPort = 35903 +externalPort = 6800 + [[ports]] localPort = 37431 externalPort = 5000 diff --git a/server/routes.ts b/server/routes.ts index f92ba5a..28c51aa 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -557,11 +557,39 @@ export async function registerRoutes(app: Express): Promise { try { const user = req.user as User; const userId = user.id; - const { pageIds, postType, mediaId, ...postFields } = req.body; + const { pageIds, postType, mediaId, mediaIds, ...postFields } = req.body; + + // Convert mediaIds to standardized format: array of { mediaId, displayOrder } + let finalMediaItems: Array<{ mediaId: string; displayOrder: number }> = []; + + if (mediaIds && Array.isArray(mediaIds)) { + // New format: array of objects or strings + finalMediaItems = mediaIds.map((item: any, index: number) => { + if (typeof item === 'string') { + // Legacy array of strings: use index as displayOrder + return { mediaId: item, displayOrder: index }; + } else if (item.mediaId) { + // New format: object with mediaId and displayOrder + return { + mediaId: item.mediaId, + displayOrder: item.displayOrder ?? index, + }; + } + throw new Error("Invalid media format"); + }); + } else if (mediaId) { + // Legacy single mediaId + finalMediaItems = [{ mediaId, displayOrder: 0 }]; + } + + // Validate max 10 photos + if (finalMediaItems.length > 10) { + return res.status(400).json({ error: "Maximum 10 photos autorisées par publication" }); + } // Validate that stories require media - if ((postType === 'story' || postType === 'both') && !mediaId) { - return res.status(400).json({ error: "Les stories nécessitent un média (image ou vidéo)" }); + if ((postType === 'story' || postType === 'both') && finalMediaItems.length === 0) { + return res.status(400).json({ error: "Les stories nécessitent au moins un média (image ou vidéo)" }); } // Convert scheduledFor string to Date if provided @@ -573,12 +601,14 @@ export async function registerRoutes(app: Express): Promise { const postData = insertPostSchema.parse({ ...postFields, userId }); const post = await storage.createPost(postData); - // Link media to post if provided - if (mediaId) { - await db.insert(postMedia).values({ + // Link media to post if provided (with display order) + if (finalMediaItems.length > 0) { + const postMediaValues = finalMediaItems.map(item => ({ postId: post.id, - mediaId: mediaId, - }); + mediaId: item.mediaId, + displayOrder: item.displayOrder, + })); + await db.insert(postMedia).values(postMediaValues); } // Create scheduled posts for each selected page diff --git a/server/storage.ts b/server/storage.ts index 82a7b95..20571bd 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -30,7 +30,7 @@ import { type InsertUserPagePermission, } from "@shared/schema"; import { db } from "./db"; -import { eq, and, gte, lte, desc, isNull } from "drizzle-orm"; +import { eq, and, gte, lte, desc, asc, isNull } from "drizzle-orm"; export interface IStorage { // Users @@ -168,7 +168,7 @@ export class DatabaseStorage implements IStorage { } async getPostMedia(postId: string): Promise { - return await db.select().from(postMedia).where(eq(postMedia.postId, postId)); + return await db.select().from(postMedia).where(eq(postMedia.postId, postId)).orderBy(asc(postMedia.displayOrder)); } // Posts