diff --git a/client/src/components/AnnouncementCard.tsx b/client/src/components/AnnouncementCard.tsx index d56e520..e982708 100644 --- a/client/src/components/AnnouncementCard.tsx +++ b/client/src/components/AnnouncementCard.tsx @@ -387,33 +387,31 @@ export default function AnnouncementCard() { return (
-
- -
-
-

- {announcement.title} -

- - {priorityConfig.label} - -
- - {announcement.content && ( -

- {announcement.content} -

- )} - -
- - {safeFormat(safeDate(announcement.createdAt), 'dd/MM à HH:mm')} - - - {announcement.author.firstName} {announcement.author.lastName} - {announcement.group && ` • ${announcement.group.name}`} - -
+
+
+

+ {announcement.title} +

+ + + {priorityConfig.label} + +
+ + {announcement.content && ( +

+ {announcement.content} +

+ )} + +
+ + {safeFormat(safeDate(announcement.createdAt), 'dd/MM à HH:mm')} + + + {announcement.author.firstName} {announcement.author.lastName} + {announcement.group && ` • ${announcement.group.name}`} +
{user?.role === 'admin' && ( diff --git a/server/announcementStorage.ts b/server/announcementStorage.ts index 4927da8..12ea3ef 100644 --- a/server/announcementStorage.ts +++ b/server/announcementStorage.ts @@ -1,7 +1,90 @@ -import { Announcement, InsertAnnouncement, AnnouncementWithRelations, User, Group } from "@shared/schema"; +import { DashboardMessage, InsertDashboardMessage, DashboardMessageWithRelations, User, Group } from "@shared/schema"; +import { db } from "./db"; +import { dashboardMessages, users, groups } from "@shared/schema"; +import { eq, desc } from "drizzle-orm"; -// Stockage en mémoire partagé pour les annonces (maximum 5) -class AnnouncementMemoryStorage { +// Type aliases pour compatibilité +type Announcement = DashboardMessage; +type InsertAnnouncement = InsertDashboardMessage; +type AnnouncementWithRelations = DashboardMessageWithRelations; + +// Interface commune pour le stockage +interface IAnnouncementStorage { + getAnnouncements(groupIds?: number[]): Promise; + createAnnouncement(announcement: InsertAnnouncement): Promise; + updateAnnouncement(id: number, announcement: Partial): Promise; + deleteAnnouncement(id: number): Promise; +} + +// Stockage PostgreSQL pour la production +class AnnouncementDatabaseStorage implements IAnnouncementStorage { + async getAnnouncements(groupIds?: number[]): Promise { + let query = db + .select({ + id: dashboardMessages.id, + title: dashboardMessages.title, + content: dashboardMessages.content, + type: dashboardMessages.type, + storeId: dashboardMessages.storeId, + createdBy: dashboardMessages.createdBy, + createdAt: dashboardMessages.createdAt, + author: { + id: users.id, + firstName: users.firstName, + lastName: users.lastName, + username: users.username, + }, + group: { + id: groups.id, + name: groups.name, + }, + }) + .from(dashboardMessages) + .leftJoin(users, eq(dashboardMessages.createdBy, users.id)) + .leftJoin(groups, eq(dashboardMessages.storeId, groups.id)) + .orderBy(desc(dashboardMessages.createdAt)); + + const results = await query; + + return results.map(result => ({ + id: result.id, + title: result.title, + content: result.content, + type: result.type, + storeId: result.storeId, + createdBy: result.createdBy, + createdAt: result.createdAt, + author: result.author as User, + group: result.group as Group | undefined, + })); + } + + async createAnnouncement(announcement: InsertAnnouncement): Promise { + const [created] = await db + .insert(dashboardMessages) + .values(announcement) + .returning(); + return created; + } + + async updateAnnouncement(id: number, announcement: Partial): Promise { + const [updated] = await db + .update(dashboardMessages) + .set(announcement) + .where(eq(dashboardMessages.id, id)) + .returning(); + return updated; + } + + async deleteAnnouncement(id: number): Promise { + await db + .delete(dashboardMessages) + .where(eq(dashboardMessages.id, id)); + } +} + +// Stockage en mémoire pour le développement +class AnnouncementMemoryStorage implements IAnnouncementStorage { private announcements = new Map(); private idCounter = 1; private readonly MAX_ANNOUNCEMENTS = 5; @@ -178,16 +261,30 @@ class AnnouncementMemoryStorage { } } -// Instance globale partagée -let globalAnnouncementStorage: AnnouncementMemoryStorage | null = null; +// Instances globales pour les différents environnements +let memoryInstance: AnnouncementMemoryStorage | null = null; +let databaseInstance: AnnouncementDatabaseStorage | null = null; export function getAnnouncementStorage( - usersGetter: () => Promise, - groupsGetter: () => Promise -): AnnouncementMemoryStorage { - if (!globalAnnouncementStorage) { - globalAnnouncementStorage = new AnnouncementMemoryStorage(usersGetter, groupsGetter); - console.log('📢 Stockage mémoire des annonces initialisé'); + usersGetter?: () => Promise, + groupsGetter?: () => Promise +): IAnnouncementStorage { + const isProduction = process.env.NODE_ENV === 'production'; + + if (isProduction) { + if (!databaseInstance) { + databaseInstance = new AnnouncementDatabaseStorage(); + console.log('📢 Stockage PostgreSQL des annonces initialisé pour la production'); + } + return databaseInstance; + } else { + if (!memoryInstance) { + if (!usersGetter || !groupsGetter) { + throw new Error("usersGetter and groupsGetter are required for memory storage initialization"); + } + memoryInstance = new AnnouncementMemoryStorage(usersGetter, groupsGetter); + console.log('📢 Stockage mémoire des annonces initialisé pour le développement'); + } + return memoryInstance; } - return globalAnnouncementStorage; } \ No newline at end of file diff --git a/shared/schema.ts b/shared/schema.ts index ec72b24..44cbc37 100644 --- a/shared/schema.ts +++ b/shared/schema.ts @@ -70,6 +70,8 @@ export const userGroups = pgTable("user_groups", { createdAt: timestamp("created_at").defaultNow(), }); + + // Suppliers - Schema exact correspondant à la production export const suppliers = pgTable("suppliers", { id: serial("id").primaryKey(), @@ -530,15 +532,12 @@ export const insertTaskSchema = createInsertSchema(tasks).omit({ dueDate: z.coerce.date().optional().nullable(), // Convertit automatiquement les chaînes en Date }); -export const insertAnnouncementSchema = createInsertSchema(dashboardMessages).omit({ +export const insertDashboardMessageSchema = createInsertSchema(dashboardMessages).omit({ id: true, createdAt: true, -}).extend({ - type: z.enum(["info", "warning", "error", "success"]).default("info"), }); -// Mapping pour la compatibilité avec l'interface actuelle -export const insertDashboardMessageSchema = insertAnnouncementSchema; +export const insertAnnouncementSchema = insertDashboardMessageSchema; export const insertNocodbConfigSchema = createInsertSchema(nocodbConfig).omit({ id: true,