mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
This update standardizes the loading indicators by replacing all instances of Loader2 with the new Spinner component. The Spinner component provides a consistent look and feel for loading states throughout the UI, enhancing the user experience. Changes include: - Updated loading indicators in various components such as popovers, modals, and views. - Ensured that the Spinner component is used with appropriate sizes for different contexts. No functional changes were made; this is purely a visual and structural improvement.
170 lines
5.3 KiB
TypeScript
170 lines
5.3 KiB
TypeScript
import { useState } from 'react';
|
|
import { useAppStore } from '@/store/app-store';
|
|
import { Spinner } from '@/components/ui/spinner';
|
|
|
|
// 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();
|
|
|
|
// Actions panel state (for tablet/mobile)
|
|
const [showActionsPanel, setShowActionsPanel] = useState(false);
|
|
|
|
// Loading state
|
|
const { isLoading, specExists, isGenerationRunning, 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,
|
|
|
|
// Sync
|
|
isSyncing,
|
|
|
|
// Status
|
|
currentPhase,
|
|
errorMessage,
|
|
|
|
// Handlers
|
|
handleCreateSpec,
|
|
handleRegenerate,
|
|
handleGenerateFeatures,
|
|
handleSync,
|
|
} = 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">
|
|
<Spinner size="lg" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Empty state - only show when spec doesn't exist AND no generation is running
|
|
// If generation is running but no spec exists, show the generating UI
|
|
if (!specExists) {
|
|
// If generation is running (from loading hook check), ensure we show the generating UI
|
|
const showAsGenerating = isCreating || isGenerationRunning;
|
|
|
|
return (
|
|
<>
|
|
<SpecEmptyState
|
|
projectPath={currentProject.path}
|
|
isCreating={showAsGenerating}
|
|
isRegenerating={isRegenerating || isGenerationRunning}
|
|
currentPhase={currentPhase || (isGenerationRunning ? 'initialization' : '')}
|
|
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 || isGenerationRunning}
|
|
isCreating={isCreating}
|
|
isGeneratingFeatures={isGeneratingFeatures}
|
|
isSyncing={isSyncing}
|
|
isSaving={isSaving}
|
|
hasChanges={hasChanges}
|
|
currentPhase={currentPhase || (isGenerationRunning ? 'working' : '')}
|
|
errorMessage={errorMessage}
|
|
onRegenerateClick={() => setShowRegenerateDialog(true)}
|
|
onGenerateFeaturesClick={handleGenerateFeatures}
|
|
onSyncClick={handleSync}
|
|
onSaveClick={saveSpec}
|
|
showActionsPanel={showActionsPanel}
|
|
onToggleActionsPanel={() => setShowActionsPanel(!showActionsPanel)}
|
|
/>
|
|
|
|
<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>
|
|
);
|
|
}
|