# Reports Frontend Rework Plan
## Overview
This plan outlines the modernization of Reports frontend pages (`Index.vue` and `Show.vue`) using shadcn-vue components and AppCard containers, following the same patterns established in the Settings pages rework.
## Current State Analysis
### Reports/Index.vue (30 lines)
**Current Implementation:**
- Simple grid layout with native divs
- Report cards: `border rounded-lg p-4 bg-white shadow-sm hover:shadow-md`
- Grid: `md:grid-cols-2 lg:grid-cols-3`
- Each card shows: name (h2), description (p), Link to report
- **No shadcn-vue components used**
**Identified Issues:**
- Native HTML/Tailwind instead of shadcn-vue Card
- Inconsistent with Settings pages styling
- No icons for visual interest
- Basic hover effects only
### Reports/Show.vue (314 lines)
**Current Implementation:**
- Complex page with filters, export buttons, and data table
- Header section: title, description, export buttons (lines 190-196)
- Buttons: `px-3 py-2 rounded bg-gray-200 hover:bg-gray-300`
- Filter section: grid layout `md:grid-cols-4` (lines 218-270)
- Native inputs: `border rounded px-2 py-1`
- Native selects: `border rounded px-2 py-1`
- DatePicker component (already working)
- Filter buttons: Apply (`bg-indigo-600`) and Reset (`bg-gray-100`)
- Data table: DataTableServer component (lines 285-300)
- Formatting functions: formatNumberEU, formatDateEU, formatDateTimeEU, formatCell
**Identified Issues:**
- No Card containers for sections
- Native buttons instead of shadcn Button
- Native input/select elements instead of shadcn Input/Select
- No visual separation between sections
- Filter section could be extracted to partial
## Target Architecture
### Pattern Reference from Settings Pages
**Settings/Index.vue Pattern:**
```vue
Title
Description
```
**Settings/Archive/Index.vue Pattern:**
- Uses AppCard for main container
- Extracted partials: ArchiveRuleCard, CreateRuleForm, EditRuleForm
- Alert components for warnings
- Badge components for status indicators
## Implementation Plan
### Phase 1: Reports/Index.vue Rework (Simple)
**Goal:** Replace native divs with shadcn-vue Card components, add icons
**Changes:**
1. **Import shadcn-vue components:**
```js
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/Components/ui/card";
import { Button } from "@/Components/ui/button";
import { BarChart3, FileText, Activity, Users, TrendingUp, Calendar } from "lucide-vue-next";
```
2. **Add icon mapping for reports:**
```js
const reportIcons = {
'contracts': FileText,
'field': TrendingUp,
'activities': Activity,
// fallback icon
default: BarChart3,
};
function getReportIcon(category) {
return reportIcons[category] || reportIcons.default;
}
```
3. **Replace report card structure:**
- Remove native `
`
- Use `
`
- Structure:
```vue
{{ report.name }}
{{ report.description }}
```
4. **Update page header:**
- Wrap in proper container with consistent spacing
- Match Settings/Index.vue header style
**Estimated Changes:**
- Lines: 30 → ~65 lines (with imports and icon logic)
- Files modified: 1 (Index.vue)
- Files created: 0
**Risk Level:** Low (simple page, straightforward replacement)
---
### Phase 2: Reports/Show.vue Rework - Structure (Medium)
**Goal:** Add Card containers for sections, replace native buttons
**Changes:**
1. **Import shadcn-vue components:**
```js
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/Components/ui/card";
import { Button } from "@/Components/ui/button";
import { Input } from "@/Components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/Components/ui/select";
import { Label } from "@/Components/ui/label";
import { Badge } from "@/Components/ui/badge";
import { Separator } from "@/Components/ui/separator";
import { Download, Filter, RotateCcw } from "lucide-vue-next";
```
2. **Wrap header + export buttons in Card:**
```vue
{{ name }}
{{ description }}
```
3. **Wrap filters in Card:**
```vue
Filtri
```
4. **Wrap DataTableServer in Card:**
```vue
Rezultati
Skupaj {{ meta?.total || 0 }} {{ meta?.total === 1 ? 'rezultat' : 'rezultatov' }}
/>
```
5. **Replace all native buttons with shadcn Button:**
- Export buttons: `variant="outline" size="sm"`
- Apply filter button: default variant
- Reset button: `variant="outline"`
**Estimated Changes:**
- Lines: 314 → ~350 lines (with imports and Card wrappers)
- Files modified: 1 (Show.vue)
- Files created: 0
- **Keep formatting functions unchanged** (working correctly)
**Risk Level:** Low-Medium (more complex but no logic changes)
---
### Phase 3: Reports/Show.vue - Replace Native Inputs (Medium)
**Goal:** Replace native input/select elements with shadcn-vue components
**Changes:**
1. **Replace date inputs:**
```vue
```
2. **Replace text/number inputs:**
```vue
```
3. **Replace select inputs (user/client):**
```vue
Nalagam…
```
4. **Update filter grid layout:**
- Change from `md:grid-cols-4` to `md:grid-cols-2 lg:grid-cols-4`
- Use `space-y-2` for label/input spacing
- Consistent gap: `gap-4`
**Estimated Changes:**
- Lines: ~350 → ~380 lines (shadcn Input/Select have more markup)
- Files modified: 1 (Show.vue)
- Files created: 0
**Risk Level:** Medium (v-model binding changes, test thoroughly)
---
### Phase 4: Optional - Extract Filter Section Partial (Optional)
**Goal:** Reduce Show.vue complexity by extracting filter logic
**Decision Criteria:**
- If filter section exceeds ~80 lines → extract to partial
- If multiple filter types need separate handling → extract
**Potential Partial Structure:**
```
resources/js/Pages/Reports/Partials/
FilterSection.vue
```
**FilterSection.vue:**
- Props: `inputs`, `filters` (reactive object), `userOptions`, `clientOptions`, `loading states`
- Emits: `@apply`, `@reset`
- Contains: entire filter grid + buttons
**Benefits:**
- Show.vue reduced from ~380 lines to ~300 lines
- Filter logic isolated and reusable
- Easier to maintain filter types
**Risks:**
- Adds complexity with props/emits
- Might not be worth it if filter logic is simple
**Recommendation:** Evaluate after Phase 3 completion. If filter section is clean and under 80 lines, skip this phase.
---
## Component Inventory
### shadcn-vue Components Needed
**Already Installed (verify):**
- Card, CardHeader, CardTitle, CardDescription, CardContent
- Button
- Input
- Select, SelectTrigger, SelectValue, SelectContent, SelectItem
- Label
- Badge
- Separator
**Need to Check:**
- lucide-vue-next icons (Download, Filter, RotateCcw, BarChart3, FileText, Activity, TrendingUp, Calendar)
### Custom Components
- AppCard (if needed for consistency)
- DatePicker (already working, keep as-is)
- DataTableServer (keep as-is)
---
## Testing Checklist
### Reports/Index.vue Testing:
- [ ] Cards display with correct icons
- [ ] Card hover effects work
- [ ] Links navigate to correct report
- [ ] Grid layout responsive (2 cols MD, 3 cols LG)
- [ ] Icons match report categories
### Reports/Show.vue Testing:
- [ ] Header Card displays title, description, export buttons
- [ ] Export buttons work (CSV, PDF, Excel)
- [ ] Filter Card displays all filter inputs correctly
- [ ] Date filters use DatePicker component
- [ ] User/Client selects load options async
- [ ] Apply filters button triggers report refresh
- [ ] Reset button clears all filters
- [ ] DataTableServer Card displays results
- [ ] Formatting functions work (dates, numbers, currencies)
- [ ] Pagination works
- [ ] All 6 reports render correctly:
- [ ] active-contracts
- [ ] field-jobs-completed
- [ ] decisions-counts
- [ ] segment-activity-counts
- [ ] actions-decisions-counts
- [ ] activities-per-period
---
## Implementation Order
### Step 1: Reports/Index.vue (30 min)
1. Import shadcn-vue components + icons
2. Add icon mapping function
3. Replace native divs with Card structure
4. Test navigation and layout
5. Verify responsive grid
### Step 2: Reports/Show.vue - Structure (45 min)
1. Import shadcn-vue components + icons
2. Wrap header + exports in Card
3. Wrap filters in Card
4. Wrap DataTableServer in Card
5. Replace all native buttons
6. Test all 6 reports
### Step 3: Reports/Show.vue - Inputs (60 min)
1. Replace text/number inputs with shadcn Input
2. Replace select inputs with shadcn Select
3. Add Label components
4. Test v-model bindings
5. Test async user/client loading
6. Test filter apply/reset
7. Verify all filter types work
### Step 4: Optional Partial Extraction (30 min, if needed)
1. Create FilterSection.vue partial
2. Move filter logic to partial
3. Set up props/emits
4. Test with all reports
### Step 5: Final Testing (30 min)
1. Test complete workflow (Index → Show → Filters → Export)
2. Verify all 6 reports
3. Test responsive layouts (mobile, tablet, desktop)
4. Check formatting consistency
5. Verify no regressions
**Total Estimated Time:** 2.5 - 3.5 hours
---
## Risk Assessment
### Low Risk:
- Index.vue rework (simple structure, straightforward replacement)
- Adding Card containers to Show.vue
- Replacing native buttons with shadcn Button
### Medium Risk:
- Replacing native inputs with shadcn Input/Select
- v-model bindings might need adjustments
- Async select loading needs testing
- Number input behavior might differ
### Mitigation Strategies:
1. Test each phase incrementally
2. Keep formatting functions unchanged (already working)
3. Test v-model bindings immediately after input replacement
4. Verify async loading with console logs
5. Test all 6 reports after each phase
6. Keep git commits small and atomic
---
## Success Criteria
### Functional Requirements:
✅ All reports navigate from Index page
✅ All filters work correctly (date, text, number, user select, client select)
✅ Apply filters refreshes report data
✅ Reset filters clears all inputs
✅ Export buttons generate CSV/PDF/Excel files
✅ DataTableServer displays results correctly
✅ Pagination works
✅ Formatting functions work (dates, numbers)
### Visual Requirements:
✅ Consistent Card-based layout
✅ shadcn-vue components throughout
✅ Icons for visual interest
✅ Hover effects on cards
✅ Proper spacing and alignment
✅ Responsive layout (mobile, tablet, desktop)
✅ Matches Settings pages style
### Code Quality:
✅ No code duplication
✅ Clean component imports
✅ Consistent naming conventions
✅ Proper TypeScript/Vue 3 patterns
✅ Formatting functions unchanged
✅ No regressions in functionality
---
## Notes
- **DatePicker component:** Already working, imported correctly, no changes needed
- **Formatting functions:** Keep unchanged (formatNumberEU, formatDateEU, formatDateTimeEU, formatCell)
- **DataTableServer:** Keep as-is, already working well
- **Async loading:** User/client select loading works, just needs shadcn Select wrapper
- **Pattern consistency:** Follow Settings/Index.vue and Settings/Archive/Index.vue patterns
- **Icon usage:** Add icons to Index.vue for visual interest, use lucide-vue-next
- **Button variants:** Use `variant="outline"` for secondary actions, default for primary
---
## Post-Implementation
After completing all phases:
1. **Documentation:**
- Update this document with actual implementation notes
- Document any deviations from plan
- Note any unexpected issues
2. **Code Review:**
- Check for consistent component usage
- Verify no native HTML/CSS buttons/inputs remain
- Ensure proper import structure
3. **User Feedback:**
- Test with actual users
- Gather feedback on UI improvements
- Note any requested adjustments
4. **Performance:**
- Verify no performance regressions
- Check bundle size impact
- Monitor async loading times
---
## Conclusion
This plan provides a structured approach to modernizing the Reports frontend pages using shadcn-vue components. The phased approach allows for incremental testing and reduces risk. The estimated total time is 2.5-3.5 hours, with low to medium risk level.
**Recommendation:** Start with Phase 1 (Index.vue) as a proof of concept, then proceed to Phase 2 and 3 for Show.vue. Evaluate Phase 4 (partial extraction) after Phase 3 completion based on actual complexity.