Skip to main content

Knowledge > Processes > Admin Dashboard Load Flow

Admin Dashboard Load Flow

How the admin dashboard at /admin/[token] authenticates, loads data, and renders tabs. Both CWA and PewSearch dashboards follow the same pattern with different tab sets.


Step 1: Token Resolution

Admin visits /admin/{token} where token is a UUID.

FUNCTION resolveToken(token: string) -> ResolvedToken | null

PATH A: Check admin_token
query premium_churches
WHERE admin_token = token
SELECT (safe columns), churches.* via FK join
IF found:
RETURN { premium, church, role: "admin", memberName: null }

PATH B: Check team member access_token
query church_team_members
WHERE access_token = token AND is_active = true
SELECT id, premium_id, role, name
IF found:
UPDATE church_team_members SET last_accessed_at = now()
WHERE id = member.id (fire-and-forget)
query premium_churches WHERE id = member.premium_id
with churches FK join
RETURN { premium, church, role: member.role, memberName: member.name }

PATH C: Cookie-based auth (resolveTokenOrHeaders)
IF x-church-id AND x-identity-id headers present (set by middleware):
query premium_churches WHERE church_id = x-church-id
query church_admin_identities WHERE id = x-identity-id for name
RETURN { premium, church, role: x-identity-role, memberName }

IF none matched:
RETURN null → notFound() (404 page)

Step 2: Parallel Data Loading (CWA Dashboard)

After authentication, the server component loads all dashboard data in parallel using Promise.all().

const [
voiceAgent, // church_voice_agents: pastor_name, settings, phone config
metrics, // getDashboardMetrics: call count, prayer count, visitor count
activity, // getRecentActivity: last 20 events across all types (role-filtered)
callsResult, // getCallLogsByChurch: page 0 of call logs
prayerResult, // getRequestsByType("prayer"): prayer requests (role-gated)
visitorResult, // getRequestsByType("visitor"): visitor contacts (role-gated)
callbackResult, // getRequestsByType("callback"): callback requests (role-gated)
careMemberCount, // getCareMemberCount: count of care subscribers
toolUsage, // getToolUsageCounts: chatbot tool usage stats
agentConversations, // getAgentConversationCounts: per-agent conversation counts
orgSettingsResult, // organization_settings: agent_config, agent_tool_config
] = await Promise.all([...11 queries...])

ALSO (CWA only):
hasBackupOwner = query church_admin_identities
WHERE church_id AND is_backup_owner = true AND is_active = true
COUNT > 0 (graceful — catches error if table doesn't exist)

PewSearch Dashboard (simpler variant)

const [
voiceAgent, // church_voice_agents
metrics, // getDashboardMetrics
activity, // getRecentActivity (no role filter in PS version)
callsResult, // page 0 of call logs
prayerResult, // prayer requests (role-gated)
visitorResult, // visitor contacts (role-gated)
callbackResult, // callback requests (role-gated)
chatbotFaqs, // canned_responses WHERE source = "pewsearch_admin"
documentCount, // church_knowledge_base COUNT
careMemberCount, // care subscriber count
] = await Promise.all([...10 queries...])

SECURITY: PewSearch strips admin_token before passing to client:
const { admin_token: _at, ...safePremium } = premium;
Team member access_tokens also stripped from SafeTeamMember

Step 3: Role-Based Tab Filtering

The ROLE_TABS matrix determines which tabs each role can see. Tier restrictions further filter the list.

ROLE_TABS (CWA):
admin: overview, calls, requests, care, training, social, settings, upgrade
office_admin: overview, calls, requests, care, training, social, settings
prayer_team: overview, requests
care_team: overview, requests, care
treasurer: overview
volunteer_coordinator: overview, requests
worship_leader: overview
spiritual_leader: overview, training
care_leader: overview, training

TIER FILTERING (additional restrictions):
free tier: only overview, training, settings, upgrade
ps_pro_website: overview, requests, website, settings, upgrade (no calls)
paid CWA tiers: full role tab list

RESULT: visibleTabs = intersect(ROLE_TABS[role], TIER_ALLOWED_TABS[plan])

Step 4: Tab Content Rendering

Each tab renders its own data, already loaded in step 2.

OVERVIEW TAB (DashboardOverview):
- Metric cards: total calls, prayers, visitors, callbacks
- Activity feed: recent events chronologically
- Completeness donut: profile training completion %
- Founder action banners (if applicable)

CALLS TAB (CallHistory):
- Paginated call log list
- Expandable transcript viewer
- AI-generated call summary + classification
- Category, urgency, sentiment badges

REQUESTS TAB (RequestManager):
- Four sub-tabs: Prayer, Visitors, Callbacks, Safety
- Safety sub-tab (4th): renders ModerationDashboard — visible to admin/office_admin only
- Shows violations from moderation_violations + active blocks from user_restrictions
- Red badge on Requests tab when safety flags exist (counted from moderation_violations)
- SAFETY FLAG [ pattern entries are EXCLUDED from the Callbacks sub-tab
- Role-gated: PASTORAL_ROLES see full text
- Other roles see redacted: "Confidential — contact the pastor"
- Status toggles: new → reviewed → resolved
- URL routing: ?tab=safety and ?tab=moderation both route to the Requests tab (Safety sub-tab)

CARE TAB (CareTab):
- Care toggle (enable/disable)
- Member list with contact info
- Broadcast composer (email + SMS)

TRAINING TAB (now labelled "Staff Practice" in the UI):
- 10-step guided setup wizard — shown until all steps are complete
- Tool management panels (Agents sub-tab) — enable/disable individual AI tools
- Pastor Pulse (weekly sermon topic, series, theme verse, announcement)
- Hours editor
- Staff editor (CRUD with photo upload)
- Ministries editor
- What to Expect editor
- FAQ/canned response editor
- Document upload (knowledge base)
- Staff Practice (formerly "Simulator") — pastoral coaching scenarios, HEAR framework scoring
- ROLE_TRAINING gates which sections each role can edit
- Settings sub-tab selection persists in URL hash

SETTINGS TAB (SettingsTab):
- Basic info, contact, voice config, chatbot config
- Team member management (admin only)
- Integration settings
- ROLE_SETTINGS gates which sections each role can edit

UPGRADE TAB (UpgradeTab):
- Current plan display
- Stripe billing portal link
- Upgrade CTA with plan comparison

WEBSITE TAB (PewSearch only, pro_website plan):
- Design: hero video, template, logo, slideshow
- Content: hours, staff, sermons, events, beliefs, giving, care
- Settings: vanity slug, contact email

Security Invariants

1. Token NEVER sent to client component (stripped before serialization)
2. All data loading happens server-side (React Server Components)
3. Role checks happen at BOTH UI level (tab visibility) AND API level (mutation routes)
4. Confidential data (prayer text, callback reasons) redacted for non-PASTORAL_ROLES
5. Financial data (giving, budget) only visible to FINANCIAL_ROLES (admin, treasurer)
6. Admin pages marked: robots: "noindex", dynamic: "force-dynamic" (no caching)