import type { ReactNode } from 'react'
import type { HomeQuickNavGroupId } from './exploreActionPhases'
import { CAUSES } from './causes'
const S = '#2d6b65'
function Ico({ children, stroke = S }: { children: ReactNode; stroke?: string }) {
return (
)
}
export const flyoutIcons = {
roads: (stroke = S) => (
),
schools: (stroke = S) => (
),
safety: (stroke = S) => (
),
family: (stroke = S) => (
),
health: (stroke = S) => (
),
other: (stroke = S) => (
),
person: (stroke = S) => (
),
globe: (stroke = S) => (
),
people: (stroke = S) => (
),
target: (stroke = S) => (
),
building: (stroke = S) => (
),
capitol: (stroke = S) => (
),
dollar: (stroke = S) => (
),
phone: (stroke = S) => (
),
vote: (stroke = S) => (
),
monitor: (stroke = S) => (
),
calendar: (stroke = S) => (
),
bell: (stroke = S) => (
),
database: (stroke = S) => (
),
lightning: (stroke = S) => (
),
code: (stroke = S) => (
),
globeAlt: (stroke = S) => (
),
} as const
export type FlyoutIconKey = keyof typeof flyoutIcons
export type HomeFlyoutItem = {
id: string
label: string
description: string
tag: string
hot?: boolean
to: string
external?: boolean
iconKey: FlyoutIconKey
}
function apiDocsUrl(): string {
return import.meta.env.PROD ? 'https://www.communityone.com/api/docs' : 'http://localhost:8001/docs'
}
function causesToReportFlyoutItems(): HomeFlyoutItem[] {
return CAUSES.map((c) => ({
id: c.id,
iconKey: c.iconKey,
label: c.label,
description: c.desc,
tag: c.tag,
hot: c.hot,
to: c.to,
external: c.to.startsWith('http'),
}))
}
export const HOME_QUICK_NAV_FLYOUTS: Record = {
cause: causesToReportFlyoutItems(),
plan: [
{
id: 'personal',
iconKey: 'person',
label: 'Personal Path',
description: 'I need help — find services and information for me',
tag: 'For me',
to: '/services',
},
{
id: 'macro',
iconKey: 'globe',
label: 'Macro Path',
description: 'I want to create change in my community',
tag: 'For my community',
hot: true,
to: '/explore',
},
{
id: 'professional',
iconKey: 'capitol',
label: 'Professional Path',
description: 'State legislators, county administrators, and nonprofit champions',
tag: 'For my role',
to: '/explore#explore-plan-path',
},
{
id: 'allies',
iconKey: 'people',
label: 'Identify Allies',
description: 'Find officials, nonprofits, and neighbors fighting for your cause',
tag: 'Strategy',
to: '/people',
},
{
id: 'success',
iconKey: 'target',
label: 'Define Success',
description: 'Set measurable goals and track your progress',
tag: 'Outcomes',
to: '/analytics',
},
],
find: [
{
id: 'np',
iconKey: 'building',
label: 'Nonprofits Near Me',
description: '1.8M organizations mapped across 5 states',
tag: 'Free',
to: '/nonprofits',
},
{
id: 'officials',
iconKey: 'capitol',
label: 'Elected Officials',
description: 'Voting records, contact info, decision patterns',
tag: '75K+ leaders',
to: '/people',
},
{
id: 'grants',
iconKey: 'dollar',
label: 'Grants & Funding',
description: 'Federal, state, and foundation opportunities',
tag: '1,000s available',
// Grants search: historical 990 grantmaking + open Grants.gov funding.
// (The bare /opportunities route is the unrelated advocacy-opportunities page.)
to: '/search?types=grants,grant_opportunities',
},
{
id: 'svc',
iconKey: 'phone',
label: 'Community Services',
description: 'Government services, hotlines, local resources',
tag: 'Services',
to: '/services',
},
],
track: [
{
id: 'vote',
iconKey: 'vote',
label: 'Vote Tracker',
description: 'How officials voted on issues that matter to you',
tag: 'Real-time',
hot: true,
to: '/documents',
},
{
id: 'budget',
iconKey: 'monitor',
label: 'Budget Watch',
description: 'Flag when line items shift year over year',
tag: 'Analysis',
to: '/analytics',
},
{
id: 'meetings',
iconKey: 'calendar',
label: 'Upcoming Meetings',
description: 'Agendas, dates, how to attend or comment',
tag: '90K+ jurisdictions',
to: '/events',
},
{
id: 'alerts',
iconKey: 'bell',
label: 'Set Alerts',
description: 'Get notified when your keywords hit an agenda',
tag: 'Free',
to: '/search',
},
],
build: [
{
id: 'data-explorer',
iconKey: 'globeAlt',
label: 'Explore data',
description: 'ACS map and scorecard — national, state, and place trends',
tag: 'Interactive',
hot: true,
to: '/data-explorer',
},
{
id: 'hf',
iconKey: 'database',
label: 'HuggingFace Datasets',
description: 'Meeting transcripts, legislation — MIT license',
tag: 'Open source',
hot: true,
to: 'https://huggingface.co/datasets/CommunityOne/open-navigator-data',
external: true,
},
{
id: 'playbooks',
iconKey: 'lightning',
label: 'Strategy Playbooks',
description: 'Fork civic tools: vote tracker, meeting monitor',
tag: 'GitHub',
to: '/opensource',
},
{
id: 'api',
iconKey: 'code',
label: 'API Reference',
description: 'Query jurisdictions, decisions, and nonprofits',
tag: 'Developers',
to: '__API_DOCS__',
external: true,
},
{
id: 'ecosystem',
iconKey: 'globeAlt',
label: 'Civic Tech Ecosystem',
description: 'Code for America, OpenStates, MySociety',
tag: 'Community',
to: 'https://www.openstates.org/',
external: true,
},
],
}
/** Resolve special `to` tokens after import.meta is available */
export function resolveHomeFlyoutHref(to: string): string {
if (to === '__API_DOCS__') return apiDocsUrl()
return to
}
export function homeQuickNavFlyoutItems(id: HomeQuickNavGroupId): HomeFlyoutItem[] {
return HOME_QUICK_NAV_FLYOUTS[id]
}