docs: add implementation plan for page1 header restyle
This commit is contained in:
303
docs/superpowers/plans/2026-03-20-page1-header-restyle.md
Normal file
303
docs/superpowers/plans/2026-03-20-page1-header-restyle.md
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user