Files
BarangaySystem/.claude/plans/db3f8841a2ce6fbe5c0279ccba883ec9-complete.md
2026-06-06 18:43:00 +08:00

8.3 KiB

task, cycles, context, private, started, finished
task cycles context private started finished
Redesign HomeCooperative.vue into a proper Coordinator/Cooperative-user dashboard and wire it into Home.vue 5 true false 2026-05-16T00:00:00Z 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.jsfetchPageData(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.