Files
automaker/apps/ui/src/components/views/spec-view.tsx
Kacper e78bfc80ec feat: refactor spec-view to folder pattern and add feature count selector
Closes #151

- Refactor spec-view.tsx from 1,230 lines to ~170 lines following folder-pattern.md
- Create unified CreateSpecDialog with all features from both dialogs:
  - featureCount selector (20/50/100) - was missing in spec-view
  - analyzeProject checkbox - was missing in sidebar
- Extract components: spec-header, spec-editor, spec-empty-state
- Extract hooks: use-spec-loading, use-spec-save, use-spec-generation
- Extract dialogs: create-spec-dialog, regenerate-spec-dialog
- Update sidebar to use new CreateSpecDialog with analyzeProject state
- Delete deprecated project-setup-dialog.tsx

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:14:44 +01:00

173 lines
4.5 KiB
TypeScript

import { RefreshCw } from "lucide-react";
import { useAppStore } from "@/store/app-store";
// Extracted hooks
import {
useSpecLoading,
useSpecSave,
useSpecGeneration,
} from "./spec-view/hooks";
// Extracted components
import {
SpecHeader,
SpecEditor,
SpecEmptyState,
} from "./spec-view/components";
// Extracted dialogs
import {
CreateSpecDialog,
RegenerateSpecDialog,
} from "./spec-view/dialogs";
export function SpecView() {
const { currentProject, appSpec } = useAppStore();
// Loading state
const { isLoading, specExists, loadSpec } = useSpecLoading();
// Save state
const { isSaving, hasChanges, saveSpec, handleChange, setHasChanges } =
useSpecSave();
// Generation state and handlers
const {
// Dialog visibility
showCreateDialog,
setShowCreateDialog,
showRegenerateDialog,
setShowRegenerateDialog,
// Create state
projectOverview,
setProjectOverview,
isCreating,
generateFeatures,
setGenerateFeatures,
analyzeProjectOnCreate,
setAnalyzeProjectOnCreate,
featureCountOnCreate,
setFeatureCountOnCreate,
// Regenerate state
projectDefinition,
setProjectDefinition,
isRegenerating,
generateFeaturesOnRegenerate,
setGenerateFeaturesOnRegenerate,
analyzeProjectOnRegenerate,
setAnalyzeProjectOnRegenerate,
featureCountOnRegenerate,
setFeatureCountOnRegenerate,
// Feature generation
isGeneratingFeatures,
// Status
currentPhase,
errorMessage,
// Handlers
handleCreateSpec,
handleRegenerate,
} = useSpecGeneration({ loadSpec });
// Reset hasChanges when spec is reloaded
// (This is needed because loadSpec updates appSpec in the store)
// No project selected
if (!currentProject) {
return (
<div
className="flex-1 flex items-center justify-center"
data-testid="spec-view-no-project"
>
<p className="text-muted-foreground">No project selected</p>
</div>
);
}
// Loading state
if (isLoading) {
return (
<div
className="flex-1 flex items-center justify-center"
data-testid="spec-view-loading"
>
<RefreshCw className="w-6 h-6 animate-spin text-muted-foreground" />
</div>
);
}
// Empty state - no spec exists
if (!specExists) {
return (
<>
<SpecEmptyState
projectPath={currentProject.path}
isCreating={isCreating}
isRegenerating={isRegenerating}
currentPhase={currentPhase}
errorMessage={errorMessage}
onCreateClick={() => setShowCreateDialog(true)}
/>
<CreateSpecDialog
open={showCreateDialog}
onOpenChange={setShowCreateDialog}
projectOverview={projectOverview}
onProjectOverviewChange={setProjectOverview}
generateFeatures={generateFeatures}
onGenerateFeaturesChange={setGenerateFeatures}
analyzeProject={analyzeProjectOnCreate}
onAnalyzeProjectChange={setAnalyzeProjectOnCreate}
featureCount={featureCountOnCreate}
onFeatureCountChange={setFeatureCountOnCreate}
onCreateSpec={handleCreateSpec}
isCreatingSpec={isCreating}
/>
</>
);
}
// Main view - spec exists
return (
<div
className="flex-1 flex flex-col overflow-hidden content-bg"
data-testid="spec-view"
>
<SpecHeader
projectPath={currentProject.path}
isRegenerating={isRegenerating}
isCreating={isCreating}
isGeneratingFeatures={isGeneratingFeatures}
isSaving={isSaving}
hasChanges={hasChanges}
currentPhase={currentPhase}
errorMessage={errorMessage}
onRegenerateClick={() => setShowRegenerateDialog(true)}
onSaveClick={saveSpec}
/>
<SpecEditor value={appSpec} onChange={handleChange} />
<RegenerateSpecDialog
open={showRegenerateDialog}
onOpenChange={setShowRegenerateDialog}
projectDefinition={projectDefinition}
onProjectDefinitionChange={setProjectDefinition}
generateFeatures={generateFeaturesOnRegenerate}
onGenerateFeaturesChange={setGenerateFeaturesOnRegenerate}
analyzeProject={analyzeProjectOnRegenerate}
onAnalyzeProjectChange={setAnalyzeProjectOnRegenerate}
featureCount={featureCountOnRegenerate}
onFeatureCountChange={setFeatureCountOnRegenerate}
onRegenerate={handleRegenerate}
isRegenerating={isRegenerating}
isGeneratingFeatures={isGeneratingFeatures}
/>
</div>
);
}