# 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
<Card class="hover:shadow-lg transition-shadow">
  <CardHeader>
    <div class="flex items-center gap-2">
      <component :is="icon" class="h-5 w-5 text-muted-foreground" />
      <CardTitle>Title</CardTitle>
    </div>
    <CardDescription>Description</CardDescription>
  </CardHeader>
  <CardContent>
    <Button variant="ghost">Action →</Button>
  </CardContent>
</Card>
```

**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 `<div class="border rounded-lg p-4 bg-white shadow-sm hover:shadow-md">`
   - Use `<Card class="hover:shadow-lg transition-shadow cursor-pointer">`
   - Structure:
     ```vue
     <Card>
       <CardHeader>
         <div class="flex items-center gap-2">
           <component :is="getReportIcon(report.category)" class="h-5 w-5 text-muted-foreground" />
           <CardTitle>{{ report.name }}</CardTitle>
         </div>
         <CardDescription>{{ report.description }}</CardDescription>
       </CardHeader>
       <CardContent>
         <Link :href="route('reports.show', report.slug)">
           <Button variant="ghost" size="sm" class="w-full justify-start">
             Odpri → 
           </Button>
         </Link>
       </CardContent>
     </Card>
     ```

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
   <Card class="mb-6">
     <CardHeader>
       <div class="flex items-start justify-between">
         <div>
           <CardTitle>{{ name }}</CardTitle>
           <CardDescription v-if="description">{{ description }}</CardDescription>
         </div>
         <div class="flex gap-2">
           <Button variant="outline" size="sm" @click="exportFile('csv')">
             <Download class="mr-2 h-4 w-4" />
             CSV
           </Button>
           <Button variant="outline" size="sm" @click="exportFile('pdf')">
             <Download class="mr-2 h-4 w-4" />
             PDF
           </Button>
           <Button variant="outline" size="sm" @click="exportFile('xlsx')">
             <Download class="mr-2 h-4 w-4" />
             Excel
           </Button>
         </div>
       </div>
     </CardHeader>
   </Card>
   ```

3. **Wrap filters in Card:**
   ```vue
   <Card class="mb-6">
     <CardHeader>
       <div class="flex items-center gap-2">
         <Filter class="h-5 w-5 text-muted-foreground" />
         <CardTitle>Filtri</CardTitle>
       </div>
     </CardHeader>
     <CardContent>
       <!-- Filter grid here -->
       <div class="grid gap-4 md:grid-cols-4">
         <!-- Filter inputs -->
       </div>
       <Separator class="my-4" />
       <div class="flex gap-2">
         <Button @click="applyFilters">
           <Filter class="mr-2 h-4 w-4" />
           Prikaži
         </Button>
         <Button variant="outline" @click="resetFilters">
           <RotateCcw class="mr-2 h-4 w-4" />
           Ponastavi
         </Button>
       </div>
     </CardContent>
   </Card>
   ```

4. **Wrap DataTableServer in Card:**
   ```vue
   <Card>
     <CardHeader>
       <CardTitle>Rezultati</CardTitle>
       <CardDescription>
         Skupaj {{ meta?.total || 0 }} {{ meta?.total === 1 ? 'rezultat' : 'rezultatov' }}
       </CardDescription>
     </CardHeader>
     <CardContent>
       <DataTableServer
         <!-- props -->
       />
     </CardContent>
   </Card>
   ```

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
   <!-- Keep DatePicker as-is (already working) -->
   <div class="space-y-2">
     <Label>{{ inp.label || inp.key }}</Label>
     <DatePicker
       v-model="filters[inp.key]"
       format="dd.MM.yyyy"
       placeholder="Izberi datum"
     />
   </div>
   ```

2. **Replace text/number inputs:**
   ```vue
   <div class="space-y-2">
     <Label>{{ inp.label || inp.key }}</Label>
     <Input
       v-model="filters[inp.key]"
       :type="inp.type === 'integer' ? 'number' : 'text'"
       placeholder="Vnesi vrednost"
     />
   </div>
   ```

3. **Replace select inputs (user/client):**
   ```vue
   <div class="space-y-2">
     <Label>{{ inp.label || inp.key }}</Label>
     <Select v-model="filters[inp.key]">
       <SelectTrigger>
         <SelectValue placeholder="— brez —" />
       </SelectTrigger>
       <SelectContent>
         <SelectItem :value="null">— brez —</SelectItem>
         <SelectItem v-for="u in userOptions" :key="u.id" :value="u.id">
           {{ u.name }}
         </SelectItem>
       </SelectContent>
     </Select>
     <div v-if="userLoading" class="text-xs text-muted-foreground">Nalagam…</div>
   </div>
   ```

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.
