# 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.