Objective
Build a completely separate home screen for the agency owner (super admin). This is NOT a caregiving screen — it's a MANAGEMENT overview. The owner needs to see: who's on shift, what needs attention, and quick actions to manage their team.
Constraints
- •ONLY shown when
subscription.plan === 'multi-agency' && user.role === 'super_admin' - •DO NOT modify GuidedHome — this is a SEPARATE component
- •DO NOT create new Firestore collections — read from existing ones
- •MUST reuse layout components (MinimalHeader, BottomNav/IconRail)
- •MUST use existing data hooks and Firestore queries where possible
- •MUST use Lucide React icons, shadcn/ui components, Tailwind classes
- •NO avatar in header, NO bell in header (same rules as all screens)
- •Bottom nav for owner: Home, Team, Schedule, Bell (with badge), More
- •Time displays use formatTimeDistance() — NEVER raw minutes
Files to Read First
- •
src/app/dashboard/page.tsx— Where conditional rendering goes - •
src/types/index.ts— Agency, CaregiverAssignment, ScheduledShift, ShiftSession interfaces - •
src/hooks/useAgency.ts— If exists, agency data fetching - •
src/app/dashboard/caregivers/page.tsx— Existing caregiver list page - •
src/app/dashboard/scheduling/page.tsx— Existing scheduling page - •
src/lib/firebase/firestore.ts— Existing Firestore query patterns - •
src/contexts/AuthContext.tsx— User role access - •
src/lib/subscription.ts— Subscription plan detection
Component Architecture
AgencyOwnerDashboard ├── AgencyGreeting (name + agency name) ├── AgencyQuickStats (3 stat cards) ├── NeedsAttentionList (alert cards) ├── ManageActionGrid (2x2 action buttons) └── TodaysShiftsList (shift cards)
Implementation Steps
Step 1: Create AgencyOwnerDashboard
Create src/components/dashboard/AgencyOwnerDashboard.tsx:
'use client';
import { useAuth } from '@/contexts/AuthContext';
import { useSubscription } from '@/lib/subscription';
import { AgencyGreeting } from '@/components/agency/AgencyGreeting';
import { AgencyQuickStats } from '@/components/agency/AgencyQuickStats';
import { NeedsAttentionList } from '@/components/agency/NeedsAttentionList';
import { ManageActionGrid } from '@/components/agency/ManageActionGrid';
import { TodaysShiftsList } from '@/components/agency/TodaysShiftsList';
export function AgencyOwnerDashboard() {
return (
<div className="flex flex-col gap-6 px-4 py-4 max-w-2xl mx-auto">
<AgencyGreeting />
<AgencyQuickStats />
<NeedsAttentionList />
<ManageActionGrid />
<TodaysShiftsList />
</div>
);
}
Step 2: Create AgencyGreeting
Create src/components/agency/AgencyGreeting.tsx:
Props: none (reads from AuthContext)
Display:
- "Hi {firstName}" — 24px semibold
- "{agencyName}" — 16px regular, secondary color
- Agency name from user's agency document in Firestore
Data: user.agencyId → fetch agency document → agency.name
Step 3: Create AgencyQuickStats
Create src/components/agency/AgencyQuickStats.tsx:
Display: 3 stat cards in horizontal row (flex, gap-3) Card 1: Caregivers - Count of active caregiver_assignments where agencyId matches - Icon: Users (blue) Card 2: Elders - Count of elders assigned to this agency - Icon: Heart (rose) Card 3: Pending Slots - Count of scheduledShifts where status === 'pending' (awaiting response) - Icon: Clock (amber) Each card: shadcn Card component, compact (80px height) - Large number (24px bold) - Label below (12px, secondary color) - Icon top-right corner (16px, muted)
Step 4: Create NeedsAttentionList
Create src/components/agency/NeedsAttentionList.tsx:
Purpose: Show issues that need the owner's action Scans for: 1. Uncovered shifts (scheduledShifts where date is upcoming AND no caregiver assigned) 2. Elders without caregiver assignment 3. Caregivers with low compliance (<70% today) 4. Shifts with no response (sent but not accepted/rejected) Display per item: ┌─────────────────────────────────────────┐ │ [AlertTriangle] 2 slots awaiting > │ │ response │ └─────────────────────────────────────────┘ - Icon color: amber for warnings, red for urgent - Chevron right → navigates to relevant page - Max 3 shown, "View all" button if more - Empty state: green CheckCircle + "All good! No issues right now."
Step 5: Create ManageActionGrid
Create src/components/agency/ManageActionGrid.tsx:
Display: 2x2 grid of action cards 1. Assign Elder - Icon: UserPlus - Navigate: /dashboard/caregivers (with assign modal pre-opened) 2. Send Slots - Icon: CalendarPlus - Navigate: /dashboard/scheduling/create 3. Onboard Caregiver - Icon: UserCheck - Navigate: /dashboard/caregivers/invite 4. Create Schedule - Icon: Calendar - Navigate: /dashboard/scheduling Each card: - 48px icon (centered, muted color) - Label below (14px, center-aligned) - Tap: navigate to action - Subtle border, rounded-lg, hover:bg-gray-50
Step 6: Create TodaysShiftsList
Create src/components/agency/TodaysShiftsList.tsx:
Purpose: Show all shifts scheduled for today Data: scheduledShifts where date = today, joined with caregiver names and elder names Display per shift: ┌─────────────────────────────────────────┐ │ Sarah J. │ Martha, John │ [Active] │ │ 7AM-3PM │ │ [green] │ └─────────────────────────────────────────┘ Columns: caregiver name | assigned elders | status badge Status badges: - Active (green) — currently on shift - Upcoming (gray) — shift hasn't started - Completed (blue) — shift ended - Missed (red) — shift time passed, no clock-in Tap row → navigate to caregiver detail view Empty state: "No shifts scheduled today" + [Create Schedule] button
Step 7: Wire into Dashboard Page
Modify src/app/dashboard/page.tsx:
// Add at top of component:
const { isMultiAgency } = useSubscription();
const isSuperAdmin = user?.role === 'super_admin' || user?.role === 'agency_owner';
// Conditional rendering:
if (isMultiAgency && isSuperAdmin) {
return <AgencyOwnerDashboard />;
}
Step 8: Owner-Specific Bottom Nav
The bottom nav items for super admin (handled in BottomNav component):
if (isMultiAgency && isSuperAdmin) {
return [
{ icon: House, label: 'Home', href: '/dashboard' },
{ icon: Users, label: 'Team', href: '/dashboard/caregivers' },
{ icon: Calendar, label: 'Schedule', href: '/dashboard/scheduling' },
{ icon: Bell, label: 'Alerts', badge: unreadCount }, // Opens notification dropdown
{ icon: Menu, label: 'More' },
];
}
Note: "Team" (NOT "Staff") — matches the mockup exactly.
Step 9: Owner-Specific Icon Rail (Desktop)
TOP: 1. Home (House) 2. Team (Users) — /dashboard/caregivers 3. Schedule (Calendar) — /dashboard/scheduling 4. Elders (Heart) — /dashboard/elder-profile 5. Reports (FileText) — /dashboard/analytics 6. Timesheets (Clock) — /dashboard/timesheet 7. More (Menu) BOTTOM (after spacer): 8. Bell (with badge) 9. Avatar (profile/settings/sign-out)
Testing Requirements
- •Super Admin sees AgencyOwnerDashboard, NOT GuidedHome
- •AgencyQuickStats shows correct counts from Firestore
- •NeedsAttentionList correctly identifies issues
- •ManageActionGrid navigates to correct pages
- •TodaysShiftsList shows today's shifts accurately
- •Bottom nav shows "Team" for super admin
- •Icon rail shows agency-specific items on desktop
- •Family plan users are completely unaffected
- •Agency caregivers (non-admin) still see GuidedHome with elder tabs
- •All existing tests pass
- •Build succeeds
- •Run:
npm test -- --testPathPattern="agency|Agency|dashboard"