mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 21:23:07 +00:00
refactor(board-view): extract BoardHeader component
This commit is contained in:
@@ -63,6 +63,7 @@ import { FeatureSuggestionsDialog } from "./feature-suggestions-dialog";
|
|||||||
import { BoardBackgroundModal } from "@/components/dialogs/board-background-modal";
|
import { BoardBackgroundModal } from "@/components/dialogs/board-background-modal";
|
||||||
import { AddFeatureDialog } from "./board-view/AddFeatureDialog";
|
import { AddFeatureDialog } from "./board-view/AddFeatureDialog";
|
||||||
import { EditFeatureDialog } from "./board-view/EditFeatureDialog";
|
import { EditFeatureDialog } from "./board-view/EditFeatureDialog";
|
||||||
|
import { BoardHeader } from "./board-view/BoardHeader";
|
||||||
import {
|
import {
|
||||||
Plus,
|
Plus,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
@@ -1718,76 +1719,17 @@ export function BoardView() {
|
|||||||
data-testid="board-view"
|
data-testid="board-view"
|
||||||
>
|
>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between p-4 border-b border-border bg-glass backdrop-blur-md">
|
<BoardHeader
|
||||||
<div>
|
projectName={currentProject.name}
|
||||||
<h1 className="text-xl font-bold">Kanban Board</h1>
|
maxConcurrency={maxConcurrency}
|
||||||
<p className="text-sm text-muted-foreground">{currentProject.name}</p>
|
onConcurrencyChange={setMaxConcurrency}
|
||||||
</div>
|
isAutoModeRunning={autoMode.isRunning}
|
||||||
<div className="flex gap-2 items-center">
|
onStartAutoMode={() => autoMode.start()}
|
||||||
{/* Concurrency Slider - only show after mount to prevent hydration issues */}
|
onStopAutoMode={() => autoMode.stop()}
|
||||||
{isMounted && (
|
onAddFeature={() => setShowAddDialog(true)}
|
||||||
<div
|
addFeatureShortcut={shortcuts.addFeature}
|
||||||
className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-secondary border border-border"
|
isMounted={isMounted}
|
||||||
data-testid="concurrency-slider-container"
|
|
||||||
>
|
|
||||||
<Users className="w-4 h-4 text-muted-foreground" />
|
|
||||||
<Slider
|
|
||||||
value={[maxConcurrency]}
|
|
||||||
onValueChange={(value) => setMaxConcurrency(value[0])}
|
|
||||||
min={1}
|
|
||||||
max={10}
|
|
||||||
step={1}
|
|
||||||
className="w-20"
|
|
||||||
data-testid="concurrency-slider"
|
|
||||||
/>
|
/>
|
||||||
<span
|
|
||||||
className="text-sm text-muted-foreground min-w-[2ch] text-center"
|
|
||||||
data-testid="concurrency-value"
|
|
||||||
>
|
|
||||||
{maxConcurrency}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Auto Mode Toggle - only show after mount to prevent hydration issues */}
|
|
||||||
{isMounted && (
|
|
||||||
<>
|
|
||||||
{autoMode.isRunning ? (
|
|
||||||
<Button
|
|
||||||
variant="destructive"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => autoMode.stop()}
|
|
||||||
data-testid="stop-auto-mode"
|
|
||||||
>
|
|
||||||
<StopCircle className="w-4 h-4 mr-2" />
|
|
||||||
Stop Auto Mode
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => autoMode.start()}
|
|
||||||
data-testid="start-auto-mode"
|
|
||||||
>
|
|
||||||
<Play className="w-4 h-4 mr-2" />
|
|
||||||
Auto Mode
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<HotkeyButton
|
|
||||||
size="sm"
|
|
||||||
onClick={() => setShowAddDialog(true)}
|
|
||||||
hotkey={shortcuts.addFeature}
|
|
||||||
hotkeyActive={false}
|
|
||||||
data-testid="add-feature-button"
|
|
||||||
>
|
|
||||||
<Plus className="w-4 h-4 mr-2" />
|
|
||||||
Add Feature
|
|
||||||
</HotkeyButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Main Content Area */}
|
{/* Main Content Area */}
|
||||||
<div className="flex-1 flex flex-col overflow-hidden">
|
<div className="flex-1 flex flex-col overflow-hidden">
|
||||||
|
|||||||
104
apps/app/src/components/views/board-view/BoardHeader.tsx
Normal file
104
apps/app/src/components/views/board-view/BoardHeader.tsx
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { HotkeyButton } from "@/components/ui/hotkey-button";
|
||||||
|
import { Slider } from "@/components/ui/slider";
|
||||||
|
import { Play, StopCircle, Plus, Users } from "lucide-react";
|
||||||
|
import { KeyboardShortcut } from "@/hooks/use-keyboard-shortcuts";
|
||||||
|
|
||||||
|
interface BoardHeaderProps {
|
||||||
|
projectName: string;
|
||||||
|
maxConcurrency: number;
|
||||||
|
onConcurrencyChange: (value: number) => void;
|
||||||
|
isAutoModeRunning: boolean;
|
||||||
|
onStartAutoMode: () => void;
|
||||||
|
onStopAutoMode: () => void;
|
||||||
|
onAddFeature: () => void;
|
||||||
|
addFeatureShortcut: KeyboardShortcut;
|
||||||
|
isMounted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BoardHeader({
|
||||||
|
projectName,
|
||||||
|
maxConcurrency,
|
||||||
|
onConcurrencyChange,
|
||||||
|
isAutoModeRunning,
|
||||||
|
onStartAutoMode,
|
||||||
|
onStopAutoMode,
|
||||||
|
onAddFeature,
|
||||||
|
addFeatureShortcut,
|
||||||
|
isMounted,
|
||||||
|
}: BoardHeaderProps) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-between p-4 border-b border-border bg-glass backdrop-blur-md">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-xl font-bold">Kanban Board</h1>
|
||||||
|
<p className="text-sm text-muted-foreground">{projectName}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 items-center">
|
||||||
|
{/* Concurrency Slider - only show after mount to prevent hydration issues */}
|
||||||
|
{isMounted && (
|
||||||
|
<div
|
||||||
|
className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-secondary border border-border"
|
||||||
|
data-testid="concurrency-slider-container"
|
||||||
|
>
|
||||||
|
<Users className="w-4 h-4 text-muted-foreground" />
|
||||||
|
<Slider
|
||||||
|
value={[maxConcurrency]}
|
||||||
|
onValueChange={(value) => onConcurrencyChange(value[0])}
|
||||||
|
min={1}
|
||||||
|
max={10}
|
||||||
|
step={1}
|
||||||
|
className="w-20"
|
||||||
|
data-testid="concurrency-slider"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className="text-sm text-muted-foreground min-w-[2ch] text-center"
|
||||||
|
data-testid="concurrency-value"
|
||||||
|
>
|
||||||
|
{maxConcurrency}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Auto Mode Toggle - only show after mount to prevent hydration issues */}
|
||||||
|
{isMounted && (
|
||||||
|
<>
|
||||||
|
{isAutoModeRunning ? (
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
size="sm"
|
||||||
|
onClick={onStopAutoMode}
|
||||||
|
data-testid="stop-auto-mode"
|
||||||
|
>
|
||||||
|
<StopCircle className="w-4 h-4 mr-2" />
|
||||||
|
Stop Auto Mode
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
size="sm"
|
||||||
|
onClick={onStartAutoMode}
|
||||||
|
data-testid="start-auto-mode"
|
||||||
|
>
|
||||||
|
<Play className="w-4 h-4 mr-2" />
|
||||||
|
Auto Mode
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<HotkeyButton
|
||||||
|
size="sm"
|
||||||
|
onClick={onAddFeature}
|
||||||
|
hotkey={addFeatureShortcut}
|
||||||
|
hotkeyActive={false}
|
||||||
|
data-testid="add-feature-button"
|
||||||
|
>
|
||||||
|
<Plus className="w-4 h-4 mr-2" />
|
||||||
|
Add Feature
|
||||||
|
</HotkeyButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user