0bacd188d6
AppShell.tsx: 627→116 lines - appShellConfig.ts: NavItem/WorkspaceConfig types, WORKSPACE_CONFIG, nav helpers - AppShellSidebar.tsx: Sidebar component with visual constants - AppShellTopBar.tsx: TopBar component Match-detail panels: - ScoreBreakdownPanel: 377→303 lines (scoreBreakdownConstants.ts + CriterionRow.tsx extracted) - LocationIntelligencePanel: 383→333 lines (SoftFactorBar.tsx extracted) - FutureAvailabilityContextPanel: 386→351 lines (futureAvailabilityConstants.tsx extracted) Compare.tsx: 485→441 lines - useCompareData hook: all queries and derived state extracted to hooks/useCompareData.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
93 lines
2.9 KiB
TypeScript
93 lines
2.9 KiB
TypeScript
import { Box, Typography, Chip, Button, IconButton } from '@mui/material'
|
|
import { Sparkles, Menu } from 'lucide-react'
|
|
import { WorkspaceType } from '../../domain/enums'
|
|
import { useAssistantStore } from '../../stores/assistantStore'
|
|
import { OrganizationContextBadge } from './OrganizationContextBadge'
|
|
import { NotificationButton } from './NotificationButton'
|
|
import { UserMenu } from './UserMenu'
|
|
import { WORKSPACE_CONFIG, getPageNameFromPath } from './appShellConfig'
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Types
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface TopBarProps {
|
|
activeWorkspace: WorkspaceType
|
|
pathname: string
|
|
onMenuClick?: () => void
|
|
isMobile?: boolean
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Component
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export function TopBar({ activeWorkspace, pathname, onMenuClick, isMobile }: TopBarProps) {
|
|
const config = WORKSPACE_CONFIG[activeWorkspace]
|
|
const pageName = getPageNameFromPath(pathname)
|
|
const openAssistant = useAssistantStore(s => s.open)
|
|
|
|
return (
|
|
<Box
|
|
component="header"
|
|
sx={{
|
|
height: 56,
|
|
flexShrink: 0,
|
|
backgroundColor: '#ffffff',
|
|
borderBottom: '1px solid #e2e8f0',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
px: { xs: 1.5, sm: 3 },
|
|
}}
|
|
>
|
|
{/* Left side */}
|
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
{isMobile && (
|
|
<IconButton size="small" onClick={onMenuClick} sx={{ mr: 0.5 }}>
|
|
<Menu size={20} />
|
|
</IconButton>
|
|
)}
|
|
<Chip
|
|
label={config.label}
|
|
size="small"
|
|
sx={{
|
|
backgroundColor: config.chipColor,
|
|
color: '#ffffff',
|
|
fontWeight: 600,
|
|
fontSize: '0.7rem',
|
|
height: 22,
|
|
}}
|
|
/>
|
|
<Typography
|
|
variant="body1"
|
|
sx={{ fontWeight: 500, color: '#1e293b', fontSize: { xs: '0.85rem', sm: '0.9375rem' } }}
|
|
>
|
|
{pageName}
|
|
</Typography>
|
|
</Box>
|
|
|
|
{/* Right side */}
|
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: { xs: 0.5, sm: 1 } }}>
|
|
<Box sx={{ display: { xs: 'none', sm: 'flex' } }}>
|
|
<OrganizationContextBadge />
|
|
</Box>
|
|
<Button
|
|
variant="outlined"
|
|
size="small"
|
|
startIcon={<Sparkles size={14} />}
|
|
onClick={openAssistant}
|
|
sx={{ textTransform: 'none', fontSize: '0.8125rem', display: { xs: 'none', md: 'flex' } }}
|
|
>
|
|
AI Assistent
|
|
</Button>
|
|
<IconButton size="small" onClick={openAssistant} sx={{ display: { xs: 'flex', md: 'none' } }}>
|
|
<Sparkles size={18} />
|
|
</IconButton>
|
|
<NotificationButton />
|
|
<UserMenu />
|
|
</Box>
|
|
</Box>
|
|
)
|
|
}
|