# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. --- ## ISTRUZIONI OBBLIGATORIE PER CLAUDE ### Auto-Aggiornamento CLAUDE.md **OBBLIGATORIO:** Claude DEVE aggiornare questo file CLAUDE.md ogni volta che: 1. **Viene completato un task significativo** (fix, nuova feature, refactoring importante) 2. **Viene risolto un problema tecnico** che potrebbe ripresentarsi in futuro 3. **Si scopre un pattern/workaround** importante da ricordare 4. **Termina una sessione di lavoro** - aggiornare "Quick Start - Session Recovery" **Cosa aggiornare:** - **Sezione "Quick Start - Session Recovery":** - Aggiornare "Ultima sessione" con data corrente - Spostare lavoro completato da "ultima sessione" a "sessioni precedenti" - Aggiungere nuovi task completati alla lista - Aggiornare "Prossimi task prioritari" (spuntare completati, aggiungere nuovi) - **Sezione "Problemi Risolti (da ricordare)":** - Aggiungere OGNI problema tecnico risolto con: - Descrizione del problema - Causa root - Soluzione implementata - File coinvolti - **Checklist:** - Aggiornare checkbox `[x]` per task completati - Aggiungere nuovi task se scoperti durante il lavoro **Formato per nuovi problemi risolti:** ```markdown XX. **Nome Problema (FIX/IMPLEMENTATO DATA):** - **Problema:** Descrizione breve - **Causa:** Perché succedeva - **Soluzione:** Come è stato risolto - **File:** File modificati ``` **NON dimenticare:** Questo file è la memoria persistente tra sessioni. Se non viene aggiornato, il lavoro fatto andrà perso e dovrà essere riscoperto. --- ## Quick Start - Session Recovery **Ultima sessione:** 28 Novembre 2025 (tarda notte) **Stato progetto:** Migrazione Oracle APEX → .NET + React TypeScript in corso **Lavoro completato nell'ultima sessione:** - **NUOVA FEATURE: Toolbar Report Designer Migliorata Drasticamente** - COMPLETATO - Design moderno stile Canva/Figma con gradient buttons e animazioni fluide - **Sezioni etichettate** su desktop (INSERISCI, MODIFICA, CRONOLOGIA, VISTA, ZOOM, PAGINA) - **Toolbar contestuale** dinamica che appare quando un elemento è selezionato: - Per testo: formattazione (grassetto, corsivo, sottolineato), allineamento, color picker - Per forme/linee: color picker riempimento/bordo, spessore bordo - Per immagini: indicatore mantieni proporzioni - Mostra tipo elemento, nome e dimensioni in tempo reale - **Color Picker integrato** con palette di 20 colori predefiniti - **Indicatore stato salvataggio** visivo: Salvato (verde), Non salvato (arancione), Salvataggio... (spinner) - **Badge** sul pulsante Snap che mostra quante opzioni sono attive - **Zoom esteso** fino al 300% con pulsante "Adatta alla finestra" - Pannello scorciatoie tastiera ampliato - Aggiunto `textDecoration` a `AprtStyle` per supportare sottolineato - **FIX: Indicatore "Non Salvato" errato** - RISOLTO - Prima usava `canUndo` che indicava solo presenza di history - Ora usa `undoCount` confrontato con `lastSavedUndoCount` per tracking accurato - **NUOVA FEATURE: Auto-Save con Toggle** - COMPLETATO - Salvataggio automatico dopo 1 secondo di inattività (debounce) - **Abilitato di default** - Toggle nella toolbar (icona AutoMode) per attivare/disattivare - Quando auto-save è attivo, il pulsante "Salva" manuale è nascosto - Quando auto-save è disattivo, il pulsante "Salva" appare - Non si attiva per template nuovi (richiede primo salvataggio manuale) - Non si attiva durante salvataggio in corso **Lavoro completato nelle sessioni precedenti (28 Novembre 2025 notte):** - **NUOVA FEATURE: Responsive Design Completo** - COMPLETATO - Tutta l'applicazione è ora responsive per mobile, tablet e desktop - Breakpoints: mobile (<600px), tablet (600-900px), desktop (>900px) - **Layout.tsx**: Sidebar collassata con icone su tablet, drawer mobile - **ReportTemplatesPage**: Header stackato su mobile, FAB per nuovo template, dialog fullScreen - **ReportEditorPage**: BottomNavigation + SwipeableDrawer (70vh) per pannelli su mobile, auto-zoom - **EditorToolbar**: 3 varianti (mobile compatta con riga collassabile, tablet media, desktop completa) - **Pannelli laterali** (DataBindingPanel, PropertiesPanel, PageNavigator): larghezza piena su mobile - **DatasetSelector**: Header collassabile su mobile - **PreviewDialog**: fullScreen su mobile con navigazione step-by-step (dataset → entity) - **ImageUploadDialog**: fullScreen su mobile, area drag-drop ottimizzata, bottoni stacked **Lavoro completato nelle sessioni precedenti (28 Novembre 2025 sera):** - **FIX: Variabili Globali Report ({{$pageNumber}}, {{$totalPages}}, ecc.)** - RISOLTO - Le variabili speciali ora vengono correttamente risolte nel PDF finale - Aggiunta classe `PageContext` per passare numero pagina e totale pagine durante il rendering - Propagato `PageContext` attraverso tutta la catena di rendering (bitmap, text, binding resolution) - `ResolveBindingPath()` ora restituisce valori reali invece di placeholder **Lavoro completato nelle sessioni precedenti (28 Novembre 2025):** - **NUOVA FEATURE: Gestione Multi-Pagina nel Report Designer** - Completata - Nuovo tipo `AprtPage` per definire pagine con impostazioni individuali (size, orientation, margins, backgroundColor) - Ogni elemento ha `pageId` per assegnazione a pagina specifica - Nuovo componente `PageNavigator.tsx` - sidebar con lista pagine, context menu, rinomina, duplica, elimina, riordina - Navigazione rapida pagine in `EditorToolbar.tsx` (pulsanti prev/next, indicatore "X / Y") - `PropertiesPanel.tsx` aggiornato per mostrare/modificare impostazioni pagina corrente - Backend `ReportGeneratorService.cs` genera PDF multi-pagina correttamente - Migrazione automatica template legacy (elementi senza pageId assegnati a prima pagina) - **FIX CRITICO: Rotazione oggetti nel PDF** - Gli oggetti ruotati nel canvas ora vengono posizionati correttamente nel PDF generato - Implementata la formula Fabric.js per calcolare il centro di rotazione - Coordinate corrette per `originX='left'`, `originY='top'` **Lavoro completato nelle sessioni precedenti:** - Sistema Report PDF con editor visuale (98% completato) - Fabric.js v6 canvas editor funzionante - Multi-dataset support con preview - **FIX: Data binding PDF ora funzionante** - I campi dati vengono risolti correttamente - **FIX: Formattazione campi** - Date, valute, numeri formattati correttamente nel PDF - Sistema Virtual Dataset implementato (CRUD completo) - SignalR real-time updates funzionante - **Context Menu ricco** - Tasto destro con opzioni complete stile Canva (copia, taglia, incolla, layer, allineamento, trasformazioni) - **FIX: Posizionamento assoluto PDF FUNZIONANTE** - SVG con viewBox in mm, coordinate corrette - **FIX: Immagini nel PDF** - Data URI, API URL e risorse embedded ora renderizzate correttamente - **FIX: Font size nel PDF** - Conversione corretta da px screen a mm per SVG **Per riprendere il lavoro sui Report:** 1. Vai alla sezione "Report PDF System - Implementation Details" più sotto 2. Consulta la "Checklist Completamento Report System" per vedere cosa manca 3. I file principali sono: - Backend: `/src/Apollinare.API/Controllers/ReportsController.cs` - Frontend: `/frontend/src/pages/ReportEditorPage.tsx` - Canvas: `/frontend/src/components/reportEditor/EditorCanvas.tsx` - **Context Menu:** `/frontend/src/components/reportEditor/ContextMenu.tsx` - **PDF Generator:** `/src/Apollinare.API/Services/Reports/ReportGeneratorService.cs` - **Page Navigator:** `/frontend/src/components/reportEditor/PageNavigator.tsx` **Prossimi task prioritari (Report System):** 1. [x] ~~**CRITICO: Posizionamento assoluto PDF**~~ - COMPLETATO 2. [x] ~~Implementare caricamento immagini reali~~ - COMPLETATO 3. [x] ~~**FIX: Rotazione oggetti nel PDF**~~ - COMPLETATO 4. [x] ~~**Gestione Multi-Pagina**~~ - COMPLETATO 5. [ ] Aggiungere rendering tabelle dinamiche per collection 6. [ ] Gestire sezioni header/footer ripetute su ogni pagina 7. [ ] UI per relazioni tra dataset multipli **Comandi utili:** ```bash # Build backend cd src && dotnet build # Build frontend cd frontend && npm run build # Run backend (porta 5000) cd src/Apollinare.API && dotnet run # Run frontend dev (porta 5173) cd frontend && npm run dev ``` --- ## Project Overview This repository contains documentation for migrating the **Apollinare Catering & Banqueting Management Software** from Oracle APEX to .NET + React TypeScript. **Original Application:** - Oracle APEX 21.1.0 (Application ID: 112) - 56 pages, 302 items, 98 processes - Database: Oracle 18 XE (schema: APOLLINARECATERINGPROD) - Language: Italian **Target Stack:** - Backend: .NET (C#) - Frontend: React TypeScript (not Vue - note the user request mentions Vue but the actual target is React TypeScript) - Database: Oracle 18 XE (read-only access for analysis) ## Database Connection (Read-Only) **Connection Details:** - Database: Oracle 18 XE - Username: `apollinarecateringprod` - Password: `bmwmRaSBRT53Z2J8CCvYK45EPDyAJ4` - Database: `xepdb1` - Hostname: `apollinare` - Port: `1521` **Important:** This connection is READ-ONLY. Use it only to analyze schema, extract business logic from procedures/packages/functions, and understand data relationships. ## Application Architecture ### Core Business Domain: Event Catering Management The application manages the complete lifecycle of catering events from quote to execution, including: - Event creation and management - Client and location management - Inventory (articles) with image storage - Quote generation with complex calculations - Resource (staff) scheduling - Kitchen and setup reports - Multi-level authorization system ### Main Business Entities **Events (EVENTI)** - Central entity - Event details (date, location, client, event type) - Guest counts by type (adults, children, seated, buffet) - Status workflow: 0 (Scheda) → 10 (Preventivo/Quote) → 20 (Confermato/Confirmed) - Quote expiration tracking - Distance calculations for location **Event Details (1:N relationships):** - `EVENTI_DET_OSPITI` - Guest type breakdown - `EVENTI_DET_PREL` - Pick lists (articles needed for the event) - `EVENTI_DET_RIS` - Resource assignments (staff) - `EVENTI_DET_DEGUST` - Tasting event details - `EVENTI_ACCONTI` - Deposits/advances - `EVENTI_ALLEG` - Attachments - `EVENTI_ALTRICOSTI` - Other costs **Master Data:** - `ARTICOLI` - Articles/items with images (BLOB), quantities, coefficients - `TB_CODICI_CATEG` - Categories with calculation coefficients (COEFF_A/B/S) - `TB_TIPI_MAT` - Material types - `TB_TIPI_EVENTO` - Event types with meal classifications - `TB_TIPI_OSPITI` - Guest types - `CLIENTI` - Clients - `LOCATION` - Event locations - `RISORSE` - Resources (staff) with type classification ### Critical Business Logic in Database **Key Stored Procedures:** - `EVENTI_AGGIORNA_QTA_LISTA(p_event_id)` - Updates pick list quantities based on guest counts and coefficients - `EVENTI_AGGIORNA_TOT_OSPITI(p_event_id)` - Recalculates total guest count - `EVENTI_RICALCOLA_ACCONTI(p_event_id)` - Recalculates deposit amounts - `EVENTI_COPIA` - Event duplication functionality - `EVENTI_PREPARE` - Event preparation process **Key Functions:** - `F_GET_QTA_IMPEGNATA(cod_articolo, data)` - Returns committed quantity for an article on a specific date (inventory reservation) - `F_EVENTO_SCADUTO(data_scad, stato, ...)` - Checks if event quote has expired - `F_MAX_NUMERO_EVENTI_RAGGIUNTO(data)` - Enforces daily event limit - `F_USER_IN_ROLE(app_user, role)` - Role-based authorization - `STRING_TO_TABLE_ENUM(string, position, delimiter)` - Utility for string parsing **Important Views:** - `V_IMPEGNI_ARTICOLI` - Calculates article commitments across events (inventory availability) - `V_IMPEGNI_ARTICOLI_LOC` - Article commitments by location - `VW_CALENDARIO_EVENTI` - Calendar view of events ### Quantity Calculation Algorithm The application uses a sophisticated coefficient-based system: 1. **Coefficients** are defined at category level (`TB_CODICI_CATEG.COEFF_A/B/S`) 2. **Standard quantities** are stored per article (`ARTICOLI.QTA_STD_A/S/B`) 3. **Guest counts** by type determine multipliers (`EVENTI_DET_OSPITI`) 4. **Final quantities** calculated as: `Guest_Count × Coefficient × Standard_Qty` Types: A (Adulti/Adults), S (Seduti/Seated), B (Buffet) ### Authorization Model **5 Authorization Levels:** 1. **Admin_auth_schema** - Full admin access - Users: admin, monia, andrea, maria, sabrina, nicole, cucina, developer, elia.ballarani 2. **User Read/Write** - Controlled by `USERS_READONLY` table - `FLGWRITE` flag determines write access 3. **Consuntivi** - Access to financial summaries - Users from `GET_CONSUNTIVI_USERS` view 4. **Gestori** (Managers) - Manager-level permissions - Users from `GET_GESTORI_USERS` view 5. **Solo Admins** - Highest level - Only: admin, monia **Session Management:** - `SET_USER_READONLY` process runs before header on every page - Sets `APP_READ_ONLY` application item based on user permissions ### Page Structure (56 Pages) **Master Data Pages:** - Pages 2-3: Articles (list + form) - Pages 4-5: Categories - Pages 6-7: Types - Pages 17-18: Clients - Pages 15, 20: Locations - Page 31: Resources (staff) **Event Management:** - Page 1: Dashboard - Page 8: Event creation wizard - Page 9: Event list - Page 12: Calendar view - Pages 13-14: Event types - **Page 22: Main event form** (most complex - multiple interactive grids) - Page 27, 32: Tastings - Page 35: Event cards/confirmed cards - Page 48: Event templates **Reports:** - Page 16: Grid view - Page 25: Kitchen summary - Page 28: Cakes and extra costs - Page 30: Setup summary - Page 38: Resources summary - Page 39: Article commitments **Admin:** - Page 45: Data management - Page 46: Max events configuration - Page 47: Permissions - Page 49: Scheduled jobs - Page 50: Sent emails - Page 51: Pending emails ### External Integrations **JasperReports:** - Quote reports (preventivi) - Event cards (schede evento) - Kitchen summaries - Custom iframeObj.js wrapper for embedding reports **Email System:** - Mail queue (pages 50-51) - Background job processing (page 49) - Template-based notifications **Custom JavaScript:** - `ajaxUtils.js` - AJAX utilities for dynamic updates - `notifica(pText, pType)` - Dynamic notifications - `setSessionState(elemList, pCallback)` - Session state management - `ajaxExec(...)` - Generic AJAX execution - `execProcessAsync(...)` - Async process execution - `execQueryAsync(...)` - Async query execution ### Migration Considerations **Complex Features Requiring Special Attention:** 1. **Page 22 (Nuovo Evento)** - Most complex page - Multiple editable interactive grids on single page - Master-detail relationships with real-time calculations - Guest type grid → triggers quantity recalculations in pick list grids - Resource assignment grid - Requires careful state management in React 2. **BLOB Storage for Images** - Article images stored as BLOBs in Oracle - Migration strategy needed (Azure Blob Storage, AWS S3, or filesystem) - MIMETYPE tracking for proper rendering 3. **PL/SQL Business Logic** - Decision needed: Port to C# or keep as Oracle functions? - Quantity calculations are complex - ensure parity - Inventory commitment logic (V_IMPEGNI_ARTICOLI) is critical 4. **State Management** - Heavy use of APEX session state - Consider Redux Toolkit or Zustand for React - Real-time grid updates and calculations 5. **Reporting** - JasperReports replacement needed - Options: SSRS, Crystal Reports, DevExpress, or PDF libraries (iTextSharp, QuestPDF) 6. **Email Queue System** - Asynchronous processing required - Consider: Hangfire, Azure Functions, or background services 7. **Calendar Component** - Page 12 uses APEX calendar - React options: FullCalendar, React Big Calendar, @event-calendar/core 8. **Multi-Grid Interactions** - Interactive grids with master-detail relationships - Consider: AG Grid, DevExtreme DataGrid, or Material-UI DataGrid ## Business Rules to Preserve 1. **Event Status Workflow:** Must follow 0 → 10 → 20 progression 2. **Quote Expiration:** Automatic status change when `DATA_SCAD_PREVENTIVO` passed 3. **Max Events Per Day:** Enforced limit (configurable) 4. **Article Commitment Tracking:** Prevent overbooking of inventory 5. **Coefficient-Based Calculations:** Ensure quantity formulas match exactly 6. **Deposit Calculations:** Auto-recalculation on cost changes 7. **Role-Based Access:** 5-level authorization system 8. **Read-Only Mode:** User-specific write restrictions ## Data Extraction Queries When analyzing the database, useful queries: ```sql -- Get all tables in schema SELECT table_name FROM user_tables ORDER BY table_name; -- Get table structure SELECT column_name, data_type, nullable, data_default FROM user_tab_columns WHERE table_name = 'EVENTI' ORDER BY column_id; -- Get all procedures and functions SELECT object_name, object_type FROM user_objects WHERE object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE') ORDER BY object_type, object_name; -- Get procedure source SELECT text FROM user_source WHERE name = 'EVENTI_AGGIORNA_QTA_LISTA' ORDER BY line; -- Get view definitions SELECT view_name, text FROM user_views WHERE view_name LIKE 'V_%' OR view_name LIKE 'VW_%'; -- Get foreign key relationships SELECT a.constraint_name, a.table_name, a.column_name, c_pk.table_name r_table_name, c_pk.constraint_name r_constraint_name FROM user_cons_columns a JOIN user_constraints c ON a.constraint_name = c.constraint_name JOIN user_constraints c_pk ON c.r_constraint_name = c_pk.constraint_name WHERE c.constraint_type = 'R' ORDER BY a.table_name, a.constraint_name; ``` ## File References - `apollinare-db-connection.md` - Database connection details (credentials) - `f112.sql` - Complete APEX export (53,282 lines) - Application structure - Page definitions - Processes and validations - LOVs and static data - JavaScript libraries ## Development Approach When working on migration tasks: 1. **Always query the database** to understand current data structure and relationships 2. **Extract PL/SQL source code** for procedures/functions before implementing equivalent C# logic 3. **Document business rules** discovered in stored procedures 4. **Preserve Italian field names** in database but consider English in application layer 5. **Test quantity calculations** thoroughly - they are core to the business 6. **Map APEX page flows** to React routes and components 7. **Identify reusable components** (grids, forms, lookups) 8. **Plan data migration** for BLOBs and complex relationships ## Key Terminology (Italian → English) - **Scheda** → Card/Draft (Event status 0) - **Preventivo** → Quote (Event status 10) - **Confermato** → Confirmed (Event status 20) - **Lista Prelievo** → Pick List (articles for event) - **Articoli** → Articles/Items - **Ospiti** → Guests - **Risorse** → Resources (staff) - **Degustazioni** → Tastings - **Allestimenti** → Setups - **Acconti** → Deposits/Advances - **Impegni** → Commitments (inventory reservations) ## Notes - The application is mature and in production use - Italian language throughout (UI, database, code comments) - Complex business logic embedded in database layer - Heavy use of APEX-specific features (Interactive Grids, Dynamic Actions) - Real-time calculations and validations are critical to user experience --- ## Report PDF System - Implementation Details ### Overview Sistema completo di generazione report PDF con editor visuale drag-and-drop (stile Canva) e metalinguaggio APRT (Apollinare Report Template) per template portabili. ### Stack Tecnologico **Backend:** - QuestPDF (Community License) - Generazione PDF programmatica - .NET 9 Web API con Entity Framework Core - SQLite per storage template, font e immagini **Frontend:** - React 19 + TypeScript + Vite - Fabric.js v6 - Canvas editor per design visuale - Material-UI per componenti UI ### Stato Corrente dell'Implementazione #### Backend (COMPLETATO) **Entities** (`/src/Apollinare.Domain/Entities/`): - `ReportTemplate.cs` - Template con JSON, thumbnail, metadata - `ReportFont.cs` - Font custom uploadabili (TTF/OTF) - `ReportImage.cs` - Immagini riutilizzabili nei report **Services** (`/src/Apollinare.API/Services/Reports/`): - `ReportGeneratorService.cs` - Parsing APRT e generazione PDF con QuestPDF - `AprtModels.cs` - Modelli C# per il metalinguaggio APRT **Controllers** (`/src/Apollinare.API/Controllers/`): - `ReportTemplatesController.cs` - CRUD template, clone, import/export - `ReportResourcesController.cs` - Gestione font e immagini - `ReportsController.cs` - Generazione PDF, schema dati, dataset management **API Endpoints disponibili:** ``` # Templates GET /api/report-templates GET /api/report-templates/{id} POST /api/report-templates PUT /api/report-templates/{id} DELETE /api/report-templates/{id} POST /api/report-templates/{id}/clone GET /api/report-templates/{id}/export POST /api/report-templates/import GET /api/report-templates/categories # Resources GET /api/report-resources/fonts POST /api/report-resources/fonts DELETE /api/report-resources/fonts/{id} GET /api/report-resources/fonts/families GET /api/report-resources/images POST /api/report-resources/images DELETE /api/report-resources/images/{id} # Report Generation POST /api/reports/generate GET /api/reports/evento/{eventoId} POST /api/reports/preview GET /api/reports/datasets GET /api/reports/schema/{datasetId} GET /api/reports/datasets/{datasetId}/entities ``` #### Frontend (COMPLETATO ~90%) **Pagine** (`/frontend/src/pages/`): - `ReportTemplatesPage.tsx` - Lista template con cards, filtri, import/export - `ReportEditorPage.tsx` - Editor principale con undo/redo, shortcuts **Componenti Editor** (`/frontend/src/components/reportEditor/`): - `EditorCanvas.tsx` - Canvas Fabric.js per design visuale - `EditorToolbar.tsx` - Toolbar con strumenti, zoom, grid, azioni - `PropertiesPanel.tsx` - Pannello proprietà elemento/pagina - `DataBindingPanel.tsx` - Browser campi dati con supporto multi-dataset - `DatasetSelector.tsx` - Selezione dataset per template - `PreviewDialog.tsx` - Dialog selezione entità per anteprima **Types** (`/frontend/src/types/report.ts`): - Definizioni complete APRT (AprtTemplate, AprtElement, AprtStyle, etc.) - DTOs per API (ReportTemplateDto, DataSchemaDto, DatasetTypeDto, etc.) - Utility functions (mmToPx, pxToMm, getPageDimensions) **Services** (`/frontend/src/services/reportService.ts`): - reportTemplateService - CRUD template - reportFontService - Gestione font - reportImageService - Gestione immagini - reportGeneratorService - Generazione PDF e schema ### Metalinguaggio APRT (Apollinare Report Template) Formato JSON esportabile/importabile per portabilità template: ```json { "version": "1.0", "meta": { "name": "Template Evento", "pageSize": "A4", "orientation": "portrait", "margins": { "top": 20, "right": 15, "bottom": 20, "left": 15 } }, "resources": { "fonts": [], "images": [] }, "dataSources": { "evento": { "type": "object", "schema": "evento" } }, "sections": [], "elements": [ { "id": "uuid", "type": "text", "position": { "x": 20, "y": 20, "width": 100, "height": 20 }, "style": { "fontFamily": "Helvetica", "fontSize": 14, "color": "#000000" }, "content": { "type": "binding", "expression": "{{evento.codice}}" }, "section": "body" } ] } ``` **Tipi elemento supportati:** text, image, shape, table, line, barcode **Data binding:** `{{campo}}`, `{{dataset.campo}}`, `{{collection.campo}}` **Variabili speciali:** `{{$pageNumber}}`, `{{$totalPages}}`, `{{$date}}`, `{{$datetime}}` ### Dataset Disponibili | Dataset ID | Nome | Descrizione | | ---------- | -------- | ------------------------------------------------------------------ | | evento | Evento | Dati evento con cliente, location, dettagli ospiti, costi, risorse | | cliente | Cliente | Anagrafica clienti completa | | location | Location | Sedi e location eventi | | articolo | Articolo | Catalogo articoli e materiali | | risorsa | Risorsa | Staff e personale | ### Funzionalità Implementate - [x] Editor visuale drag-and-drop con Fabric.js - [x] Supporto elementi: testo, forme, linee, tabelle, immagini (placeholder) - [x] Gestione zoom (25% - 300%) - [x] Griglia e snap to grid - [x] Undo/Redo (max 100 stati) - [x] Shortcuts tastiera (Ctrl+Z, Ctrl+Y, Ctrl+S, Delete) - [x] Pannello proprietà con posizione, stile, contenuto - [x] Data binding con browser campi disponibili - [x] Selezione multipla dataset per template - [x] Preview con selezione entità reali - [x] Salvataggio/caricamento template - [x] Import/export template come file .aprt - [x] Clone template - [x] Generazione PDF default per eventi - [x] Formattazione campi (valuta, data, numero, percentuale) - [x] **Responsive design completo** (mobile, tablet, desktop) - [x] **Toolbar professionale** stile Canva/Figma con sezioni etichettate - [x] **Toolbar contestuale** per formattazione rapida (testo, forme, immagini) - [x] **Color picker integrato** con palette preset - [x] **Auto-save** con toggle (abilitato di default, 1s debounce) - [x] **Indicatore stato salvataggio** accurato (Salvato/Non salvato/Salvataggio...) ### Cosa Manca per Completare #### Alta Priorità - [ ] **Caricamento immagini reali** - Attualmente placeholder, implementare upload e rendering - [ ] **Tabelle dinamiche** - Rendering collection dati (es. lista ospiti, articoli) - [ ] **Sezioni header/footer** - Ripetizione su ogni pagina - [ ] **Font custom** - Upload e utilizzo font TTF/OTF nei PDF #### Media Priorità - [ ] **Relazioni tra dataset** - UI per collegare campi tra dataset diversi - [ ] **Barcode/QRCode** - Supporto codici a barre - [ ] **Formule calcolate** - Espressioni matematiche nei campi - [ ] **Stili condizionali** - Formattazione basata su valore dati - [ ] **Raggruppamento elementi** - Group/ungroup nel canvas #### Bassa Priorità - [ ] **Template predefiniti** - Library di template pronti all'uso - [ ] **Anteprima live** - Preview in tempo reale durante editing - [x] ~~**Multi-pagina** - Editor pagine multiple~~ - COMPLETATO - [ ] **Righelli e guide** - Ausili allineamento avanzati - [ ] **Esportazione altri formati** - Excel, Word oltre PDF --- ## Checklist Completamento Report System ### Backend - [x] Entity ReportTemplate - [x] Entity ReportFont - [x] Entity ReportImage - [x] ReportTemplatesController (CRUD + clone + import/export) - [x] ReportResourcesController (fonts + images) - [x] ReportsController (generate + preview + schema + datasets) - [x] ReportGeneratorService con QuestPDF - [x] Schema dati per tutti i dataset (evento, cliente, location, articolo, risorsa) - [x] Generazione PDF default evento - [x] Generazione PDF multi-pagina - [ ] Rendering tabelle dinamiche da collection - [ ] Supporto font custom nel PDF - [ ] Rendering immagini da storage ### Frontend - [x] ReportTemplatesPage (lista + filtri + azioni) - [x] ReportEditorPage (editor principale) - [x] EditorCanvas con Fabric.js v6 - [x] EditorToolbar completa - [x] PropertiesPanel (posizione + stile + contenuto) - [x] DataBindingPanel multi-dataset - [x] DatasetSelector - [x] PreviewDialog con selezione entità - [x] Types APRT completi - [x] Services API completi - [x] Undo/Redo - [x] Keyboard shortcuts - [x] PageNavigator (gestione multi-pagina) - [x] Navigazione pagine in toolbar - [x] **Responsive design** (mobile/tablet/desktop) - [ ] Upload e gestione immagini nell'editor - [ ] Editor tabelle avanzato (colonne, binding dati) - [ ] UI relazioni tra dataset - [ ] Gestione sezioni header/footer ### Testing - [x] Build frontend senza errori - [x] Build backend senza errori - [ ] Test funzionale editor canvas - [x] Test generazione PDF con dati reali (binding e formattazione funzionanti) - [ ] Test import/export template - [ ] Test con font e immagini custom ### Documentazione - [x] Documentazione APRT metalanguage - [x] Lista API endpoints - [x] Checklist implementazione - [ ] Guida utente editor - [ ] Esempi template comuni --- ## Note Tecniche per Future Sessioni ### Struttura File Report System ``` src/ ├── Apollinare.Domain/Entities/ │ ├── ReportTemplate.cs # Entity template con TemplateJson │ ├── ReportFont.cs # Font custom uploadati │ └── ReportImage.cs # Immagini riutilizzabili │ ├── Apollinare.API/ │ ├── Controllers/ │ │ ├── ReportTemplatesController.cs # CRUD template │ │ ├── ReportResourcesController.cs # Font e immagini │ │ └── ReportsController.cs # Generazione PDF + schema │ │ │ └── Services/Reports/ │ ├── ReportGeneratorService.cs # QuestPDF generator │ └── AprtModels.cs # Modelli C# per APRT JSON frontend/src/ ├── pages/ │ ├── ReportTemplatesPage.tsx # Lista template │ └── ReportEditorPage.tsx # Editor principale │ ├── components/reportEditor/ │ ├── EditorCanvas.tsx # Fabric.js canvas │ ├── EditorToolbar.tsx # Toolbar strumenti │ ├── PropertiesPanel.tsx # Proprietà elemento │ ├── DataBindingPanel.tsx # Browser campi dati │ ├── DatasetSelector.tsx # Selezione dataset │ ├── PreviewDialog.tsx # Dialog anteprima │ └── ContextMenu.tsx # Menu tasto destro (NEW) │ ├── types/ │ └── report.ts # Types APRT + DTOs │ └── services/ └── reportService.ts # API calls ``` ### Problemi Risolti (da ricordare) 1. **Fabric.js v6 breaking changes:** - `sendToBack()` → `canvas.sendObjectToBack(obj)` - Event handlers hanno signature diversa - Proprietà `data` non è nel tipo base, serve cast a `FabricObjectWithData` 2. **TypeScript strict mode:** - Usare `as any` per event handlers Fabric.js - Interface `FabricObjectWithData` per oggetti con metadata custom 3. **QuestPDF TimeSpan:** - `evento.OraInizio` è `TimeSpan?` non `string` - Formattare con `{evento.OraInizio:hh\\:mm}` 4. **Data Binding PDF (FIX 27/11/2025):** - **Problema:** I binding `{{dataEvento}}` non venivano risolti - PDF mostrava campi vuoti - **Causa:** Il frontend creava binding senza prefisso dataset quando c'era un solo dataset - **Soluzione Frontend** (`DataBindingPanel.tsx`): Sempre includere il prefisso dataset ```typescript // Prima: {{dataEvento}} - non funzionava // Dopo: {{evento.dataEvento}} - corretto const createBinding = (datasetId: string, fieldName: string) => { return `{{${datasetId}.${fieldName}}}`; }; ``` - **Soluzione Backend** (`ReportGeneratorService.cs`): Aggiunto fallback per compatibilità con template esistenti ```csharp // Se binding senza prefisso, cerca in tutti i dataset if (current == null && parts.Length == 1) { foreach (var kvp in dataContext) { var foundValue = GetPropertyValue(kvp.Value, path); if (foundValue != null) { current = foundValue; break; } } } ``` - **Formattazione:** Aggiunto `ResolveBindingWithFormat()` per applicare format (date, currency, etc.) 5. **SignalR Connection (FIX 27/11/2025):** - Aggiunto `app.UseWebSockets()` in Program.cs prima di `app.UseRouting()` - Configurato signalr.ts con `withAutomaticReconnect()` 6. **MUI Fragment in Menu (FIX 27/11/2025):** - Menu component non accetta Fragment come child - Sostituire `<>...` con array `[, ]` 7. **HTML p/div nesting (FIX 27/11/2025):** - Error: `
cannot be a descendant of

` - Fix: `` 8. **Context Menu Browser Default (FIX 27/11/2025 notte):** - **Problema:** Il menu contestuale del browser appariva invece di quello custom - **Soluzione:** Usare `onContextMenu` su Box container React invece di eventi Fabric.js - **File:** `EditorCanvas.tsx` - Aggiunto handler sul Box wrapper 9. **Fabric.js v6 Layer Ordering (FIX 27/11/2025 notte):** - **Problema:** `canvas.moveTo()` non esiste in Fabric.js v6 - **Soluzione:** Usare `canvas.remove(obj)` + `canvas.insertAt(targetIndex, obj)` - **File:** `EditorCanvas.tsx` - Aggiunto z-index sync in useEffect 10. **QuestPDF Posizionamento Assoluto (RISOLTO 27/11/2025):** - **Problema:** QuestPDF non ha API `.Position()` per posizionamento assoluto - **Soluzione:** Usare SVG con `viewBox` in mm per avere coordinate 1:1 con il designer - **File:** `ReportGeneratorService.cs` - Metodi `GenerateSvgContent()`, `RenderElementToSvg()` - **Chiave della soluzione:** ```csharp // SVG viewBox in mm - 1 unità SVG = 1mm svgBuilder.AppendLine($""); ``` - Le coordinate dal template sono già in mm relative all'area contenuto (dentro i margini) - Non serve più conversione mm→px: usiamo mm direttamente nel viewBox 11. **Immagini nel PDF (RISOLTO 27/11/2025):** - **Problema:** Le immagini embedded come data URI in `imageSettings.src` non venivano renderizzate - **Soluzione:** `RenderImageToSvg()` ora gestisce 3 fonti: 1. Data URI (`data:image/...;base64,...`) - usato direttamente 2. API URL (`/api/report-resources/images/{id}`) - caricato da DB e convertito in data URI 3. URL esterni (`http://...`) - passato direttamente - **File:** `ReportGeneratorService.cs` - Metodo `RenderImageToSvg()`, `GuessMimeType()` 12. **Font Size nel PDF (RISOLTO 27/11/2025):** - **Problema:** Il font size appariva troppo grande/piccolo nel PDF - **Causa:** La formula `fontSize * mmToPx / 3` era un'approssimazione incorretta - **Soluzione:** Conversione corretta da px screen (96 DPI) a mm: ```csharp // 1px @ 96 DPI = 0.2646mm var fontSizeMm = (style?.FontSize ?? 12) * 0.2646f; ``` - **File:** `ReportGeneratorService.cs` - Metodo `RenderElementToSvg()` case "text" 13. **Rotazione Oggetti nel PDF (RISOLTO 28/11/2025):** - **Problema:** Gli oggetti ruotati nel canvas Fabric.js venivano posizionati in modo completamente errato nel PDF - **Causa:** In Fabric.js con `originX='left'` e `originY='top'`, quando un oggetto viene ruotato: - L'oggetto ruota attorno al suo centro geometrico - Le coordinate `left`/`top` salvate rappresentano la posizione dell'origin point **dopo** la rotazione - Il backend calcolava il centro di rotazione in modo errato usando `(x + width/2, y + height/2)` - **Soluzione:** Implementata la formula corretta di Fabric.js per calcolare il centro: ```csharp // Calcolo del centro usando la formula Fabric.js (originX='left', originY='top') var angleRad = rotation * Math.PI / 180f; var halfWidth = width / 2; var halfHeight = height / 2; var cos = (float)Math.Cos(angleRad); var sin = (float)Math.Sin(angleRad); // Centro dell'oggetto in coordinate canvas var centerX = left + halfWidth * cos - halfHeight * sin; var centerY = top + halfWidth * sin + halfHeight * cos; // Posizione di disegno (angolo sup-sinistro del rettangolo non ruotato centrato sul centro) var drawX = centerX - halfWidth; var drawY = centerY - halfHeight; // Ruota attorno al centro calcolato canvas.RotateDegrees(rotation, centerX, centerY); // Disegna a (drawX, drawY) ``` - **File:** `ReportGeneratorService.cs` - Metodi `RenderElementToCanvas()` e `GenerateSvgContent()` + `RenderElementToSvg()` - **Nota:** La stessa logica è applicata sia al rendering bitmap (SkiaSharp) che SVG 14. **Gestione Multi-Pagina (IMPLEMENTATO 28/11/2025):** - **Struttura dati:** - `AprtPage`: `{ id, name, pageSize?, orientation?, margins?, backgroundColor? }` - `AprtElement.pageId`: ID della pagina a cui appartiene l'elemento - `AprtTemplate.pages`: Array di pagine del template - **Frontend:** - `PageNavigator.tsx`: Sidebar con lista pagine, context menu (rinomina, duplica, elimina, sposta) - `EditorToolbar.tsx`: Pulsanti prev/next pagina, indicatore "Pagina X di Y" - `ReportEditorPage.tsx`: State `currentPageId`, filtro elementi per pagina, handlers CRUD pagine - `PropertiesPanel.tsx`: Modifica nome pagina e impostazioni (format, orientation, margins, background) - **Backend (`ReportGeneratorService.cs`):** ```csharp // Pre-render di ogni pagina separatamente foreach (var pageDefinition in aprt.Pages) { var pageElements = aprt.Elements .Where(e => e.Visible && (e.PageId == pageDefinition.Id || (string.IsNullOrEmpty(e.PageId) && pageDefinition.Id == aprt.Pages[0].Id))) .ToList(); var pageImageBytes = RenderContentToBitmap(pageElements, pageWidth, pageHeight, ...); pageRenderData.Add((pageWidth, pageHeight, bgColor, pageImageBytes)); } // Genera PDF con pagine separate Document.Create(container => { foreach (var (pageWidth, pageHeight, bgColor, imageBytes) in pageRenderData) container.Page(page => { page.Size(...); page.Content().Image(imageBytes); }); }); ``` - **Migrazione template legacy:** `MigrateTemplatePages()` crea pagina default e assegna elementi orfani 15. **Variabili Globali Report (FIX 28/11/2025 sera):** - **Problema:** Le variabili speciali `{{$pageNumber}}`, `{{$totalPages}}`, `{{$date}}`, `{{$datetime}}`, `{{$time}}` non venivano stampate nel PDF - restavano come placeholder - **Causa:** `ResolveBindingPath()` restituiva placeholder statici (`"{{PAGE}}"`) invece dei valori reali perché il contesto pagina non veniva passato durante il rendering - **Soluzione:** 1. Aggiunta classe `PageContext` con `PageNumber` e `TotalPages` 2. Il ciclo di rendering ora traccia l'indice pagina corrente 3. `PageContext` propagato attraverso tutta la catena: `GeneratePdfAsync` → `RenderContentToBitmap` → `RenderElementToCanvas` → `RenderTextToCanvas` → `ResolveContent` → `ResolveBindingWithFormat` → `ResolveBindingPath` 4. `ResolveBindingPath()` ora usa i valori reali dal contesto: ```csharp "$pageNumber" => pageContext?.PageNumber.ToString() ?? "1", "$totalPages" => pageContext?.TotalPages.ToString() ?? "1", "$date" => DateTime.Now.ToString("dd/MM/yyyy"), "$time" => DateTime.Now.ToString("HH:mm"), "$datetime" => DateTime.Now.ToString("dd/MM/yyyy HH:mm"), ``` - **File:** `ReportGeneratorService.cs` - Metodi `GeneratePdfAsync()`, `RenderContentToBitmap()`, `RenderElementToCanvas()`, `RenderTextToCanvas()`, `ResolveContent()`, `ResolveBindingWithFormat()`, `ResolveBinding()`, `ResolveExpression()`, `ResolveBindingPath()` 16. **Responsive Design Completo (IMPLEMENTATO 28/11/2025 notte):** - **Obiettivo:** Rendere tutta l'applicazione responsive per mobile, tablet e desktop - **Breakpoints MUI utilizzati:** - Mobile: `theme.breakpoints.down("sm")` → < 600px - Tablet: `theme.breakpoints.between("sm", "md")` → 600-900px - Desktop: `theme.breakpoints.up("md")` → > 900px - **Pattern principale per Report Editor su mobile:** - `BottomNavigation` per switch tra pannelli (Pagine, Dati, Proprietà) - `SwipeableDrawer` con `anchor="bottom"` e altezza 70vh per contenuto pannelli - Auto-zoom canvas: 0.5 mobile, 0.75 tablet, 1 desktop - **Pattern per toolbar mobile:** - Riga primaria con azioni essenziali sempre visibili - Riga secondaria collassabile con `` per azioni secondarie - **Pattern per dialog mobile:** - `fullScreen` prop su Dialog - AppBar con pulsante back invece di DialogTitle - Navigazione step-by-step invece di layout side-by-side - **File modificati:** - `Layout.tsx` - Sidebar collassata su tablet - `ReportTemplatesPage.tsx` - FAB, fullScreen dialogs - `ReportEditorPage.tsx` - BottomNavigation + SwipeableDrawer - `EditorToolbar.tsx` - 3 varianti layout (mobile/tablet/desktop) - `DataBindingPanel.tsx`, `PropertiesPanel.tsx`, `PageNavigator.tsx` - Width responsive - `DatasetSelector.tsx` - Header collapsible - `PreviewDialog.tsx`, `ImageUploadDialog.tsx` - fullScreen + step navigation 17. **Indicatore "Non Salvato" Errato (FIX 28/11/2025 tarda notte):** - **Problema:** Dopo il salvataggio, l'indicatore continuava a mostrare "Non salvato" - **Causa:** `hasUnsavedChanges` era basato su `templateHistory.canUndo` che indica solo se c'è history disponibile, non se ci sono modifiche non salvate - **Soluzione:** Introdotto `lastSavedUndoCount` che viene aggiornato dopo ogni salvataggio riuscito. `hasUnsavedChanges` ora confronta `templateHistory.undoCount !== lastSavedUndoCount` - **File:** `ReportEditorPage.tsx` 18. **Auto-Save Feature (IMPLEMENTATO 28/11/2025 tarda notte):** - **Funzionalità:** Salvataggio automatico dopo 1 secondo di inattività - **Implementazione:** - Stato `autoSaveEnabled` (default: true) in `ReportEditorPage.tsx` - `useEffect` con debounce di 1000ms che triggera `saveMutation.mutate()` - Non si attiva se: `isNew`, `!hasUnsavedChanges`, `saveMutation.isPending` - Toggle nella toolbar con icona `AutoSaveIcon` (da @mui/icons-material) - Pulsante "Salva" nascosto quando auto-save è attivo - **Props toolbar:** `autoSaveEnabled`, `onAutoSaveToggle` - **File:** `ReportEditorPage.tsx`, `EditorToolbar.tsx` 19. **Toolbar Migliorata Stile Canva/Figma (IMPLEMENTATO 28/11/2025 tarda notte):** - **Miglioramenti:** - Design moderno con gradient buttons e animazioni fluide - Sezioni etichettate su desktop (INSERISCI, MODIFICA, CRONOLOGIA, VISTA, ZOOM, PAGINA) - Toolbar contestuale dinamica basata su tipo elemento selezionato - Color picker integrato con 20 colori preset - Indicatore stato salvataggio visivo - Badge su pulsante Snap - Zoom esteso fino a 300% - **Componenti aggiunti:** `ToolbarSection`, `StyledIconButton`, `ColorPickerButton` - **Type aggiunto:** `textDecoration` in `AprtStyle` - **File:** `EditorToolbar.tsx`, `types/report.ts` ### Schema Database Report System Le tabelle sono già nel DbContext (`AppollinareDbContext.cs`): - `ReportTemplates` - Template salvati - `ReportFonts` - Font custom - `ReportImages` - Immagini riutilizzabili Migration già applicata per SQLite. ### Dipendenze Chiave **Backend (NuGet):** - `QuestPDF` - Generazione PDF (Community License, gratis per revenue < $1M) **Frontend (npm):** - `fabric` v6.x - Canvas editor - `uuid` - Generazione ID elementi - `@tanstack/react-query` - Data fetching ### Routes Frontend ```typescript // App.tsx } /> } /> } /> ``` Menu aggiunto in `Layout.tsx` sotto "Report" con icona PrintIcon.