Spaces:
Sleeping
Sleeping
| import React from 'react'; | |
| import { Button } from './ui/button'; | |
| import { Menu, Sun, Moon, Languages, ChevronDown } from 'lucide-react'; | |
| import { | |
| DropdownMenu, | |
| DropdownMenuContent, | |
| DropdownMenuItem, | |
| DropdownMenuTrigger, | |
| } from './ui/dropdown-menu'; | |
| import clareAvatar from '../assets/dfe44dab3ad8cd93953eac4a3e68bd1a5f999653.png'; | |
| import type { Workspace } from '../App'; | |
| interface HeaderProps { | |
| user: UserType | null; | |
| onMenuClick: () => void; | |
| onUserClick: () => void; | |
| isDarkMode: boolean; | |
| onToggleDarkMode: () => void; | |
| language: Language; | |
| onLanguageChange: (lang: Language) => void; | |
| workspaces: Workspace[]; | |
| currentWorkspace: Workspace | undefined; | |
| onWorkspaceChange: (workspaceId: string) => void; | |
| } | |
| type UserType = { | |
| name: string; | |
| email: string; | |
| }; | |
| type Language = 'auto' | 'en' | 'zh'; | |
| export function Header({ | |
| user, | |
| onMenuClick, | |
| onUserClick, | |
| isDarkMode, | |
| onToggleDarkMode, | |
| language, | |
| onLanguageChange, | |
| workspaces, | |
| currentWorkspace, | |
| onWorkspaceChange, | |
| }: HeaderProps) { | |
| const languageLabels = { | |
| auto: 'Auto', | |
| en: 'English', | |
| zh: '简体中文', | |
| }; | |
| return ( | |
| <header className="h-16 border-b border-border bg-card px-4 lg:px-6 flex items-center justify-between sticky top-0 z-[100]"> | |
| <div className="flex items-center gap-4"> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="lg:hidden" | |
| onClick={onMenuClick} | |
| > | |
| <Menu className="h-5 w-5" /> | |
| </Button> | |
| <div className="flex items-center gap-3"> | |
| <div className="w-10 h-10 rounded-full overflow-hidden bg-white flex items-center justify-center"> | |
| <img src={clareAvatar} alt="Clare AI" className="w-full h-full object-cover" /> | |
| </div> | |
| <div> | |
| <h1 className="text-lg sm:text-xl tracking-tight"> | |
| Clare <span className="text-sm font-bold text-muted-foreground hidden sm:inline ml-2">Your Personalized AI Tutor</span> | |
| </h1> | |
| <p className="text-xs text-muted-foreground hidden sm:block"> | |
| Personalized guidance, review, and intelligent reinforcement | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| <div className="flex items-center gap-2"> | |
| <DropdownMenu> | |
| <DropdownMenuTrigger asChild> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| aria-label="Change language" | |
| > | |
| <Languages className="h-5 w-5" /> | |
| </Button> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuContent align="end"> | |
| <DropdownMenuItem onClick={() => onLanguageChange('auto')}> | |
| {language === 'auto' && '✓ '}Auto | |
| </DropdownMenuItem> | |
| <DropdownMenuItem onClick={() => onLanguageChange('en')}> | |
| {language === 'en' && '✓ '}English | |
| </DropdownMenuItem> | |
| <DropdownMenuItem onClick={() => onLanguageChange('zh')}> | |
| {language === 'zh' && '✓ '}简体中文 | |
| </DropdownMenuItem> | |
| </DropdownMenuContent> | |
| </DropdownMenu> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| onClick={onToggleDarkMode} | |
| aria-label="Toggle dark mode" | |
| > | |
| {isDarkMode ? <Sun className="h-5 w-5" /> : <Moon className="h-5 w-5" />} | |
| </Button> | |
| {user && currentWorkspace ? ( | |
| <DropdownMenu> | |
| <DropdownMenuTrigger asChild> | |
| <Button | |
| variant="outline" | |
| className="gap-2 pl-2 pr-3" | |
| aria-label="Switch workspace" | |
| > | |
| <img | |
| src={currentWorkspace.avatar} | |
| alt={currentWorkspace.name} | |
| className="w-6 h-6 rounded-full object-cover" | |
| /> | |
| <span className="hidden sm:inline max-w-[120px] truncate">{currentWorkspace.name}</span> | |
| <ChevronDown className="h-4 w-4 opacity-50" /> | |
| </Button> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuContent align="end" className="min-w-[14rem]"> | |
| {workspaces.map((workspace) => ( | |
| <DropdownMenuItem | |
| key={workspace.id} | |
| onClick={() => onWorkspaceChange(workspace.id)} | |
| className={`gap-3 ${currentWorkspace.id === workspace.id ? 'bg-accent' : ''}`} | |
| > | |
| <img | |
| src={workspace.avatar} | |
| alt={workspace.name} | |
| className="w-6 h-6 rounded-full object-cover flex-shrink-0" | |
| /> | |
| <span className="truncate">{workspace.name}</span> | |
| {currentWorkspace.id === workspace.id && ( | |
| <span className="ml-auto text-primary">✓</span> | |
| )} | |
| </DropdownMenuItem> | |
| ))} | |
| </DropdownMenuContent> | |
| </DropdownMenu> | |
| ) : null} | |
| </div> | |
| </header> | |
| ); | |
| } |