import { useState, useCallback } from 'react'; import { Button } from '@/components/ui/button'; import { Slider } from '@/components/ui/slider'; import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Bot, Wand2, Settings2, GitBranch } from 'lucide-react'; import { UsagePopover } from '@/components/usage-popover'; import { useAppStore } from '@/store/app-store'; import { useSetupStore } from '@/store/setup-store'; import { useIsMobile } from '@/hooks/use-media-query'; import { AutoModeSettingsDialog } from './dialogs/auto-mode-settings-dialog'; import { WorktreeSettingsDialog } from './dialogs/worktree-settings-dialog'; import { PlanSettingsDialog } from './dialogs/plan-settings-dialog'; import { getHttpApiClient } from '@/lib/http-api-client'; import { BoardSearchBar } from './board-search-bar'; import { BoardControls } from './board-controls'; import { ViewToggle, type ViewMode } from './components'; import { HeaderMobileMenu } from './header-mobile-menu'; export type { ViewMode }; interface BoardHeaderProps { projectPath: string; maxConcurrency: number; runningAgentsCount: number; onConcurrencyChange: (value: number) => void; isAutoModeRunning: boolean; onAutoModeToggle: (enabled: boolean) => void; onOpenPlanDialog: () => void; isMounted: boolean; // Search bar props searchQuery: string; onSearchChange: (query: string) => void; isCreatingSpec: boolean; creatingSpecProjectPath?: string; // Board controls props onShowBoardBackground: () => void; onShowCompletedModal: () => void; completedCount: number; // View toggle props viewMode: ViewMode; onViewModeChange: (mode: ViewMode) => void; } // Shared styles for header control containers const controlContainerClass = 'flex items-center gap-1.5 px-3 h-8 rounded-md bg-secondary border border-border'; export function BoardHeader({ projectPath, maxConcurrency, runningAgentsCount, onConcurrencyChange, isAutoModeRunning, onAutoModeToggle, onOpenPlanDialog, isMounted, searchQuery, onSearchChange, isCreatingSpec, creatingSpecProjectPath, onShowBoardBackground, onShowCompletedModal, completedCount, viewMode, onViewModeChange, }: BoardHeaderProps) { const [showAutoModeSettings, setShowAutoModeSettings] = useState(false); const [showWorktreeSettings, setShowWorktreeSettings] = useState(false); const [showPlanSettings, setShowPlanSettings] = useState(false); const claudeAuthStatus = useSetupStore((state) => state.claudeAuthStatus); const skipVerificationInAutoMode = useAppStore((state) => state.skipVerificationInAutoMode); const setSkipVerificationInAutoMode = useAppStore((state) => state.setSkipVerificationInAutoMode); const planUseSelectedWorktreeBranch = useAppStore((state) => state.planUseSelectedWorktreeBranch); const setPlanUseSelectedWorktreeBranch = useAppStore( (state) => state.setPlanUseSelectedWorktreeBranch ); const addFeatureUseSelectedWorktreeBranch = useAppStore( (state) => state.addFeatureUseSelectedWorktreeBranch ); const setAddFeatureUseSelectedWorktreeBranch = useAppStore( (state) => state.setAddFeatureUseSelectedWorktreeBranch ); const codexAuthStatus = useSetupStore((state) => state.codexAuthStatus); // Worktree panel visibility (per-project) const worktreePanelVisibleByProject = useAppStore((state) => state.worktreePanelVisibleByProject); const setWorktreePanelVisible = useAppStore((state) => state.setWorktreePanelVisible); const isWorktreePanelVisible = worktreePanelVisibleByProject[projectPath] ?? true; const handleWorktreePanelToggle = useCallback( async (visible: boolean) => { // Update local store setWorktreePanelVisible(projectPath, visible); // Persist to server try { const httpClient = getHttpApiClient(); await httpClient.settings.updateProject(projectPath, { worktreePanelVisible: visible, }); } catch (error) { console.error('Failed to persist worktree panel visibility:', error); } }, [projectPath, setWorktreePanelVisible] ); const isClaudeCliVerified = !!claudeAuthStatus?.authenticated; const showClaudeUsage = isClaudeCliVerified; // Codex usage tracking visibility logic // Show if Codex is authenticated (CLI or API key) const showCodexUsage = !!codexAuthStatus?.authenticated; const isMobile = useIsMobile(); return (
Controls how many AI agents can run simultaneously. Higher values process more features in parallel but use more API resources.