---
task: Redesign HomeCooperative.vue into a proper Coordinator/Cooperative-user dashboard and wire it into Home.vue
cycles: 5
context: true
private: false
started: 2026-05-16T00:00:00Z
finished: 2026-05-16T00:01:00Z
---

## files
- `resources/js/Pages/Home.vue` [lines 57-58] — COORDINATOR currently maps to `HomeShared`; must import and use `HomeCooperative` instead
- `resources/js/Pages/Fragments/Home/HomeCooperative.vue` — full rewrite: currently only a chapter/geo-map component, needs full dashboard
- `resources/js/Pages/Fragments/Home/HomeStoreOwner.vue` — reference pattern: BalanceBox + ServiceButtonGrid + HomeSkeleton
- `resources/js/Components/Core/Stats/BalanceBox.vue` — stat card component (props: `stats[]`, `footerItems[]`, emits `footer-click`)
- `resources/js/Components/Core/Services/ServiceButtonGrid.vue` — icon grid (prop: `items[]` with `icon`, `title`, `pagename` or `action`)
- `resources/js/Components/Core/Services/SideTextButtonList.vue` — text list of quick actions
- `resources/js/Components/Core/Skeleton/HomeSkeleton.vue` — loading skeleton
- `resources/js/composables/usePageData.js` — `fetchPageData(url, payload)` pattern
- `routes/web.php` [lines 76-135] — `/home-data` GET endpoint; must add COORDINATOR-scoped cooperative stats
- `app/Http/Controllers/Market/CooperativeController.php` — available methods: list, show, registerMember, publicRegisterMember

## steps
1. **`routes/web.php` @ `/home-data` closure** — After the existing `$myStoresCount` block (line ~114), add a COORDINATOR-specific stats block:
   - Check `$acctType === UserTypes::COORDINATOR`
   - Query `Organization::where('type','COOPERATIVE')->count()` → `cooperative_total_no`
   - Query `CooperativeMember::whereHas('organization', fn($q)=>$q->where('created_by',$user->id))->count()` → `cooperative_members_no`
   - Query `Organization::where('type','COOPERATIVE')->where('created_by',$user->id)->withCount('members')->count()` → `my_cooperatives_no`
   - Add `pending_members_no`: count of `cooperative_members` with `created_at >= now()->subDays(7)` under the coordinator's cooperatives
   - Include all four keys in `$props['props']['stats']` unconditionally (0 for non-coordinators is fine)

2. **`resources/js/Pages/Home.vue`** — Add import at top: `import HomeCooperative from './Fragments/Home/HomeCooperative.vue';`
   — Change line 57-58 from `<HomeShared title="Coordinator" />` to `<HomeCooperative />`

3. **`resources/js/Pages/Fragments/Home/HomeCooperative.vue`** — Full rewrite. Preserve the chapter map as a collapsible section at the bottom. New structure:

   **Script:**
   - Imports: `ref, onMounted, computed, h`, `usePageData`, `useNavigate`, `useAuth`, `useModal`, `BalanceBox`, `ServiceButtonGrid`, `SideTextButtonList`, `HomeSkeleton`, and the existing `useChapters` (keep for map section)
   - Stats ref: `[{ title:'Cooperatives', number:0, unit:'Total', numberId:'cooperative_total_no' }, { title:'Members', number:0, unit:'Enrolled', numberId:'cooperative_members_no' }, { title:'New (7d)', number:0, unit:'Members', numberId:'pending_members_no' }]`
   - Footer items: `[{ title:'Cooperatives', icon:'<people icon url>', pagename:'CooperativeList' }, { title:'My Profile', icon:'<profile icon url>', pagename:'UserInfoEdit' }]`
   - `services` array: 8 items:
     1. `{ icon:'<people svg>', title:'Cooperatives', pagename:'CooperativeList' }`
     2. `{ icon:'<person-plus svg>', title:'Register Member', pagename:'CooperativeMemberRegister' }` (needs active coop hash — use `action:'registerMember'` to prompt)
     3. `{ icon:'<building svg>', title:'My Cooperative', action:'viewMyCoop' }`
     4. `{ icon:'<bar-chart svg>', title:'Reports', pagename:'ListReports' }`
     5. `{ icon:'<file-text svg>', title:'Documents', action:'viewDocs' }`
     6. `{ icon:'<check-square svg>', title:'Resolutions', action:'viewResolutions' }`
     7. `{ icon:'<people svg>', title:'Members', action:'viewMembers' }`
     8. `{ icon:'<map svg>', title:'Chapter Map', action:'toggleMap' }`
   - `quickActions` list items:
     - `{ text:'Create Cooperative', pagename:'CreateCooperative', icon:'...' }`
     - `{ text:'Member Ledger', pagename:'AccountingDashboard', icon:'...' }`
     - `{ text:'Add Transaction', pagename:'AddTransaction', icon:'...' }`
     - `{ text:'My Personal Profile', pagename:'UserInfoEdit', icon:'...' }`
   - `activeOrgHash`: `computed(() => user.value?.settings?.cooperatives?.[0] ?? null)`
   - `showMap`: `ref(false)` — toggled by `toggleMap` action
   - `viewMyCoop()`: if `activeOrgHash.value`, navigate to `CooperativeDetail` with `target: activeOrgHash.value`; else `modal.quickDismiss({title:'No Cooperative', body:'You have not joined a cooperative yet.'})`
   - `handleItemClick(item)`: dispatch on `item.action` or `navigate({ page: item.pagename })`
   - On `onMounted`: `fetchPageData('/home-data', {})` then `applyStats()`

   **Template:**
   - `<HomeSkeleton v-if="loading" />`
   - BalanceBox with cooperative stats and footer items, `@footer-click="handleItemClick"`
   - `<h5>Cooperative Services</h5>` + `<ServiceButtonGrid :items="services" @item-click="handleItemClick" />`
   - `<h5>Quick Actions</h5>` + `<SideTextButtonList :items="quickActions" @item-click="handleItemClick" />`
   - Collapsible map section: `<button @click="showMap=!showMap">Chapter Map</button>` + `<div v-show="showMap">` containing the existing Leaflet map code (preserve all existing refs and lifecycle hooks, but only `initMap()` when `showMap` becomes true via `watch`)

   **Style:** No `bg-white`/`bg-light`/`text-dark`. Use `var(--bg-card)`, `var(--text-primary)`. `:global(.dark-mode) .chapter-row { background: var(--bg-card) !important; }`.

4. **Icon URLs** — Reuse CDN URLs already in the project. Map to Font Awesome alternatives in the `icon` field or pick from existing `/assets/micons/` SVGs already used in `HomeUltimate.vue`. Acceptable: use `fas fa-*` class names as `icon` if `ServiceButtonGrid` supports icon class strings — check the component prop; if it only accepts URLs, use the same CDN icon URLs already referenced in `HomeShared.vue` and `HomeStoreOwner.vue` (people: `a/04d0e432a298.bin`, profile: `a/ac7a1cebe580.bin`, chart: `a/f87407046b18.bin`, docs: `a/c9fd442fe676.bin`).

5. **VueRouteMap check** — Confirm `CooperativeList`, `CooperativeDetail`, `CreateCooperative`, `CooperativeMemberRegister` all have `coordinator` in `allowedUserTypes`. If any are missing, add `'coordinator'` to their arrays in `app/Http/Controllers/Support/VueRouteMap.php`.

6. **UserPermissions check** — Confirm `UserTypes::COORDINATOR` has `ViewCooperatives`, `CreateCooperative`, `JoinCooperative`, `ViewAccountingReports` in `UserPermissions::roles()`. Add any missing ones.

## context
```
// routes/web.php ~line 92
$acctType = $user?->acct_type instanceof \App\Enums\UserTypes
    ? $user->acct_type
    : \App\Enums\UserTypes::tryFrom($user?->acct_type ?? '');
// stats keys currently returned: total_users_no, active_stores_no, pending_orders_no,
//   total_balance_php, total_transactions_no, total_transactions_php, projected_income_today,
//   transactions_today_no, cash_flow_today_php, my_stores_no

// BalanceBox props:
//   stats: Array<{ title, number, unit, align?, numberId? }>
//   footerItems: Array<{ title, icon?, pagename?, action? }>
//   boxStyle: string (CSS)

// ServiceButtonGrid: prop items[] = [{ icon: URL|string, title, pagename?, action? }]
// SideTextButtonList: prop items[] = [{ text, pagename?, action?, icon? }]
// usePageData: { data, loading, error, fetchPageData(url, payload) }
// applyStats pattern from HomeStoreOwner.vue:
//   stats.value = stats.value.map(s => {
//       const v = data.value?.stats[s.numberId];
//       return v !== undefined ? { ...s, number: v } : s;
//   });

// Home.vue line 57-58 currently:
//   <template v-else-if="isCoordinator">
//     <HomeShared title="Coordinator" />
//   </template>

// Organization model: type='COOPERATIVE', created_by=user.id
// cooperative_members table: organization_id, user_id, created_at
// active coop hash from: user.value?.settings?.cooperatives[0]
```

## notes
- dictionary: `ai-docs/dictionary.md`
- linters: none detected
- constraints: No `bg-white`/`bg-light`/`text-dark` hardcoding; use theme CSS vars. Leaflet map is lazy (only init when `showMap=true`). All icon URLs must use CDN pattern already established in the project. COORDINATOR must appear in `allowedUserTypes` for coop pages.
