# Phase 2: Fundație Pattern-uri Globale 🏗️ **Priority:** Foundation pentru future phases **Duration:** 8-10 hours **Status:** ⏸️ Not Started **Risk Level:** Low (additive changes only) --- ## Obiective 1. **Creare fișiere pattern globale** - 5 fișiere CSS noi 2. **Extract pattern-uri repetate** - Loading spinners, trends, breakdowns 3. **Design tokens extinse** - Card-specific, animations, interactivity 4. **PrimeVue overrides centralizate** - Pregătire pentru Phase 3 5. **Zero modificări vizuale** - Setup fără impact --- ## Task Breakdown (15 tasks) ### 1. File Creation (5 tasks) #### Task 1.1: Create interactive.css **Status:** ⏸️ | **Est:** 90 min **File:** `reports-app/frontend/src/assets/css/patterns/interactive.css` ```css /* Interactive Patterns - ROA2WEB */ /* ===== Loading Spinners ===== */ .loading-spinner { width: var(--spinner-size, 40px); height: var(--spinner-size, 40px); border: 4px solid var(--color-border); border-top-color: var(--color-primary); border-radius: var(--radius-full); animation: spin 1s linear infinite; } .loading-spinner-sm { --spinner-size: 24px; border-width: 3px; } .loading-spinner-lg { --spinner-size: 56px; border-width: 5px; } @keyframes spin { to { transform: rotate(360deg); } } /* ===== Trend Indicators ===== */ .trend { display: inline-flex; align-items: center; gap: var(--space-xs); font-size: var(--text-sm); font-weight: var(--font-medium); } .trend-up { color: var(--color-success); } .trend-down { color: var(--color-error); } .trend-neutral { color: var(--color-text-secondary); } .trend-icon { font-size: 0.75rem; } /* ===== Collapse/Expand Patterns ===== */ .collapsible-header { display: flex; justify-content: space-between; align-items: center; cursor: pointer; user-select: none; padding: var(--space-sm); border-radius: var(--radius-sm); transition: background-color var(--transition-fast); } .collapsible-header:hover { background: var(--color-bg-secondary); } .collapse-icon { font-size: 0.625rem; color: var(--color-text-secondary); transition: transform var(--transition-fast); display: inline-block; width: 1rem; } .collapse-icon.expanded { transform: rotate(90deg); } /* ===== Card Hover Effects ===== */ .card-hover { transition: all var(--transition-fast); } .card-hover:hover { box-shadow: var(--shadow-md); transform: translateY(var(--hover-lift, -2px)); border-color: var(--color-primary); } /* ===== Sparkline Containers ===== */ .sparkline-container { width: 100%; background: var(--color-bg-secondary); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: var(--space-sm); } .sparkline-chart { width: 100%; height: var(--sparkline-height, 80px); position: relative; } .sparkline-chart-lg { --sparkline-height: 150px; } .sparkline-canvas { width: 100% !important; height: 100% !important; display: block; } ``` **Acceptance Criteria:** - [ ] File created in correct location - [ ] All patterns documented with comments - [ ] CSS variables used throughout - [ ] No hardcoded values --- #### Task 1.2: Create dashboard.css **Status:** ⏸️ | **Est:** 2 hours **File:** `reports-app/frontend/src/assets/css/patterns/dashboard.css` ```css /* Dashboard Patterns - ROA2WEB */ /* ===== Page Headers ===== */ .page-header { margin-bottom: var(--space-xl); text-align: center; } .page-title { margin: 0 0 var(--space-sm) 0; font-size: var(--text-3xl); font-weight: var(--font-bold); color: var(--color-text); display: flex; align-items: center; justify-content: center; gap: var(--space-md); } .page-subtitle { margin: 0; font-size: var(--text-base); color: var(--color-text-secondary); } /* ===== Section Structure ===== */ .section-header { display: flex; justify-content: space-between; align-items: center; padding: var(--space-lg); background: var(--color-bg-secondary); border-bottom: 1px solid var(--color-border); flex-wrap: wrap; gap: var(--space-md); } .section-title { font-size: var(--text-xl); font-weight: var(--font-semibold); color: var(--color-text); margin: 0; } .section-controls { display: flex; align-items: center; gap: var(--space-md); flex-wrap: wrap; } /* ===== Metrics Grid ===== */ .metrics-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-lg); margin-bottom: var(--space-xl); } @media (max-width: 1024px) { .metrics-row { grid-template-columns: 1fr; } } /* ===== Breakdown Patterns ===== */ .breakdown-section { padding-top: var(--space-lg); border-top: 1px solid var(--color-border); margin-top: var(--space-lg); } .breakdown-item { display: flex; justify-content: space-between; align-items: center; padding: var(--space-sm) 0; } .breakdown-label { font-size: var(--text-sm); color: var(--color-text-secondary); font-weight: var(--font-medium); } .breakdown-value { font-size: var(--text-base); color: var(--color-text); font-weight: var(--font-semibold); font-family: var(--font-mono, monospace); } .breakdown-subitems { padding-left: var(--space-lg); margin-top: var(--space-sm); } .breakdown-subitem { display: flex; justify-content: space-between; padding: var(--space-xs) 0; } .breakdown-sublabel { color: var(--color-text-secondary); font-size: var(--text-sm); } .breakdown-subvalue { font-weight: var(--font-medium); font-family: var(--font-mono, monospace); font-size: var(--text-sm); } ``` **Acceptance Criteria:** - [ ] All dashboard patterns defined - [ ] Responsive grid included - [ ] Breakdown patterns complete --- #### Task 1.3: Create animations.css **Status:** ⏸️ | **Est:** 30 min **File:** `reports-app/frontend/src/assets/css/patterns/animations.css` ```css /* Animations - ROA2WEB */ /* Slide Down Animation */ @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .slide-down { animation: slideDown var(--duration-fast) ease-out; } /* Fade In Animation */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .fade-in { animation: fadeIn var(--duration-normal) ease-in; } /* Slide In From Right */ @keyframes slideInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } } .slide-in-right { animation: slideInRight var(--duration-normal) ease-out; } /* Pulse Animation */ @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .pulse { animation: pulse var(--duration-slower) ease-in-out infinite; } ``` **Acceptance Criteria:** - [ ] Common animations defined - [ ] Duration variables used - [ ] Utility classes created --- #### Task 1.4: Create tokens.css **Status:** ⏸️ | **Est:** 45 min **File:** `reports-app/frontend/src/assets/css/core/tokens.css` ```css /* Extended Design Tokens - ROA2WEB */ :root { /* ===== Card Tokens ===== */ --card-padding: var(--space-lg); --card-padding-sm: var(--space-md); --card-padding-lg: var(--space-xl); --card-gap: var(--space-md); --card-min-height: 280px; /* ===== Typography Tokens ===== */ --value-size: 1.5rem; --value-size-lg: 2rem; --label-size: 0.875rem; --sublabel-size: 0.8125rem; /* ===== Interactive Tokens ===== */ --hover-lift: -2px; --active-lift: 0px; --focus-ring: 0 0 0 3px rgba(var(--color-primary-rgb, 59, 130, 246), 0.1); /* ===== Animation Durations ===== */ --duration-instant: 100ms; --duration-fast: 150ms; --duration-normal: 250ms; --duration-slow: 350ms; --duration-slower: 500ms; /* ===== Component Sizing ===== */ --spinner-size: 40px; --spinner-size-sm: 24px; --spinner-size-lg: 56px; --spinner-border: 4px; /* ===== Dashboard Metrics ===== */ --metric-gap: 1rem; --sparkline-height: 80px; --sparkline-height-lg: 150px; } ``` **Acceptance Criteria:** - [ ] All extended tokens defined - [ ] References existing variables - [ ] No hardcoded values --- #### Task 1.5: Create primevue-overrides.css **Status:** ⏸️ | **Est:** 2 hours **File:** `reports-app/frontend/src/assets/css/vendor/primevue-overrides.css` ```css /* PrimeVue Component Overrides - ROA2WEB */ /* Global customization of PrimeVue saga-blue theme */ /* ===== Input Components ===== */ .p-inputtext, .p-password input, .p-dropdown, .p-calendar input, .p-autocomplete input { border: 2px solid var(--color-border) !important; border-radius: var(--radius-md) !important; padding: var(--space-sm) var(--space-md) !important; font-size: var(--text-base) !important; font-family: inherit !important; color: var(--color-text) !important; background: var(--color-bg) !important; transition: all var(--transition-fast) !important; min-height: 44px !important; } /* ===== Focus States ===== */ .p-inputtext:focus, .p-password input:focus, .p-dropdown:focus, .p-calendar input:focus, .p-autocomplete input:focus { outline: none !important; border-color: var(--color-primary) !important; box-shadow: var(--focus-ring) !important; } /* ===== Hover States ===== */ .p-inputtext:hover:not(:disabled), .p-password input:hover:not(:disabled), .p-dropdown:hover:not(:disabled) { border-color: var(--color-border-dark, #d1d5db) !important; } /* ===== Disabled States ===== */ .p-inputtext:disabled, .p-password input:disabled, .p-dropdown:disabled { background: var(--color-bg-muted, #f3f4f6) !important; color: var(--color-text-muted, #9ca3af) !important; opacity: 0.6 !important; cursor: not-allowed !important; } /* ===== Validation States ===== */ .p-invalid.p-component, .p-inputtext.p-invalid, .p-password.p-invalid input { border-color: var(--color-error, #ef4444) !important; } /* ===== Button Overrides ===== */ .p-button { padding: var(--space-sm) var(--space-md) !important; font-size: var(--text-sm) !important; font-weight: var(--font-medium) !important; border-radius: var(--radius-md) !important; transition: all var(--transition-fast) !important; } .p-button:hover { transform: translateY(-1px) !important; box-shadow: var(--shadow-md) !important; } /* ===== DataTable ===== */ .p-datatable .p-datatable-thead > tr > th { background: var(--color-bg-muted, #f9fafb) !important; color: var(--color-text) !important; font-weight: var(--font-semibold) !important; border-bottom: 2px solid var(--color-border) !important; padding: var(--space-md) var(--space-lg) !important; } .p-datatable .p-datatable-tbody > tr { transition: background-color var(--transition-fast) !important; } .p-datatable .p-datatable-tbody > tr:hover { background: var(--color-bg-secondary, #f8fafc) !important; } /* ===== Card ===== */ .p-card { box-shadow: var(--shadow-sm) !important; border: 1px solid var(--color-border) !important; border-radius: var(--card-radius, 8px) !important; } .p-card .p-card-header { background: var(--color-bg-secondary) !important; border-bottom: 1px solid var(--color-border) !important; padding: var(--space-lg) !important; } .p-card .p-card-body { padding: var(--space-lg) !important; } /* ===== Mobile Optimizations ===== */ @media (max-width: 768px) { .p-inputtext, .p-password input, .p-dropdown, .p-calendar input { font-size: 16px !important; /* Prevent iOS zoom */ } } ``` **Acceptance Criteria:** - [ ] All common PrimeVue components styled - [ ] Design tokens used (not hardcoded) - [ ] Mobile optimizations included - [ ] Ready for Phase 3 migration --- ### 2. Integration (2 tasks) #### Task 2.1: Update main.css **Status:** ⏸️ | **Est:** 15 min **File:** `reports-app/frontend/src/assets/css/main.css` **Add after existing imports:** ```css /* Main CSS Entry Point - ROA2WEB */ /* 1. Core Foundation */ @import './core/variables.css'; @import './core/tokens.css'; /* NEW */ @import './core/reset.css'; @import './core/typography.css'; /* 2. Layout System */ @import './layout/grid.css'; @import './layout/containers.css'; @import './layout/navigation.css'; /* 3. Component Library */ @import './components/cards.css'; @import './components/buttons.css'; @import './components/tables.css'; @import './components/forms.css'; @import './components/stats.css'; /* 4. Patterns */ @import './patterns/interactive.css'; /* NEW */ @import './patterns/dashboard.css'; /* NEW */ @import './patterns/animations.css'; /* NEW */ /* 5. Utilities */ @import './utilities/spacing.css'; @import './utilities/display.css'; @import './utilities/text.css'; @import './utilities/flex.css'; /* 6. Vendor Overrides */ @import './vendor/primevue-overrides.css'; /* NEW */ /* 7. Mobile Optimizations */ @import './mobile.css'; ``` **Acceptance Criteria:** - [ ] All new files imported - [ ] Import order correct (core → patterns → vendor) - [ ] No syntax errors --- #### Task 2.2: Verify No Visual Changes **Status:** ⏸️ | **Est:** 30 min ```bash # Build and verify npm run build # Check bundle size ls -lh dist/assets/*.css # Run dev server npm run dev # Visually check pages ``` **Check all pages:** - [ ] Login page unchanged - [ ] Dashboard unchanged - [ ] Invoices unchanged - [ ] No console errors - [ ] No CSS warnings **Acceptance Criteria:** - [ ] Zero visual changes - [ ] Build successful - [ ] No errors in console --- ### 3. Testing & Documentation (3 tasks) #### Task 3.1: Build Verification **Status:** ⏸️ | **Est:** 15 min ```bash cd reports-app/frontend # Clean build rm -rf dist/ npm run build # Check for errors echo $? # Should be 0 # Verify CSS files ls -la dist/assets/*.css ``` **Acceptance Criteria:** - [ ] Build completes without errors - [ ] CSS bundle created - [ ] No missing imports --- #### Task 3.2: Pattern Documentation **Status:** ⏸️ | **Est:** 45 min **Create:** `docs/CSS_PATTERNS_REFERENCE.md` **Content:** ```markdown # ROA2WEB CSS Patterns Reference ## Interactive Patterns ### Loading Spinner \`\`\`html
\`\`\` ### Trend Indicator \`\`\`html +15% \`\`\` ``` **Acceptance Criteria:** - [ ] All patterns documented with examples - [ ] HTML examples provided - [ ] Use cases explained --- #### Task 3.3: Commit Phase 2 **Status:** ⏸️ | **Est:** 10 min ```bash git add . git commit -m "feat(css): Phase 2 - Add global pattern foundation - Create interactive.css (loading, trends, collapse) - Create dashboard.css (headers, metrics, breakdowns) - Create animations.css (slideDown, fadeIn, pulse) - Create tokens.css (extended design tokens) - Create primevue-overrides.css (centralized PrimeVue styling) - Update main.css with new imports - Zero visual changes (additive only) Files created: 5 new CSS files Lines added: ~600 lines Phase: 2/7 complete " git push origin feature/css-refactoring ``` **Acceptance Criteria:** - [ ] All files committed - [ ] Commit message descriptive - [ ] Pushed to remote --- ## Completion Criteria - [ ] 5 new CSS files created - [ ] All patterns implemented - [ ] main.css updated - [ ] Zero visual changes - [ ] Build successful - [ ] Documentation created - [ ] Committed to git --- ## Next Phase **Phase 3:** PrimeVue Centralizare - Migrate all component `:deep()` to global - Eliminate `!important` from components - See: [phase-3-primevue.md](./phase-3-primevue.md) --- **Created:** 2025-11-18 **Status:** ⏸️ Not Started