From 3636676dbc4e2a6b62c6f4cf41f8a0e12204e821 Mon Sep 17 00:00:00 2001 From: SmartRootsSrl Date: Fri, 20 Mar 2026 16:39:26 +0100 Subject: [PATCH] docs: add implementation plan for page1 header restyle --- .../plans/2026-03-20-page1-header-restyle.md | 303 ++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 docs/superpowers/plans/2026-03-20-page1-header-restyle.md diff --git a/docs/superpowers/plans/2026-03-20-page1-header-restyle.md b/docs/superpowers/plans/2026-03-20-page1-header-restyle.md new file mode 100644 index 0000000..61183ad --- /dev/null +++ b/docs/superpowers/plans/2026-03-20-page1-header-restyle.md @@ -0,0 +1,303 @@ +# Page 1 Header Restyle & Label Fixes — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Redesign l'header di pagina 1 (titolo centrato + box Tipologia/Data/Bid/Ask uniformi), rinominare colonne nelle tabelle Sottostanti ed Eventi, e fixare lo spazio nel footer branding. + +**Architecture:** Modifiche localizzate a 3 file esistenti. Nessuna nuova classe o interfaccia. Le nuove costanti colore/brush vengono aggiunte a `PdfTheme.cs` seguendo il pattern `=>` già usato nel file. Il nuovo `DrawTitle` in `AnagraficaSectionRenderer` è una riscrittura completa del metodo esistente. + +**Tech Stack:** C# / ASP.NET Core 8, Syncfusion PDF v33, Syncfusion.Drawing + +--- + +## File map + +| File | Modifica | +|------|----------| +| `CertReports.Syncfusion/Helpers/PdfTheme.cs` | Aggiungi 6 colori + 5 brush (stile `=>`) + fix footer offset (+2pt) | +| `CertReports.Syncfusion/Services/Implementations/AnagraficaSectionRenderer.cs` | Riscrivi `DrawTitle`, aggiungi `DrawInfoBox`, rinomina headers sottostanti | +| `CertReports.Syncfusion/Services/Implementations/EventiSectionRenderer.cs` | Rinomina "Trigger CPN" → "Trigger Cedola" | + +--- + +## Task 1: Nuovi colori e fix footer in PdfTheme.cs + +**Files:** +- Modify: `CertReports.Syncfusion/Helpers/PdfTheme.cs` + +- [ ] **Step 1: Aggiungi nuove costanti colore** + + Inserisci dopo la riga `public static readonly Color TableAltRow = ...` (blocco colori, riga ~33): + + ```csharp + // Colori box header pagina 1 + public static readonly Color AccentBlueDark = Color.FromArgb(255, 13, 71, 161); // #0D47A1 + public static readonly Color BoxLightBlueBg = Color.FromArgb(255, 235, 242, 251); // #EBF2FB + public static readonly Color BoxGrayBg = Color.FromArgb(255, 245, 245, 245); // #F5F5F5 + public static readonly Color BoxGrayAccent = Color.FromArgb(255, 136, 136, 136); // #888888 + public static readonly Color BoxGrayLabel = Color.FromArgb(255, 102, 102, 102); // #666666 + public static readonly Color BoxGrayValue = Color.FromArgb(255, 51, 51, 51); // #333333 + ``` + +- [ ] **Step 2: Aggiungi i brush corrispondenti — usa il pattern `=>` come il resto del file** + + Inserisci dopo la riga `public static PdfPen AccentBluePen => ...` (blocco Brushes, riga ~86): + + ```csharp + public static PdfBrush AccentBlueDarkBrush => new PdfSolidBrush(AccentBlueDark); + public static PdfBrush BoxLightBlueBgBrush => new PdfSolidBrush(BoxLightBlueBg); + public static PdfBrush BoxGrayBgBrush => new PdfSolidBrush(BoxGrayBg); + public static PdfBrush BoxGrayAccentBrush => new PdfSolidBrush(BoxGrayAccent); + public static PdfBrush BoxGrayLabelBrush => new PdfSolidBrush(BoxGrayLabel); + public static PdfBrush BoxGrayValueBrush => new PdfSolidBrush(BoxGrayValue); + ``` + +- [ ] **Step 3: Fix footer — cambia solo l'argomento `PointF` in `DrawTextWebLink` (riga ~203)** + + ```csharp + // PRIMA: + webLink.DrawTextWebLink(g, new PointF(prefixWidth, footerY)); + + // DOPO: + webLink.DrawTextWebLink(g, new PointF(prefixWidth + 2f, footerY)); + ``` + + > Il `DrawString` del testo prefisso (riga ~193) usa già `prefixWidth + 2f` come larghezza del `RectangleF` — questo fix allinea solo il punto di partenza del link. + +- [ ] **Step 4: Build** + + ```bash + dotnet build CertReports.Syncfusion/CertReports.Syncfusion.csproj + ``` + Atteso: `Build succeeded` senza errori. + +- [ ] **Step 5: Commit** + + ```bash + git add CertReports.Syncfusion/Helpers/PdfTheme.cs + git commit -m "feat: add box header colors/brushes and fix footer branding offset" + ``` + +--- + +## Task 2: Riscrittura DrawTitle in AnagraficaSectionRenderer.cs + +**Files:** +- Modify: `CertReports.Syncfusion/Services/Implementations/AnagraficaSectionRenderer.cs` + +Il metodo `DrawTitle` (righe 74-112) viene sostituito interamente. Si aggiunge il metodo privato `DrawInfoBox`. + +**Layout:** +``` + Scheda Prodotto XS1234567890 ← centrato, AccentBlue, SectionTitleFont +───────────────────────────────────────── ← AccentBluePen +[TIPOLOGIA / Cert. Bonus Cap] [DATA / 18/03] [BID / 98.50] [ASK / 99.20] +``` + +**Dimensioni box:** +- Altezza: `28f`; Gap: `6f`; Larghezza Data: `84f`, Bid: `70f`, Ask: `70f` +- `tipW` calcolato dinamicamente (vedi DrawTitle) +- Bordo sinistro accent: `4f`; Padding: `6f` sx, `4f` dx +- Label: `PdfTheme.Small` (6.5pt) a `y + 4f` +- Valore Bid/Ask/Data: `PdfTheme.Bold` (8pt bold) a `y + 14f` +- Valore Tipologia: `PdfTheme.Bold` (8pt bold) a `y + 14f` — testo più lungo, dimensione coerente con gli altri box + +- [ ] **Step 1: Aggiungi il metodo `DrawInfoBox` alla classe (prima di `DrawCaratteristiche`)** + + ```csharp + private void DrawInfoBox( + PdfGraphics g, + float x, float y, float w, float boxH, + string label, string value, + PdfBrush bgBrush, PdfBrush accentBrush, + PdfBrush labelBrush, PdfBrush valueBrush, + PdfFont valueFont) + { + g.DrawRectangle(bgBrush, new RectangleF(x, y, w, boxH)); + g.DrawRectangle(accentBrush, new RectangleF(x, y, 4f, boxH)); + float innerX = x + 4f + 6f; + float innerW = w - 4f - 6f - 4f; + g.DrawString(label, PdfTheme.Small, labelBrush, + new RectangleF(innerX, y + 4f, innerW, 10f)); + g.DrawString(value, valueFont, valueBrush, + new RectangleF(innerX, y + 14f, innerW, 14f)); + } + ``` + + > **Nota Syncfusion:** `RectangleF` non supporta named arguments — sempre forma posizionale `new RectangleF(x, y, w, h)`. + +- [ ] **Step 2: Sostituisci il metodo `DrawTitle` (righe 74-112) con la nuova implementazione** + + ```csharp + private float DrawTitle(PdfGraphics g, CertificateInfo info, float w, float y) + { + // ── Titolo centrato ────────────────────────────────────────── + g.DrawString($"Scheda Prodotto {info.Isin}", + PdfTheme.SectionTitleFont, + new PdfSolidBrush(PdfTheme.AccentBlue), + new RectangleF(0, y, w, 20f), + new PdfStringFormat(PdfTextAlignment.Center)); + y += 24f; + + // Linea separatrice blu + g.DrawLine(PdfTheme.AccentBluePen, 0, y, w, y); + y += 8f; + + // ── Riga box: Tipologia | Data | Bid | Ask ─────────────────── + const float boxH = 28f; + const float gap = 6f; + const float dataW = 84f; + const float bidW = 70f; + const float askW = 70f; + + bool showTip = !string.IsNullOrEmpty(info.Categoria); + bool showData = !string.IsNullOrEmpty(info.LastPriceDate); + bool showBidAsk = !string.IsNullOrEmpty(info.Bid) && !string.IsNullOrEmpty(info.Ask); + + // Calcolo dinamico larghezza Tipologia in base ai box presenti + int nBoxes = (showTip ? 1 : 0) + (showData ? 1 : 0) + (showBidAsk ? 2 : 0); + float totalGaps = Math.Max(0, nBoxes - 1) * gap; + float fixedW = (showData ? dataW : 0f) + (showBidAsk ? bidW + askW : 0f); + float tipW = showTip ? (w - totalGaps - fixedW) : 0f; + + float xCursor = 0f; + + if (showTip) + { + DrawInfoBox(g, xCursor, y, tipW, boxH, + "TIPOLOGIA", info.Categoria, + PdfTheme.BoxLightBlueBgBrush, PdfTheme.AccentBlueBrush, + PdfTheme.AccentBlueBrush, PdfTheme.AccentBlueDarkBrush, + PdfTheme.Bold); + xCursor += tipW + gap; + } + + if (showData) + { + DrawInfoBox(g, xCursor, y, dataW, boxH, + "DATA", info.LastPriceDate, + PdfTheme.BoxGrayBgBrush, PdfTheme.BoxGrayAccentBrush, + PdfTheme.BoxGrayLabelBrush, PdfTheme.BoxGrayValueBrush, + PdfTheme.Bold); + xCursor += dataW + gap; + } + + if (showBidAsk) + { + DrawInfoBox(g, xCursor, y, bidW, boxH, + "BID", info.Bid, + PdfTheme.BoxLightBlueBgBrush, PdfTheme.AccentBlueBrush, + PdfTheme.AccentBlueBrush, PdfTheme.AccentBlueDarkBrush, + PdfTheme.Bold); + xCursor += bidW + gap; + + DrawInfoBox(g, xCursor, y, askW, boxH, + "ASK", info.Ask, + PdfTheme.BoxLightBlueBgBrush, PdfTheme.AccentBlueBrush, + PdfTheme.AccentBlueBrush, PdfTheme.AccentBlueDarkBrush, + PdfTheme.Bold); + } + + y += boxH + 10f; + return y; + } + ``` + +- [ ] **Step 3: Build** + + ```bash + dotnet build CertReports.Syncfusion/CertReports.Syncfusion.csproj + ``` + Atteso: `Build succeeded`. + +- [ ] **Step 4: Verifica visiva** + + Avvia il progetto e apri nel browser: + ``` + https://localhost:{porta}/api/report/by-isin/{ISIN_VALIDO} + ``` + Controlla che la pagina 1 mostri: titolo centrato + linea + riga box con altezze uniformi. + Con `?branding=true` verifica che "Powered by Smart Roots" abbia lo spazio corretto tra "by" e il link. + +- [ ] **Step 5: Commit** + + ```bash + git add CertReports.Syncfusion/Services/Implementations/AnagraficaSectionRenderer.cs + git commit -m "feat: redesign page1 header - centered title, info boxes row (Tipologia/Data/Bid/Ask)" + ``` + +--- + +## Task 3: Rinomina colonne tabella Sottostanti + +**Files:** +- Modify: `CertReports.Syncfusion/Services/Implementations/AnagraficaSectionRenderer.cs` (metodo `DrawSottostanti`, riga ~338) + +- [ ] **Step 1: Aggiorna l'array `headers` in `DrawSottostanti`** + + ```csharp + // PRIMA: + string[] headers = { "Nome", "Strike", "Last", "% Perf.", "Barr.K", + "Buffer K", "Trig.CPN", "Buf.CPN", "Trig.AC" }; + + // DOPO: + string[] headers = { "Nome", "Strike", "Last", "% Perf.", "Barriera Capitale", + "Buffer Capitale", "Trigger Cedola", "Buffer Cedola", "Trig.AC" }; + ``` + +- [ ] **Step 2: Build** + + ```bash + dotnet build CertReports.Syncfusion/CertReports.Syncfusion.csproj + ``` + +- [ ] **Step 3: Commit** + + ```bash + git add CertReports.Syncfusion/Services/Implementations/AnagraficaSectionRenderer.cs + git commit -m "fix: rename sottostanti column headers (Barriera/Buffer/Trigger Cedola)" + ``` + +--- + +## Task 4: Rinomina colonna tabella Eventi + +**Files:** +- Modify: `CertReports.Syncfusion/Services/Implementations/EventiSectionRenderer.cs` (riga ~45) + +- [ ] **Step 1: Aggiorna l'array `headers` in `EventiSectionRenderer.Render`** + + ```csharp + // PRIMA: + "Trigger CPN", "Cedola %", "Pagato", "Memoria", + + // DOPO: + "Trigger Cedola", "Cedola %", "Pagato", "Memoria", + ``` + +- [ ] **Step 2: Build** + + ```bash + dotnet build CertReports.Syncfusion/CertReports.Syncfusion.csproj + ``` + +- [ ] **Step 3: Commit** + + ```bash + git add CertReports.Syncfusion/Services/Implementations/EventiSectionRenderer.cs + git commit -m "fix: rename eventi column Trigger CPN -> Trigger Cedola" + ``` + +--- + +## Verifica finale + +- [ ] Avvia il server: `dotnet run --project CertReports.Syncfusion` +- [ ] Apri report con un ISIN valido, verifica pagina 1: + - Titolo "Scheda Prodotto {ISIN}" centrato in blu + - Linea separatrice blu + - Box Tipologia / Data / Bid / Ask sulla stessa riga, stessa altezza (28pt) + - Box Tipologia si estende per occupare lo spazio residuo +- [ ] Verifica tabella Sottostanti: header con "Barriera Capitale", "Buffer Capitale", "Trigger Cedola", "Buffer Cedola" +- [ ] Verifica sezione Eventi: colonna "Trigger Cedola" (era "Trigger CPN") +- [ ] Verifica footer con `?branding=true`: "Powered by Smart Roots" con spazio visibile tra "by" e il link cliccabile