From 515ca5583605c8f9f563d2b58145dd08fbb08ac8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 21 Feb 2026 20:04:46 +0100 Subject: [PATCH] feat(export): export modified gammes to excel with specified columns --- src/app/api/export/modified-gammes/route.ts | 75 +++++++++++++++++++ .../grid/components/floating-summary-bar.tsx | 41 +++++++++- 2 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/app/api/export/modified-gammes/route.ts diff --git a/src/app/api/export/modified-gammes/route.ts b/src/app/api/export/modified-gammes/route.ts new file mode 100644 index 0000000..f65d767 --- /dev/null +++ b/src/app/api/export/modified-gammes/route.ts @@ -0,0 +1,75 @@ +import { NextRequest, NextResponse } from "next/server"; +import ExcelJS from "exceljs"; +import { z } from "zod"; + +const ExportModifiedGammesSchema = z.object({ + nomFournisseur: z.string(), + changes: z.array(z.object({ + codein: z.string(), + gtin: z.string(), + gamme: z.string(), + })), +}); + +export async function POST(req: NextRequest) { + const body = await req.json(); + const parsed = ExportModifiedGammesSchema.safeParse(body); + if (!parsed.success) { + return NextResponse.json({ error: "Invalid payload" }, { status: 400 }); + } + + const { nomFournisseur, changes } = parsed.data; + const workbook = new ExcelJS.Workbook(); + workbook.creator = "CollectFlow"; + workbook.created = new Date(); + + const sheet = workbook.addWorksheet("Gammes Modifiées", { + views: [{ state: "frozen", ySplit: 1 }], + }); + + // Header style + const headerStyle: Partial = { + font: { bold: true, color: { argb: "FFFFFFFF" } }, + fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FF0F172A" } }, + alignment: { horizontal: "center" }, + border: { bottom: { style: "thin", color: { argb: "FF334155" } } }, + }; + + sheet.columns = [ + { header: "CODE FOURNISSEUR", key: "codein", width: 22 }, + { header: "GENCOD", key: "gtin", width: 18 }, + { header: "GAMME", key: "gamme", width: 12 }, + ]; + + // Apply header style + sheet.getRow(1).eachCell((cell) => { Object.assign(cell, headerStyle); }); + sheet.getRow(1).height = 22; + + for (const row of changes) { + sheet.addRow({ + codein: row.codein, + gtin: row.gtin || "—", + gamme: row.gamme || "—", + }); + } + + // Centrer la colonne Gamme + const gammeCol = sheet.getColumn("gamme"); + gammeCol.alignment = { horizontal: "center" }; + + // Format codein et gtin en texte pour eviter la notation scientifique excel + sheet.getColumn("codein").numFmt = "@"; + sheet.getColumn("gtin").numFmt = "@"; + + // Generate buffer + const buffer = await workbook.xlsx.writeBuffer(); + + const filename = `Modifications_Gammes_${nomFournisseur.replace(/\s+/g, "_")}_${new Date().toISOString().slice(0, 10)}.xlsx`; + + return new NextResponse(buffer, { + headers: { + "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "Content-Disposition": `attachment; filename="${filename}"`, + }, + }); +} diff --git a/src/features/grid/components/floating-summary-bar.tsx b/src/features/grid/components/floating-summary-bar.tsx index c8a9983..7d4c4f1 100644 --- a/src/features/grid/components/floating-summary-bar.tsx +++ b/src/features/grid/components/floating-summary-bar.tsx @@ -49,8 +49,46 @@ export function FloatingSummaryBar() { /> -
+
+