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
104 lines
3.4 KiB
TypeScript
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}`}`
|
|
}
|
|
}
|