fediversion/frontend/contexts/vertical-context.tsx
fullsizemalt 29c5d30ebb feat: Add multi-vertical frontend infrastructure
Phase 3 - Frontend Multi-Vertical Support:
- Add VerticalContext for band state management
- Add BandSelector dropdown component
- Create dynamic [vertical] routes for shows, songs, venues
- Update navbar to use band selector and vertical-aware links
- Update api-config.ts for Fediversion domain
- Rebrand from Elmeg to Fediversion
2025-12-28 13:56:22 -08:00

104 lines
3.4 KiB
TypeScript

"use client"
import { createContext, useContext, useState, useEffect, ReactNode } from "react"
import { usePathname } from "next/navigation"
// Supported verticals (bands)
export const VERTICALS = [
{ slug: "goose", name: "Goose", emoji: "🦆", color: "#F59E0B" },
{ slug: "phish", name: "Phish", emoji: "🐟", color: "#EF4444" },
{ slug: "grateful-dead", name: "Grateful Dead", emoji: "💀", color: "#8B5CF6" },
{ slug: "dead-and-company", name: "Dead & Company", emoji: "⚡", color: "#3B82F6" },
{ slug: "billy-strings", name: "Billy Strings", emoji: "🎸", color: "#10B981" },
] as const
export type VerticalSlug = typeof VERTICALS[number]["slug"]
export interface Vertical {
slug: VerticalSlug
name: string
emoji: string
color: string
}
interface VerticalContextType {
current: Vertical
setCurrent: (slug: VerticalSlug) => void
all: readonly Vertical[]
}
const VerticalContext = createContext<VerticalContextType | null>(null)
export function VerticalProvider({ children }: { children: ReactNode }) {
const pathname = usePathname()
// Detect vertical from URL path
const getVerticalFromPath = (): Vertical => {
const segments = pathname.split("/").filter(Boolean)
const firstSegment = segments[0]
const found = VERTICALS.find(v => v.slug === firstSegment)
return found || VERTICALS[0] // Default to Goose
}
const [current, setCurrentState] = useState<Vertical>(getVerticalFromPath)
// Update current when path changes
useEffect(() => {
setCurrentState(getVerticalFromPath())
}, [pathname])
const setCurrent = (slug: VerticalSlug) => {
const found = VERTICALS.find(v => v.slug === slug)
if (found) {
setCurrentState(found)
// Store preference
if (typeof window !== "undefined") {
localStorage.setItem("preferred-vertical", slug)
}
}
}
// Load preference on mount
useEffect(() => {
if (typeof window !== "undefined") {
const stored = localStorage.getItem("preferred-vertical") as VerticalSlug | null
if (stored && VERTICALS.find(v => v.slug === stored)) {
// Only set if not already in a vertical-specific route
const segments = pathname.split("/").filter(Boolean)
const isVerticalRoute = VERTICALS.some(v => v.slug === segments[0])
if (!isVerticalRoute) {
setCurrent(stored)
}
}
}
}, [])
return (
<VerticalContext.Provider value={{ current, setCurrent, all: VERTICALS }}>
{children}
</VerticalContext.Provider>
)
}
export function useVertical() {
const context = useContext(VerticalContext)
if (!context) {
throw new Error("useVertical must be used within a VerticalProvider")
}
return context
}
// Helper to build vertical-aware paths
export function useVerticalPath() {
const { current } = useVertical()
return (path: string) => {
// If path already starts with a vertical, return as-is
const segments = path.split("/").filter(Boolean)
if (VERTICALS.some(v => v.slug === segments[0])) {
return path
}
// Prepend current vertical
return `/${current.slug}${path.startsWith("/") ? path : `/${path}`}`
}
}