Spaces:
Sleeping
Sleeping
Download frontend/src/components/AppLayout.tsx from BrainForge/AdvisoryBuilderWorkshop: direct link, hf CLI and curl.
- Browser
- Download file 6.51 kB
-
https://huggingface.co/spaces/BrainForge/AdvisoryBuilderWorkshop/resolve/main/frontend/src/components/AppLayout.tsx
- Command line
-
hf download hf://spaces/BrainForge/AdvisoryBuilderWorkshop/frontend/src/components/AppLayout.tsx
-
curl -L -o AppLayout.tsx https://huggingface.co/spaces/BrainForge/AdvisoryBuilderWorkshop/resolve/main/frontend/src/components/AppLayout.tsx
6.51 kB
| import { Outlet, Link, useLocation } from 'react-router-dom' | |
| import { useState } from 'react' | |
| import { useAuth } from '../context/AuthContext' | |
| import { UserMenu } from './UserMenu' | |
| import { SaveWarningBar } from './SaveWarningBar' | |
| import { ProfileModal } from './ProfileModal' | |
| import { AccountModal } from './AccountModal' | |
| import { ClearDataModal } from './ClearDataModal' | |
| import { PersonaPromptBuildHost } from './PersonaPromptBuildHost' | |
| import { AdvisorPanelBuildHost } from './AdvisorPanelBuildHost' | |
| import { WorkshopTutorialHost } from './WorkshopTutorialHost' | |
| import { HeaderNavDropdown } from './HeaderNavDropdown' | |
| import { SiteFooter } from './SiteFooter' | |
| function headerNavLinkClass(active: boolean) { | |
| return `header-nav-link${active ? ' header-nav-link--current' : ''}` | |
| } | |
| /** Soft “you are here” label in the site header (not a second competing headline). */ | |
| function headerPageContext(pathname: string): string | null { | |
| /* Experiment pages omit header context — each page has its own H1. */ | |
| if (pathname === '/experiment' || pathname === '/experiment-advisor') return null | |
| if (pathname.startsWith('/create-persona')) return 'Create a Persona' | |
| if (pathname.startsWith('/create-advisor')) return 'Create an Advisor Panel' | |
| if (pathname === '/workshop/manage') return 'Manage creations' | |
| if (/^\/persona\/[^/]+\/summary/.test(pathname)) return 'Persona summary' | |
| if (/^\/advisor\/[^/]+\/summary/.test(pathname)) return 'Advisor summary' | |
| return null | |
| } | |
| const PERSONA_NAV_ITEMS = [ | |
| { to: '/persona', label: 'Persona Workshop' }, | |
| { to: '/create-persona/form', label: 'Create a Persona — form' }, | |
| { to: '/create-persona/chat', label: 'Create a Persona — Interactive Q&A' }, | |
| { to: '/experiment', label: 'Experiment with Persona Prompts' }, | |
| { to: '/workshop/manage', label: 'Manage Personas and Advisory Panels' }, | |
| ] as const | |
| const ADVISOR_NAV_ITEMS = [ | |
| { to: '/advisor', label: 'Advisor Panel Workshop' }, | |
| { to: '/create-advisor/form', label: 'Create an Advisor Panel — form' }, | |
| { to: '/create-advisor/chat', label: 'Create an Advisor Panel — Interactive Q&A' }, | |
| { to: '/experiment-advisor', label: 'Experiment with Advisor Panels' }, | |
| { to: '/workshop/manage', label: 'Manage Personas and Advisory Panels' }, | |
| ] as const | |
| export function AppLayout() { | |
| const { pathname } = useLocation() | |
| const { user, loading } = useAuth() | |
| const [profile, setProfile] = useState(false) | |
| const [account, setAccount] = useState(false) | |
| const [clear, setClear] = useState(false) | |
| const [pinnedMenu, setPinnedMenu] = useState<'persona' | 'advisor' | null>(null) | |
| const showSaveBanner = !loading && !user | |
| const pageContext = headerPageContext(pathname) | |
| const suppressLayoutFooter = | |
| pathname === '/experiment' || pathname === '/experiment-advisor' | |
| const homeActive = pathname === '/' | |
| const personaActive = | |
| pathname === '/persona' || | |
| pathname.startsWith('/persona/') || | |
| pathname.startsWith('/create-persona') || | |
| pathname === '/experiment' | |
| const advisorActive = | |
| pathname === '/advisor' || | |
| pathname.startsWith('/advisor/') || | |
| pathname.startsWith('/create-advisor') || | |
| pathname === '/experiment-advisor' | |
| return ( | |
| <div | |
| className={`layout-main${showSaveBanner ? ' layout-main--save-banner' : ''}`} | |
| > | |
| <header className="header-bar"> | |
| <div className="header-bar-brand"> | |
| <div className="header-brand-lockup"> | |
| <a | |
| href="https://neon.ai" | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="header-brand-logo-link" | |
| title="Neon.ai — the company behind this workshop" | |
| > | |
| <img | |
| src="/neon-logo.png" | |
| alt="Neon.ai" | |
| className="header-brand-logo" | |
| /> | |
| </a> | |
| <Link to="/" className="header-brand" title="AI Expert Advisory Builder's Workshop"> | |
| <span className="header-brand-kicker">AI Expert Advisory</span> | |
| <span className="header-brand-name">Builder's Workshop</span> | |
| </Link> | |
| <a | |
| href="https://neon.ai" | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="header-maker" | |
| title="Neon.ai — the company behind this workshop" | |
| > | |
| <span className="header-maker-label">by</span> | |
| <span className="header-maker-name">Neon.ai</span> | |
| </a> | |
| </div> | |
| {pageContext && ( | |
| <p className="header-page-context"> | |
| <span className="header-page-context-label">Now viewing</span> | |
| <span className="header-page-context-value">{pageContext}</span> | |
| </p> | |
| )} | |
| </div> | |
| <nav className="header-bar-nav" aria-label="Main"> | |
| <Link | |
| to="/" | |
| className={headerNavLinkClass(homeActive)} | |
| aria-current={homeActive ? 'page' : undefined} | |
| > | |
| Home | |
| </Link> | |
| <HeaderNavDropdown | |
| label="Personas" | |
| active={personaActive} | |
| items={[...PERSONA_NAV_ITEMS]} | |
| pinnedOpen={pinnedMenu === 'persona'} | |
| onPinnedChange={(pinned) => setPinnedMenu(pinned ? 'persona' : null)} | |
| /> | |
| <HeaderNavDropdown | |
| label="Advisor Panels" | |
| active={advisorActive} | |
| items={[...ADVISOR_NAV_ITEMS]} | |
| pinnedOpen={pinnedMenu === 'advisor'} | |
| onPinnedChange={(pinned) => setPinnedMenu(pinned ? 'advisor' : null)} | |
| /> | |
| </nav> | |
| <div className="header-bar-tools"> | |
| <UserMenu | |
| onProfile={() => setProfile(true)} | |
| onAccount={() => setAccount(true)} | |
| onClearData={() => setClear(true)} | |
| /> | |
| </div> | |
| </header> | |
| <PersonaPromptBuildHost /> | |
| <AdvisorPanelBuildHost /> | |
| <div className="layout-body"> | |
| <Outlet /> | |
| </div> | |
| {!suppressLayoutFooter && <SiteFooter />} | |
| <WorkshopTutorialHost /> | |
| <SaveWarningBar /> | |
| {profile && <ProfileModal onClose={() => setProfile(false)} />} | |
| {account && <AccountModal onClose={() => setAccount(false)} />} | |
| {clear && <ClearDataModal onClose={() => setClear(false)} />} | |
| </div> | |
| ) | |
| } | |