Add complete planning documentation for CSS architecture refactoring project: - 7-phase implementation plan (92-120 hours) - 123 detailed tasks across all phases - Target: ~3,260 lines CSS reduction (40-50%) - Complete requirements analysis - Progress tracking system - Phase-by-phase breakdown with acceptance criteria Documentation structure: - features/README.md - Project overview and quick start - features/CSS_REFACTORING_PLAN.md - Implementation strategy - features/CSS_REFACTORING_REQUIREMENTS.md - Detailed requirements - features/PROGRESS_TRACKER.md - Live progress tracking - features/phases/*.md - 7 phase documents with tasks Ready to begin Phase 1: Forms Standardization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
585 lines
13 KiB
Markdown
585 lines
13 KiB
Markdown
# Phase 4: Card Components Refactoring 📊
|
||
|
||
**Priority:** High - Major duplication area
|
||
**Duration:** 16-20 hours
|
||
**Status:** ⏸️ Not Started
|
||
**Risk Level:** High
|
||
|
||
---
|
||
|
||
## Obiective
|
||
|
||
1. **Extract common patterns** - Base card, sparklines, breakdowns
|
||
2. **Refactor 5 card components** - ~800 lines eliminated
|
||
3. **Standardize metric displays** - Consistent value/label patterns
|
||
4. **Reusable card classes** - For future components
|
||
|
||
---
|
||
|
||
## Current State
|
||
|
||
| Component | Current CSS | Target CSS | Reduction |
|
||
|-----------|-------------|------------|-----------|
|
||
| MetricCard.vue | 331 lines | 80 lines | 251 lines (76%) |
|
||
| CashFlowMetricCard.vue | 179 lines | 60 lines | 119 lines (67%) |
|
||
| ClientiBalanceCard.vue | 260 lines | 90 lines | 170 lines (65%) |
|
||
| FurnizoriBalanceCard.vue | ~260 lines | 90 lines | 170 lines (65%) |
|
||
| TreasuryDualCard.vue | ~200 lines | 60 lines | 140 lines (70%) |
|
||
| **TOTAL** | **~1,230 lines** | **~380 lines** | **~850 lines (69%)** |
|
||
|
||
---
|
||
|
||
## Task Breakdown (22 tasks)
|
||
|
||
### 1. Global Pattern Extraction (5 tasks)
|
||
|
||
#### Task 1.1: Add Base Card Styles to cards.css
|
||
**Status:** ⏸️ | **Est:** 1 hour
|
||
|
||
**File:** `reports-app/frontend/src/assets/css/components/cards.css`
|
||
|
||
**Add at end of file:**
|
||
```css
|
||
/* ===== Dashboard Metric Cards ===== */
|
||
|
||
.metric-card {
|
||
background: var(--color-bg);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--card-radius);
|
||
padding: var(--card-padding);
|
||
transition: all var(--transition-fast);
|
||
min-height: var(--card-min-height);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--card-gap);
|
||
}
|
||
|
||
.metric-card:hover {
|
||
box-shadow: var(--shadow-md);
|
||
transform: translateY(var(--hover-lift));
|
||
border-color: var(--color-primary);
|
||
}
|
||
|
||
/* Metric display patterns */
|
||
.metric-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-md);
|
||
margin-bottom: var(--space-sm);
|
||
}
|
||
|
||
.metric-icon {
|
||
width: 40px;
|
||
height: 40px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: var(--radius-md);
|
||
font-size: var(--text-xl);
|
||
}
|
||
|
||
.metric-value {
|
||
font-size: var(--value-size);
|
||
font-weight: var(--font-bold);
|
||
line-height: var(--leading-tight);
|
||
font-family: var(--font-mono, monospace);
|
||
color: var(--color-text);
|
||
}
|
||
|
||
.metric-value-lg {
|
||
font-size: var(--value-size-lg);
|
||
}
|
||
|
||
.metric-label {
|
||
font-size: var(--label-size);
|
||
font-weight: var(--font-medium);
|
||
color: var(--color-text-secondary);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
margin-bottom: var(--space-xs);
|
||
}
|
||
|
||
/* Responsive */
|
||
@media (max-width: 768px) {
|
||
.metric-card {
|
||
min-height: calc(var(--card-min-height) - 40px);
|
||
padding: var(--card-padding-sm);
|
||
}
|
||
|
||
.metric-value {
|
||
font-size: 1.25rem;
|
||
}
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Base card patterns added
|
||
- [ ] Metric display patterns defined
|
||
- [ ] Responsive rules included
|
||
- [ ] No visual changes (not used yet)
|
||
|
||
---
|
||
|
||
#### Task 1.2: Add Sparkline Patterns to dashboard.css
|
||
**Status:** ⏸️ | **Est:** 30 min
|
||
|
||
**File:** `reports-app/frontend/src/assets/css/patterns/dashboard.css`
|
||
|
||
**Add:**
|
||
```css
|
||
/* ===== Enhanced Sparkline Patterns ===== */
|
||
|
||
.metric-sparkline {
|
||
margin: var(--space-md) 0;
|
||
}
|
||
|
||
.sparkline-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: var(--space-xs);
|
||
}
|
||
|
||
.sparkline-title {
|
||
font-size: var(--text-xs);
|
||
color: var(--color-text-secondary);
|
||
text-transform: uppercase;
|
||
font-weight: var(--font-medium);
|
||
}
|
||
|
||
.sparkline-value {
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--font-semibold);
|
||
font-family: var(--font-mono, monospace);
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Sparkline header pattern defined
|
||
- [ ] Title/value layout included
|
||
|
||
---
|
||
|
||
#### Task 1.3: Enhanced Breakdown Patterns
|
||
**Status:** ⏸️ | **Est:** 45 min
|
||
|
||
**File:** `reports-app/frontend/src/assets/css/patterns/dashboard.css`
|
||
|
||
**Enhance existing breakdown patterns:**
|
||
```css
|
||
/* ===== Enhanced Breakdown Patterns ===== */
|
||
|
||
.breakdown-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);
|
||
margin-bottom: var(--space-xs);
|
||
}
|
||
|
||
.breakdown-header:hover {
|
||
background: var(--color-bg-secondary);
|
||
}
|
||
|
||
.breakdown-header-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-sm);
|
||
}
|
||
|
||
.breakdown-toggle {
|
||
color: var(--color-text-secondary);
|
||
font-size: 0.625rem;
|
||
transition: transform var(--transition-fast);
|
||
}
|
||
|
||
.breakdown-toggle.expanded {
|
||
transform: rotate(90deg);
|
||
}
|
||
|
||
.breakdown-divider {
|
||
height: 1px;
|
||
background: var(--color-border);
|
||
margin: var(--space-md) 0;
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Breakdown header with toggle
|
||
- [ ] Hover states defined
|
||
- [ ] Animation classes ready
|
||
|
||
---
|
||
|
||
#### Task 1.4: Add Color Utilities
|
||
**Status:** ⏸️ | **Est:** 20 min
|
||
|
||
**File:** `reports-app/frontend/src/assets/css/utilities/colors.css` (NEW)
|
||
|
||
```css
|
||
/* Color Utilities - ROA2WEB */
|
||
|
||
/* Background colors for icons */
|
||
.bg-primary { background-color: var(--color-primary); }
|
||
.bg-success { background-color: var(--color-success); }
|
||
.bg-warning { background-color: var(--color-warning); }
|
||
.bg-error { background-color: var(--color-error); }
|
||
.bg-info { background-color: var(--color-info); }
|
||
|
||
.bg-primary-light { background-color: rgba(var(--color-primary-rgb), 0.1); }
|
||
.bg-success-light { background-color: rgba(var(--color-success-rgb), 0.1); }
|
||
.bg-warning-light { background-color: rgba(var(--color-warning-rgb), 0.1); }
|
||
|
||
/* Text colors */
|
||
.text-primary { color: var(--color-primary); }
|
||
.text-success { color: var(--color-success); }
|
||
.text-warning { color: var(--color-warning); }
|
||
.text-error { color: var(--color-error); }
|
||
.text-muted { color: var(--color-text-muted); }
|
||
```
|
||
|
||
**Add to main.css:**
|
||
```css
|
||
@import './utilities/colors.css';
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Color utilities created
|
||
- [ ] Imported in main.css
|
||
- [ ] RGB variants for transparency
|
||
|
||
---
|
||
|
||
#### Task 1.5: Test Global Patterns
|
||
**Status:** ⏸️ | **Est:** 15 min
|
||
|
||
```bash
|
||
# Build and verify
|
||
npm run build
|
||
|
||
# Check for errors
|
||
npm run dev
|
||
|
||
# No visual changes expected
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Build successful
|
||
- [ ] No CSS errors
|
||
- [ ] Patterns available (not used yet)
|
||
|
||
---
|
||
|
||
### 2. Component Refactoring (15 tasks - 3 per component x 5)
|
||
|
||
#### MetricCard.vue (Tasks 2.1-2.3)
|
||
|
||
##### Task 2.1: Update MetricCard Template
|
||
**Status:** ⏸️ | **Est:** 1 hour
|
||
|
||
**File:** `src/components/dashboard/cards/MetricCard.vue`
|
||
|
||
**Current template structure:**
|
||
```vue
|
||
<div class="metric-card">
|
||
<div class="card-header">
|
||
<div class="icon-wrapper" :style="{ background: iconBg }">
|
||
<i :class="icon"></i>
|
||
</div>
|
||
<!-- ... -->
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
**Updated template:**
|
||
```vue
|
||
<div class="metric-card card-hover">
|
||
<div class="metric-header">
|
||
<div class="metric-icon bg-primary-light text-primary">
|
||
<i :class="icon"></i>
|
||
</div>
|
||
<div class="metric-label">{{ label }}</div>
|
||
</div>
|
||
|
||
<div class="metric-value" :class="{ 'trend-up': trend > 0, 'trend-down': trend < 0 }">
|
||
{{ formattedValue }}
|
||
</div>
|
||
|
||
<div v-if="showSparkline" class="sparkline-container">
|
||
<canvas ref="sparklineCanvas" class="sparkline-canvas"></canvas>
|
||
</div>
|
||
|
||
<div v-if="hasBreakdown" class="breakdown-section">
|
||
<div class="breakdown-header" @click="toggleBreakdown">
|
||
<div class="breakdown-header-left">
|
||
<i class="pi pi-chevron-right breakdown-toggle" :class="{ expanded: breakdownExpanded }"></i>
|
||
<span class="breakdown-label">Detalii</span>
|
||
</div>
|
||
<span class="breakdown-value">{{ breakdownTotal }}</span>
|
||
</div>
|
||
|
||
<div v-if="breakdownExpanded" class="breakdown-subitems slide-down">
|
||
<div v-for="item in breakdownItems" :key="item.id" class="breakdown-subitem">
|
||
<span class="breakdown-sublabel">{{ item.label }}</span>
|
||
<span class="breakdown-subvalue">{{ item.value }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Template uses global classes
|
||
- [ ] No inline styles for colors
|
||
- [ ] Breakdown uses global pattern
|
||
- [ ] Sparkline uses global container
|
||
|
||
---
|
||
|
||
##### Task 2.2: Remove Duplicate CSS from MetricCard
|
||
**Status:** ⏸️ | **Est:** 45 min
|
||
|
||
**DELETE from <style scoped> (lines to remove ~250):**
|
||
```css
|
||
/* DELETE - now in cards.css */
|
||
.metric-card {
|
||
background: var(--color-bg, #ffffff);
|
||
border: 1px solid var(--color-border, #e5e7eb);
|
||
/* ... 20 more lines ... */
|
||
}
|
||
|
||
.metric-card:hover {
|
||
/* ... DELETE ... */
|
||
}
|
||
|
||
.card-header {
|
||
/* ... DELETE ... */
|
||
}
|
||
|
||
/* DELETE - now in dashboard.css */
|
||
.breakdown-header {
|
||
/* ... DELETE ... */
|
||
}
|
||
|
||
.breakdown-subitems {
|
||
/* ... DELETE ... */
|
||
}
|
||
|
||
/* DELETE - now in animations.css */
|
||
@keyframes slideDown {
|
||
/* ... DELETE ... */
|
||
}
|
||
```
|
||
|
||
**KEEP component-specific:**
|
||
```css
|
||
/* Component-specific Chart.js configuration */
|
||
.sparkline-canvas {
|
||
/* Keep Chart.js specific overrides */
|
||
}
|
||
|
||
/* Component-specific data formatting */
|
||
.metric-specific-class {
|
||
/* Only if truly unique to this component */
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] 250+ lines deleted
|
||
- [ ] Only component-specific CSS remains
|
||
- [ ] Card renders identically
|
||
- [ ] Functionality preserved
|
||
|
||
---
|
||
|
||
##### Task 2.3: Test MetricCard
|
||
**Status:** ⏸️ | **Est:** 30 min
|
||
|
||
**Visual tests:**
|
||
- [ ] Card layout identical
|
||
- [ ] Hover effect works
|
||
- [ ] Sparkline renders
|
||
- [ ] Breakdown expands/collapses
|
||
- [ ] Trend indicators show correctly
|
||
- [ ] Icon background colors work
|
||
|
||
**Functional tests:**
|
||
- [ ] Props work (value, label, icon, trend)
|
||
- [ ] Computed properties correct
|
||
- [ ] Chart.js renders
|
||
- [ ] Breakdown data displays
|
||
- [ ] Click interactions work
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] No visual regressions
|
||
- [ ] All features work
|
||
- [ ] ~250 lines CSS eliminated
|
||
|
||
---
|
||
|
||
#### CashFlowMetricCard.vue (Tasks 2.4-2.6)
|
||
|
||
##### Task 2.4: Update CashFlowMetricCard Template
|
||
**Status:** ⏸️ | **Est:** 45 min
|
||
|
||
**Apply same pattern as MetricCard:**
|
||
- [ ] Use `.metric-card` base class
|
||
- [ ] Use `.metric-header`, `.metric-value`, `.metric-label`
|
||
- [ ] Use global breakdown pattern
|
||
- [ ] Remove inline styles
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Template updated
|
||
- [ ] Global classes used
|
||
- [ ] No inline styles
|
||
|
||
---
|
||
|
||
##### Task 2.5: Remove Duplicate CSS
|
||
**Status:** ⏸️ | **Est:** 30 min
|
||
|
||
**Target reduction:** 179 → 60 lines (119 lines deleted)
|
||
|
||
**Delete:**
|
||
- [ ] Card base styles
|
||
- [ ] Hover effects
|
||
- [ ] Breakdown patterns
|
||
- [ ] Animations
|
||
|
||
**Keep:**
|
||
- [ ] Component-specific chart config
|
||
- [ ] Unique data formatting
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] 119 lines deleted
|
||
- [ ] Component CSS < 60 lines
|
||
|
||
---
|
||
|
||
##### Task 2.6: Test CashFlowMetricCard
|
||
**Status:** ⏸️ | **Est:** 20 min
|
||
|
||
- [ ] Card renders correctly
|
||
- [ ] Dual charts display
|
||
- [ ] Cash flow data accurate
|
||
- [ ] Breakdown works
|
||
- [ ] No visual regressions
|
||
|
||
---
|
||
|
||
#### ClientiBalanceCard.vue (Tasks 2.7-2.9)
|
||
##### Task 2.7: Update Template
|
||
**Status:** ⏸️ | **Est:** 45 min
|
||
**Acceptance:** Template uses global patterns
|
||
|
||
##### Task 2.8: Remove Duplicate CSS
|
||
**Status:** ⏸️ | **Est:** 30 min
|
||
**Target:** 260 → 90 lines (170 deleted)
|
||
|
||
##### Task 2.9: Test
|
||
**Status:** ⏸️ | **Est:** 20 min
|
||
**Acceptance:** Client balance displays correctly
|
||
|
||
---
|
||
|
||
#### FurnizoriBalanceCard.vue (Tasks 2.10-2.12)
|
||
##### Task 2.10: Update Template
|
||
**Status:** ⏸️ | **Est:** 45 min
|
||
|
||
##### Task 2.11: Remove Duplicate CSS
|
||
**Status:** ⏸️ | **Est:** 30 min
|
||
**Target:** ~260 → 90 lines (170 deleted)
|
||
|
||
##### Task 2.12: Test
|
||
**Status:** ⏸️ | **Est:** 20 min
|
||
|
||
---
|
||
|
||
#### TreasuryDualCard.vue (Tasks 2.13-2.15)
|
||
##### Task 2.13: Update Template
|
||
**Status:** ⏸️ | **Est:** 45 min
|
||
|
||
##### Task 2.14: Remove Duplicate CSS
|
||
**Status:** ⏸️ | **Est:** 30 min
|
||
**Target:** ~200 → 60 lines (140 deleted)
|
||
|
||
##### Task 2.15: Test
|
||
**Status:** ⏸️ | **Est:** 20 min
|
||
|
||
---
|
||
|
||
### 3. Final Testing (2 tasks)
|
||
|
||
#### Task 3.1: Test All Cards Together
|
||
**Status:** ⏸️ | **Est:** 1 hour
|
||
|
||
**Dashboard view:**
|
||
- [ ] All 5 cards display in grid
|
||
- [ ] Hover effects consistent
|
||
- [ ] Sparklines render
|
||
- [ ] Breakdowns work on all cards
|
||
- [ ] Trend indicators correct
|
||
- [ ] Responsive layout works
|
||
|
||
**Playwright:**
|
||
```bash
|
||
npm run test:e2e -- tests/e2e/dashboard/
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] All cards work together
|
||
- [ ] No layout issues
|
||
- [ ] Visual regression tests pass
|
||
|
||
---
|
||
|
||
#### Task 3.2: Performance Measurement
|
||
**Status:** ⏸️ | **Est:** 30 min
|
||
|
||
**Measure:**
|
||
```bash
|
||
# CSS bundle size
|
||
ls -lh dist/assets/*.css
|
||
|
||
# Component CSS reduction
|
||
grep -c "}" src/components/dashboard/cards/*.vue
|
||
```
|
||
|
||
**Document:**
|
||
- [ ] Before: ~1,230 lines total card CSS
|
||
- [ ] After: ~380 lines total card CSS
|
||
- [ ] Reduction: ~850 lines (69%)
|
||
- [ ] Bundle size impact: ___ KB
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Target reduction achieved
|
||
- [ ] Metrics documented
|
||
|
||
---
|
||
|
||
## Completion Criteria
|
||
|
||
- [ ] 5 card components refactored
|
||
- [ ] ~850 lines CSS eliminated
|
||
- [ ] All cards use global patterns
|
||
- [ ] Visual regression tests pass
|
||
- [ ] Performance metrics documented
|
||
- [ ] Committed to git
|
||
|
||
---
|
||
|
||
## Next Phase
|
||
|
||
**Phase 5:** DashboardView.vue Major Refactoring
|
||
- THE BIG ONE: 2,010 → 300 lines
|
||
- See: [phase-5-dashboard.md](./phase-5-dashboard.md)
|
||
|
||
---
|
||
|
||
**Created:** 2025-11-18
|
||
**Status:** ⏸️ Not Started
|