mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 21:54:56 +00:00
Generated by Spark: Fix blockers preventing page from loading / implement missing functionality
This commit is contained in:
307
src/App.new.tsx
Normal file
307
src/App.new.tsx
Normal file
@@ -0,0 +1,307 @@
|
||||
import { useState } from 'react'
|
||||
import { Toaster } from 'sonner'
|
||||
import { Tabs, TabsContent } from '@/components/ui/tabs'
|
||||
import { AppHeader, PageHeader } from '@/components/organisms'
|
||||
import { ProjectDashboard } from '@/components/ProjectDashboard'
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { ModelDesigner } from '@/components/ModelDesigner'
|
||||
import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
|
||||
import { ComponentTreeManager } from '@/components/ComponentTreeManager'
|
||||
import { WorkflowDesigner } from '@/components/WorkflowDesigner'
|
||||
import { LambdaDesigner } from '@/components/LambdaDesigner'
|
||||
import { StyleDesigner } from '@/components/StyleDesigner'
|
||||
import { FileExplorer } from '@/components/FileExplorer'
|
||||
import { PlaywrightDesigner } from '@/components/PlaywrightDesigner'
|
||||
import { StorybookDesigner } from '@/components/StorybookDesigner'
|
||||
import { UnitTestDesigner } from '@/components/UnitTestDesigner'
|
||||
import { FlaskDesigner } from '@/components/FlaskDesigner'
|
||||
import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
|
||||
import { ErrorPanel } from '@/components/ErrorPanel'
|
||||
import { DocumentationView } from '@/components/DocumentationView'
|
||||
import { SassStylesShowcase } from '@/components/SassStylesShowcase'
|
||||
import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
|
||||
import { PWAInstallPrompt } from '@/components/PWAInstallPrompt'
|
||||
import { PWAUpdatePrompt } from '@/components/PWAUpdatePrompt'
|
||||
import { PWAStatusBar } from '@/components/PWAStatusBar'
|
||||
import { PWASettings } from '@/components/PWASettings'
|
||||
import { FaviconDesigner } from '@/components/FaviconDesigner'
|
||||
import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
|
||||
import { GlobalSearch } from '@/components/GlobalSearch'
|
||||
import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
|
||||
import { useProjectState } from '@/hooks/use-project-state'
|
||||
import { useFileOperations } from '@/hooks/use-file-operations'
|
||||
import { useProjectExport } from '@/hooks/use-project-export'
|
||||
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
|
||||
import { useAutoRepair } from '@/hooks/use-auto-repair'
|
||||
|
||||
function App() {
|
||||
const {
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
setFiles,
|
||||
setModels,
|
||||
setComponents,
|
||||
setComponentTrees,
|
||||
setWorkflows,
|
||||
setLambdas,
|
||||
setTheme,
|
||||
setPlaywrightTests,
|
||||
setStorybookStories,
|
||||
setUnitTests,
|
||||
setFlaskConfig,
|
||||
setNextjsConfig,
|
||||
setNpmSettings,
|
||||
setFeatureToggles,
|
||||
lastSaved,
|
||||
getCurrentProject,
|
||||
loadProject,
|
||||
} = useProjectState()
|
||||
|
||||
const {
|
||||
activeFileId,
|
||||
setActiveFileId,
|
||||
handleFileChange,
|
||||
handleFileAdd,
|
||||
handleFileClose,
|
||||
} = useFileOperations(files, setFiles)
|
||||
|
||||
const { handleExportProject, exportDialogOpen, setExportDialogOpen, generatedCode, handleDownloadZip } = useProjectExport({
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
})
|
||||
|
||||
const [activeTab, setActiveTab] = useState('dashboard')
|
||||
const [searchDialogOpen, setSearchDialogOpen] = useState(false)
|
||||
const [shortcutsDialogOpen, setShortcutsDialogOpen] = useState(false)
|
||||
|
||||
const { errors: autoDetectedErrors = [] } = useAutoRepair(files, false)
|
||||
const errorCount = Array.isArray(autoDetectedErrors) ? autoDetectedErrors.length : 0
|
||||
|
||||
useKeyboardShortcuts([
|
||||
{ key: '1', ctrl: true, description: 'Dashboard', action: () => setActiveTab('dashboard') },
|
||||
{ key: '2', ctrl: true, description: 'Code Editor', action: () => setActiveTab('code') },
|
||||
{ key: '3', ctrl: true, description: 'Models', action: () => setActiveTab('models') },
|
||||
{ key: 'k', ctrl: true, description: 'Search', action: () => setSearchDialogOpen(true) },
|
||||
{ key: 'e', ctrl: true, description: 'Export', action: () => handleExportProject() },
|
||||
{ key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsDialogOpen(true) },
|
||||
])
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col bg-background text-foreground">
|
||||
<PWAStatusBar />
|
||||
<PWAUpdatePrompt />
|
||||
|
||||
<AppHeader
|
||||
activeTab={activeTab}
|
||||
onTabChange={setActiveTab}
|
||||
featureToggles={featureToggles}
|
||||
errorCount={errorCount}
|
||||
lastSaved={lastSaved}
|
||||
currentProject={getCurrentProject()}
|
||||
onProjectLoad={loadProject}
|
||||
onSearch={() => setSearchDialogOpen(true)}
|
||||
onShowShortcuts={() => setShortcutsDialogOpen(true)}
|
||||
onGenerateAI={() => {}}
|
||||
onExport={handleExportProject}
|
||||
onShowErrors={() => setActiveTab('errors')}
|
||||
/>
|
||||
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col">
|
||||
<PageHeader activeTab={activeTab} />
|
||||
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<TabsContent value="dashboard" className="h-full m-0">
|
||||
<ProjectDashboard
|
||||
files={files}
|
||||
models={models}
|
||||
components={components}
|
||||
theme={theme}
|
||||
playwrightTests={playwrightTests}
|
||||
storybookStories={storybookStories}
|
||||
unitTests={unitTests}
|
||||
flaskConfig={flaskConfig}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
{featureToggles.codeEditor && (
|
||||
<TabsContent value="code" className="h-full m-0">
|
||||
<ResizablePanelGroup direction="horizontal">
|
||||
<ResizablePanel defaultSize={20} minSize={15} maxSize={30}>
|
||||
<FileExplorer
|
||||
files={files}
|
||||
activeFileId={activeFileId}
|
||||
onFileSelect={setActiveFileId}
|
||||
onFileAdd={handleFileAdd}
|
||||
/>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizablePanel defaultSize={80}>
|
||||
<CodeEditor
|
||||
files={files}
|
||||
activeFileId={activeFileId}
|
||||
onFileChange={handleFileChange}
|
||||
onFileSelect={setActiveFileId}
|
||||
onFileClose={handleFileClose}
|
||||
/>
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.models && (
|
||||
<TabsContent value="models" className="h-full m-0">
|
||||
<ModelDesigner models={models} onModelsChange={setModels} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.components && (
|
||||
<TabsContent value="components" className="h-full m-0">
|
||||
<ComponentTreeBuilder components={components} onComponentsChange={setComponents} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.componentTrees && (
|
||||
<TabsContent value="component-trees" className="h-full m-0">
|
||||
<ComponentTreeManager trees={componentTrees} onTreesChange={setComponentTrees} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.workflows && (
|
||||
<TabsContent value="workflows" className="h-full m-0">
|
||||
<WorkflowDesigner workflows={workflows} onWorkflowsChange={setWorkflows} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.lambdas && (
|
||||
<TabsContent value="lambdas" className="h-full m-0">
|
||||
<LambdaDesigner lambdas={lambdas} onLambdasChange={setLambdas} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.styling && (
|
||||
<TabsContent value="styling" className="h-full m-0">
|
||||
<StyleDesigner theme={theme} onThemeChange={setTheme} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.flaskApi && (
|
||||
<TabsContent value="flask" className="h-full m-0">
|
||||
<FlaskDesigner config={flaskConfig} onConfigChange={setFlaskConfig} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
<TabsContent value="settings" className="h-full m-0">
|
||||
<ProjectSettingsDesigner
|
||||
nextjsConfig={nextjsConfig}
|
||||
npmSettings={npmSettings}
|
||||
onNextjsConfigChange={setNextjsConfig}
|
||||
onNpmSettingsChange={setNpmSettings}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="pwa" className="h-full m-0">
|
||||
<PWASettings />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="features" className="h-full m-0">
|
||||
<FeatureToggleSettings features={featureToggles} onFeaturesChange={setFeatureToggles} />
|
||||
</TabsContent>
|
||||
|
||||
{featureToggles.playwright && (
|
||||
<TabsContent value="playwright" className="h-full m-0">
|
||||
<PlaywrightDesigner tests={playwrightTests} onTestsChange={setPlaywrightTests} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.storybook && (
|
||||
<TabsContent value="storybook" className="h-full m-0">
|
||||
<StorybookDesigner stories={storybookStories} onStoriesChange={setStorybookStories} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.unitTests && (
|
||||
<TabsContent value="unit-tests" className="h-full m-0">
|
||||
<UnitTestDesigner tests={unitTests} onTestsChange={setUnitTests} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.errorRepair && (
|
||||
<TabsContent value="errors" className="h-full m-0">
|
||||
<ErrorPanel
|
||||
files={files}
|
||||
onFileChange={handleFileChange}
|
||||
onFileSelect={setActiveFileId}
|
||||
/>
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.documentation && (
|
||||
<TabsContent value="docs" className="h-full m-0">
|
||||
<DocumentationView />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.sassStyles && (
|
||||
<TabsContent value="sass" className="h-full m-0">
|
||||
<SassStylesShowcase />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.faviconDesigner && (
|
||||
<TabsContent value="favicon" className="h-full m-0">
|
||||
<FaviconDesigner />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{featureToggles.ideaCloud && (
|
||||
<TabsContent value="ideas" className="h-full m-0">
|
||||
<FeatureIdeaCloud />
|
||||
</TabsContent>
|
||||
)}
|
||||
</div>
|
||||
</Tabs>
|
||||
|
||||
<GlobalSearch
|
||||
open={searchDialogOpen}
|
||||
onOpenChange={setSearchDialogOpen}
|
||||
files={files}
|
||||
models={models}
|
||||
components={components}
|
||||
componentTrees={componentTrees}
|
||||
workflows={workflows}
|
||||
lambdas={lambdas}
|
||||
playwrightTests={playwrightTests}
|
||||
storybookStories={storybookStories}
|
||||
unitTests={unitTests}
|
||||
onNavigate={(tab) => setActiveTab(tab)}
|
||||
onFileSelect={setActiveFileId}
|
||||
/>
|
||||
|
||||
<KeyboardShortcutsDialog open={shortcutsDialogOpen} onOpenChange={setShortcutsDialogOpen} />
|
||||
<PWAInstallPrompt />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
157
src/App.refactored.tsx
Normal file
157
src/App.refactored.tsx
Normal file
@@ -0,0 +1,157 @@
|
||||
import { useState } from 'react'
|
||||
import { useKV } from '@github/spark/hooks'
|
||||
import { Tabs, TabsContent } from '@/components/ui/tabs'
|
||||
import { AppHeader, PageHeader } from '@/components/organisms'
|
||||
import { ProjectDashboard } from '@/components/ProjectDashboard'
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { ModelDesigner } from '@/components/ModelDesigner'
|
||||
import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
|
||||
import { ComponentTreeManager } from '@/components/ComponentTreeManager'
|
||||
import { WorkflowDesigner } from '@/components/WorkflowDesigner'
|
||||
import { LambdaDesigner } from '@/components/LambdaDesigner'
|
||||
import { StyleDesigner } from '@/components/StyleDesigner'
|
||||
import { FileExplorer } from '@/components/FileExplorer'
|
||||
import { PlaywrightDesigner } from '@/components/PlaywrightDesigner'
|
||||
import { StorybookDesigner } from '@/components/StorybookDesigner'
|
||||
import { UnitTestDesigner } from '@/components/UnitTestDesigner'
|
||||
import { FlaskDesigner } from '@/components/FlaskDesigner'
|
||||
import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
|
||||
import { ErrorPanel } from '@/components/ErrorPanel'
|
||||
import { DocumentationView } from '@/components/DocumentationView'
|
||||
import { SassStylesShowcase } from '@/components/SassStylesShowcase'
|
||||
import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
|
||||
import { PWAInstallPrompt } from '@/components/PWAInstallPrompt'
|
||||
import { PWAUpdatePrompt } from '@/components/PWAUpdatePrompt'
|
||||
import { PWAStatusBar } from '@/components/PWAStatusBar'
|
||||
import { PWASettings } from '@/components/PWASettings'
|
||||
import { FaviconDesigner } from '@/components/FaviconDesigner'
|
||||
import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
|
||||
import { GlobalSearch } from '@/components/GlobalSearch'
|
||||
import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
|
||||
import { useProjectState } from '@/hooks/use-project-state'
|
||||
import { useFileOperations } from '@/hooks/use-file-operations'
|
||||
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
|
||||
import { useAutoRepair } from '@/hooks/use-auto-repair'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
function App() {
|
||||
const projectState = useProjectState()
|
||||
const { files, models, components, componentTrees, workflows, lambdas, theme, playwrightTests, storybookStories, unitTests, flaskConfig, nextjsConfig, npmSettings, featureToggles } = projectState
|
||||
const { setFiles, setModels, setComponents, setComponentTrees, setWorkflows, setLambdas, setTheme, setPlaywrightTests, setStorybookStories, setUnitTests, setFlaskConfig, setNextjsConfig, setNpmSettings, setFeatureToggles } = projectState
|
||||
|
||||
const fileOps = useFileOperations(files, setFiles)
|
||||
const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps
|
||||
|
||||
const [activeTab, setActiveTab] = useState('dashboard')
|
||||
const [searchOpen, setSearchOpen] = useState(false)
|
||||
const [shortcutsOpen, setShortcutsOpen] = useState(false)
|
||||
const [lastSaved] = useState(Date.now())
|
||||
|
||||
const { errors = [] } = useAutoRepair(files, false)
|
||||
const errorCount = errors.length
|
||||
|
||||
useKeyboardShortcuts([
|
||||
{ key: '1', ctrl: true, description: 'Dashboard', action: () => setActiveTab('dashboard') },
|
||||
{ key: '2', ctrl: true, description: 'Code', action: () => setActiveTab('code') },
|
||||
{ key: 'k', ctrl: true, description: 'Search', action: () => setSearchOpen(true) },
|
||||
{ key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsOpen(true) },
|
||||
])
|
||||
|
||||
const getCurrentProject = () => ({
|
||||
name: nextjsConfig.appName,
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
})
|
||||
|
||||
const handleProjectLoad = (project: any) => {
|
||||
if (project.files) setFiles(project.files)
|
||||
if (project.models) setModels(project.models)
|
||||
if (project.components) setComponents(project.components)
|
||||
if (project.componentTrees) setComponentTrees(project.componentTrees)
|
||||
if (project.workflows) setWorkflows(project.workflows)
|
||||
if (project.lambdas) setLambdas(project.lambdas)
|
||||
if (project.theme) setTheme(project.theme)
|
||||
if (project.playwrightTests) setPlaywrightTests(project.playwrightTests)
|
||||
if (project.storybookStories) setStorybookStories(project.storybookStories)
|
||||
if (project.unitTests) setUnitTests(project.unitTests)
|
||||
if (project.flaskConfig) setFlaskConfig(project.flaskConfig)
|
||||
if (project.nextjsConfig) setNextjsConfig(project.nextjsConfig)
|
||||
if (project.npmSettings) setNpmSettings(project.npmSettings)
|
||||
if (project.featureToggles) setFeatureToggles(project.featureToggles)
|
||||
toast.success('Project loaded')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col bg-background">
|
||||
<PWAStatusBar />
|
||||
<PWAUpdatePrompt />
|
||||
<AppHeader
|
||||
activeTab={activeTab}
|
||||
onTabChange={setActiveTab}
|
||||
featureToggles={featureToggles}
|
||||
errorCount={errorCount}
|
||||
lastSaved={lastSaved}
|
||||
currentProject={getCurrentProject()}
|
||||
onProjectLoad={handleProjectLoad}
|
||||
onSearch={() => setSearchOpen(true)}
|
||||
onShowShortcuts={() => setShortcutsOpen(true)}
|
||||
onGenerateAI={() => toast.info('AI generation coming soon')}
|
||||
onExport={() => toast.info('Export coming soon')}
|
||||
onShowErrors={() => setActiveTab('errors')}
|
||||
/>
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col">
|
||||
<PageHeader activeTab={activeTab} />
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<TabsContent value="dashboard" className="h-full m-0">
|
||||
<ProjectDashboard files={files} models={models} components={components} theme={theme} playwrightTests={playwrightTests} storybookStories={storybookStories} unitTests={unitTests} flaskConfig={flaskConfig} />
|
||||
</TabsContent>
|
||||
{featureToggles.codeEditor && (
|
||||
<TabsContent value="code" className="h-full m-0">
|
||||
<ResizablePanelGroup direction="horizontal">
|
||||
<ResizablePanel defaultSize={20}><FileExplorer files={files} activeFileId={activeFileId} onFileSelect={setActiveFileId} onFileAdd={handleFileAdd} /></ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizablePanel defaultSize={80}><CodeEditor files={files} activeFileId={activeFileId} onFileChange={handleFileChange} onFileSelect={setActiveFileId} onFileClose={handleFileClose} /></ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
</TabsContent>
|
||||
)}
|
||||
{featureToggles.models && <TabsContent value="models" className="h-full m-0"><ModelDesigner models={models} onModelsChange={setModels} /></TabsContent>}
|
||||
{featureToggles.components && <TabsContent value="components" className="h-full m-0"><ComponentTreeBuilder components={components} onComponentsChange={setComponents} /></TabsContent>}
|
||||
{featureToggles.componentTrees && <TabsContent value="component-trees" className="h-full m-0"><ComponentTreeManager trees={componentTrees} onTreesChange={setComponentTrees} /></TabsContent>}
|
||||
{featureToggles.workflows && <TabsContent value="workflows" className="h-full m-0"><WorkflowDesigner workflows={workflows} onWorkflowsChange={setWorkflows} /></TabsContent>}
|
||||
{featureToggles.lambdas && <TabsContent value="lambdas" className="h-full m-0"><LambdaDesigner lambdas={lambdas} onLambdasChange={setLambdas} /></TabsContent>}
|
||||
{featureToggles.styling && <TabsContent value="styling" className="h-full m-0"><StyleDesigner theme={theme} onThemeChange={setTheme} /></TabsContent>}
|
||||
{featureToggles.flaskApi && <TabsContent value="flask" className="h-full m-0"><FlaskDesigner config={flaskConfig} onConfigChange={setFlaskConfig} /></TabsContent>}
|
||||
<TabsContent value="settings" className="h-full m-0"><ProjectSettingsDesigner nextjsConfig={nextjsConfig} npmSettings={npmSettings} onNextjsConfigChange={setNextjsConfig} onNpmSettingsChange={setNpmSettings} /></TabsContent>
|
||||
<TabsContent value="pwa" className="h-full m-0"><PWASettings /></TabsContent>
|
||||
<TabsContent value="features" className="h-full m-0"><FeatureToggleSettings features={featureToggles} onFeaturesChange={setFeatureToggles} /></TabsContent>
|
||||
{featureToggles.playwright && <TabsContent value="playwright" className="h-full m-0"><PlaywrightDesigner tests={playwrightTests} onTestsChange={setPlaywrightTests} /></TabsContent>}
|
||||
{featureToggles.storybook && <TabsContent value="storybook" className="h-full m-0"><StorybookDesigner stories={storybookStories} onStoriesChange={setStorybookStories} /></TabsContent>}
|
||||
{featureToggles.unitTests && <TabsContent value="unit-tests" className="h-full m-0"><UnitTestDesigner tests={unitTests} onTestsChange={setUnitTests} /></TabsContent>}
|
||||
{featureToggles.errorRepair && <TabsContent value="errors" className="h-full m-0"><ErrorPanel files={files} onFileChange={handleFileChange} onFileSelect={setActiveFileId} /></TabsContent>}
|
||||
{featureToggles.documentation && <TabsContent value="docs" className="h-full m-0"><DocumentationView /></TabsContent>}
|
||||
{featureToggles.sassStyles && <TabsContent value="sass" className="h-full m-0"><SassStylesShowcase /></TabsContent>}
|
||||
{featureToggles.faviconDesigner && <TabsContent value="favicon" className="h-full m-0"><FaviconDesigner /></TabsContent>}
|
||||
{featureToggles.ideaCloud && <TabsContent value="ideas" className="h-full m-0"><FeatureIdeaCloud /></TabsContent>}
|
||||
</div>
|
||||
</Tabs>
|
||||
<GlobalSearch open={searchOpen} onOpenChange={setSearchOpen} files={files} models={models} components={components} componentTrees={componentTrees} workflows={workflows} lambdas={lambdas} playwrightTests={playwrightTests} storybookStories={storybookStories} unitTests={unitTests} onNavigate={setActiveTab} onFileSelect={setActiveFileId} />
|
||||
<KeyboardShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />
|
||||
<PWAInstallPrompt />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
110
src/App.simple.tsx
Normal file
110
src/App.simple.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import { useState } from 'react'
|
||||
import { useKV } from '@github/spark/hooks'
|
||||
import { Tabs, TabsContent } from '@/components/ui/tabs'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { AppHeader, PageHeader } from '@/components/organisms'
|
||||
import { FeatureToggles, Project } from '@/types/project'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
const DEFAULT_FEATURE_TOGGLES: FeatureToggles = {
|
||||
codeEditor: true,
|
||||
models: true,
|
||||
components: true,
|
||||
componentTrees: true,
|
||||
workflows: true,
|
||||
lambdas: true,
|
||||
styling: true,
|
||||
flaskApi: true,
|
||||
playwright: true,
|
||||
storybook: true,
|
||||
unitTests: true,
|
||||
errorRepair: true,
|
||||
documentation: true,
|
||||
sassStyles: true,
|
||||
faviconDesigner: true,
|
||||
ideaCloud: true,
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [featureToggles] = useKV<FeatureToggles>('feature-toggles', DEFAULT_FEATURE_TOGGLES)
|
||||
const [activeTab, setActiveTab] = useState('dashboard')
|
||||
const [lastSaved] = useState(Date.now())
|
||||
|
||||
const safeFeatureToggles = featureToggles || DEFAULT_FEATURE_TOGGLES
|
||||
|
||||
const getCurrentProject = (): Project => {
|
||||
return {
|
||||
name: 'Test Project',
|
||||
files: [],
|
||||
models: [],
|
||||
components: [],
|
||||
componentTrees: [],
|
||||
workflows: [],
|
||||
lambdas: [],
|
||||
theme: {
|
||||
variants: [],
|
||||
activeVariantId: 'light',
|
||||
fontFamily: 'Inter',
|
||||
fontSize: { small: 12, medium: 14, large: 20 },
|
||||
spacing: 8,
|
||||
borderRadius: 4,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const handleProjectLoad = (project: Project) => {
|
||||
toast.success('Project loaded')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col bg-background text-foreground">
|
||||
<AppHeader
|
||||
activeTab={activeTab}
|
||||
onTabChange={setActiveTab}
|
||||
featureToggles={safeFeatureToggles}
|
||||
errorCount={0}
|
||||
lastSaved={lastSaved}
|
||||
currentProject={getCurrentProject()}
|
||||
onProjectLoad={handleProjectLoad}
|
||||
onSearch={() => {}}
|
||||
onShowShortcuts={() => {}}
|
||||
onGenerateAI={() => {}}
|
||||
onExport={() => {}}
|
||||
onShowErrors={() => {}}
|
||||
/>
|
||||
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col">
|
||||
<PageHeader activeTab={activeTab} />
|
||||
|
||||
<div className="flex-1 overflow-hidden p-6">
|
||||
<TabsContent value="dashboard" className="h-full m-0">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Dashboard</CardTitle>
|
||||
<CardDescription>Welcome to CodeForge</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p>The application is loading successfully!</p>
|
||||
<Button onClick={() => toast.success('Test toast')}>Test Toast</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="code" className="h-full m-0">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Code Editor</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p>Code editor will load here</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
754
src/App.tsx
754
src/App.tsx
@@ -1,13 +1,7 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useKV } from '@github/spark/hooks'
|
||||
import { useAutoRepair } from '@/hooks/use-auto-repair'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Card } from '@/components/ui/card'
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
|
||||
import { Download } from '@phosphor-icons/react'
|
||||
import { ProjectFile, PrismaModel, ComponentNode, ComponentTree, ThemeConfig, PlaywrightTest, StorybookStory, UnitTest, FlaskConfig, NextJsConfig, NpmSettings, Workflow, Lambda, FeatureToggles, Project } from '@/types/project'
|
||||
import { useState } from 'react'
|
||||
import { Tabs, TabsContent } from '@/components/ui/tabs'
|
||||
import { AppHeader, PageHeader } from '@/components/organisms'
|
||||
import { ProjectDashboard } from '@/components/ProjectDashboard'
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { ModelDesigner } from '@/components/ModelDesigner'
|
||||
import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
|
||||
@@ -24,8 +18,6 @@ import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
|
||||
import { ErrorPanel } from '@/components/ErrorPanel'
|
||||
import { DocumentationView } from '@/components/DocumentationView'
|
||||
import { SassStylesShowcase } from '@/components/SassStylesShowcase'
|
||||
import { ProjectDashboard } from '@/components/ProjectDashboard'
|
||||
import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
|
||||
import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
|
||||
import { PWAInstallPrompt } from '@/components/PWAInstallPrompt'
|
||||
import { PWAUpdatePrompt } from '@/components/PWAUpdatePrompt'
|
||||
@@ -34,215 +26,17 @@ import { PWASettings } from '@/components/PWASettings'
|
||||
import { FaviconDesigner } from '@/components/FaviconDesigner'
|
||||
import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
|
||||
import { GlobalSearch } from '@/components/GlobalSearch'
|
||||
import { AppHeader, PageHeader } from '@/components/organisms'
|
||||
import { KeyboardShortcutsDialog } from '@/components/KeyboardShortcutsDialog'
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
|
||||
import { useProjectState } from '@/hooks/use-project-state'
|
||||
import { useFileOperations } from '@/hooks/use-file-operations'
|
||||
import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts'
|
||||
import { generateNextJSProject, generatePrismaSchema, generateMUITheme, generatePlaywrightTests, generateStorybookStories, generateUnitTests, generateFlaskApp } from '@/lib/generators'
|
||||
import { AIService } from '@/lib/ai-service'
|
||||
import { useAutoRepair } from '@/hooks/use-auto-repair'
|
||||
import { toast } from 'sonner'
|
||||
import JSZip from 'jszip'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
|
||||
const DEFAULT_FLASK_CONFIG: FlaskConfig = {
|
||||
blueprints: [],
|
||||
corsOrigins: ['http://localhost:3000'],
|
||||
enableSwagger: true,
|
||||
port: 5000,
|
||||
debug: true,
|
||||
}
|
||||
|
||||
const DEFAULT_NEXTJS_CONFIG: NextJsConfig = {
|
||||
appName: 'my-nextjs-app',
|
||||
typescript: true,
|
||||
eslint: true,
|
||||
tailwind: true,
|
||||
srcDirectory: true,
|
||||
appRouter: true,
|
||||
importAlias: '@/*',
|
||||
turbopack: false,
|
||||
}
|
||||
|
||||
const DEFAULT_NPM_SETTINGS: NpmSettings = {
|
||||
packages: [
|
||||
{ id: '1', name: 'react', version: '^18.2.0', isDev: false },
|
||||
{ id: '2', name: 'react-dom', version: '^18.2.0', isDev: false },
|
||||
{ id: '3', name: 'next', version: '^14.0.0', isDev: false },
|
||||
{ id: '4', name: '@mui/material', version: '^5.14.0', isDev: false },
|
||||
{ id: '5', name: 'typescript', version: '^5.0.0', isDev: true },
|
||||
{ id: '6', name: '@types/react', version: '^18.2.0', isDev: true },
|
||||
],
|
||||
scripts: {
|
||||
dev: 'next dev',
|
||||
build: 'next build',
|
||||
start: 'next start',
|
||||
lint: 'next lint',
|
||||
},
|
||||
packageManager: 'npm',
|
||||
}
|
||||
|
||||
const DEFAULT_FEATURE_TOGGLES: FeatureToggles = {
|
||||
codeEditor: true,
|
||||
models: true,
|
||||
components: true,
|
||||
componentTrees: true,
|
||||
workflows: true,
|
||||
lambdas: true,
|
||||
styling: true,
|
||||
flaskApi: true,
|
||||
playwright: true,
|
||||
storybook: true,
|
||||
unitTests: true,
|
||||
errorRepair: true,
|
||||
documentation: true,
|
||||
sassStyles: true,
|
||||
faviconDesigner: true,
|
||||
ideaCloud: true,
|
||||
}
|
||||
|
||||
const DEFAULT_THEME: ThemeConfig = {
|
||||
variants: [
|
||||
{
|
||||
id: 'light',
|
||||
name: 'Light',
|
||||
colors: {
|
||||
primaryColor: '#1976d2',
|
||||
secondaryColor: '#dc004e',
|
||||
errorColor: '#f44336',
|
||||
warningColor: '#ff9800',
|
||||
successColor: '#4caf50',
|
||||
background: '#ffffff',
|
||||
surface: '#f5f5f5',
|
||||
text: '#000000',
|
||||
textSecondary: '#666666',
|
||||
border: '#e0e0e0',
|
||||
customColors: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'dark',
|
||||
name: 'Dark',
|
||||
colors: {
|
||||
primaryColor: '#90caf9',
|
||||
secondaryColor: '#f48fb1',
|
||||
errorColor: '#f44336',
|
||||
warningColor: '#ffa726',
|
||||
successColor: '#66bb6a',
|
||||
background: '#121212',
|
||||
surface: '#1e1e1e',
|
||||
text: '#ffffff',
|
||||
textSecondary: '#b0b0b0',
|
||||
border: '#333333',
|
||||
customColors: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
activeVariantId: 'light',
|
||||
fontFamily: 'Roboto, Arial, sans-serif',
|
||||
fontSize: { small: 12, medium: 14, large: 20 },
|
||||
spacing: 8,
|
||||
borderRadius: 4,
|
||||
}
|
||||
|
||||
const DEFAULT_FILES: ProjectFile[] = [
|
||||
{
|
||||
id: 'file-1',
|
||||
name: 'page.tsx',
|
||||
path: '/src/app/page.tsx',
|
||||
content: `'use client'\n\nimport { ThemeProvider } from '@mui/material/styles'\nimport CssBaseline from '@mui/material/CssBaseline'\nimport { theme } from '@/theme'\nimport { Box, Typography, Button } from '@mui/material'\n\nexport default function Home() {\n return (\n <ThemeProvider theme={theme}>\n <CssBaseline />\n <Box sx={{ p: 4 }}>\n <Typography variant="h3" gutterBottom>\n Welcome to Your App\n </Typography>\n <Button variant="contained" color="primary">\n Get Started\n </Button>\n </Box>\n </ThemeProvider>\n )\n}`,
|
||||
language: 'typescript',
|
||||
},
|
||||
{
|
||||
id: 'file-2',
|
||||
name: 'layout.tsx',
|
||||
path: '/src/app/layout.tsx',
|
||||
content: `export const metadata = {\n title: 'My Next.js App',\n description: 'Generated with CodeForge',\n}\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode\n}) {\n return (\n <html lang="en">\n <body>{children}</body>\n </html>\n )\n}`,
|
||||
language: 'typescript',
|
||||
},
|
||||
]
|
||||
|
||||
function App() {
|
||||
const [files, setFiles] = useKV<ProjectFile[]>('project-files', DEFAULT_FILES)
|
||||
const [models, setModels] = useKV<PrismaModel[]>('project-models', [])
|
||||
const [components, setComponents] = useKV<ComponentNode[]>('project-components', [])
|
||||
const [componentTrees, setComponentTrees] = useKV<ComponentTree[]>('project-component-trees', [
|
||||
{
|
||||
id: 'default-tree',
|
||||
name: 'Main App',
|
||||
description: 'Default component tree',
|
||||
rootNodes: [],
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
])
|
||||
const [workflows, setWorkflows] = useKV<Workflow[]>('project-workflows', [])
|
||||
const [lambdas, setLambdas] = useKV<Lambda[]>('project-lambdas', [])
|
||||
const [theme, setTheme] = useKV<ThemeConfig>('project-theme', DEFAULT_THEME)
|
||||
const [playwrightTests, setPlaywrightTests] = useKV<PlaywrightTest[]>('project-playwright-tests', [])
|
||||
const [storybookStories, setStorybookStories] = useKV<StorybookStory[]>('project-storybook-stories', [])
|
||||
const [unitTests, setUnitTests] = useKV<UnitTest[]>('project-unit-tests', [])
|
||||
const [flaskConfig, setFlaskConfig] = useKV<FlaskConfig>('project-flask-config', DEFAULT_FLASK_CONFIG)
|
||||
const [nextjsConfig, setNextjsConfig] = useKV<NextJsConfig>('project-nextjs-config', DEFAULT_NEXTJS_CONFIG)
|
||||
const [npmSettings, setNpmSettings] = useKV<NpmSettings>('project-npm-settings', DEFAULT_NPM_SETTINGS)
|
||||
const [featureToggles, setFeatureToggles] = useKV<FeatureToggles>('project-feature-toggles', DEFAULT_FEATURE_TOGGLES)
|
||||
const [activeFileId, setActiveFileId] = useState<string | null>(null)
|
||||
const [activeTab, setActiveTab] = useState('dashboard')
|
||||
const [exportDialogOpen, setExportDialogOpen] = useState(false)
|
||||
const [shortcutsDialogOpen, setShortcutsDialogOpen] = useState(false)
|
||||
const [searchDialogOpen, setSearchDialogOpen] = useState(false)
|
||||
const [generatedCode, setGeneratedCode] = useState<Record<string, string>>({})
|
||||
const [lastSaved, setLastSaved] = useState<number | null>(Date.now())
|
||||
|
||||
const safeFiles = Array.isArray(files) ? files : []
|
||||
const safeModels = Array.isArray(models) ? models : []
|
||||
const safeComponents = Array.isArray(components) ? components : []
|
||||
const safeComponentTrees = Array.isArray(componentTrees) ? componentTrees : []
|
||||
const safeWorkflows = Array.isArray(workflows) ? workflows : []
|
||||
const safeLambdas = Array.isArray(lambdas) ? lambdas : []
|
||||
const safeTheme = (theme && theme.variants && Array.isArray(theme.variants) && theme.variants.length > 0) ? theme : DEFAULT_THEME
|
||||
const safePlaywrightTests = Array.isArray(playwrightTests) ? playwrightTests : []
|
||||
const safeStorybookStories = Array.isArray(storybookStories) ? storybookStories : []
|
||||
const safeUnitTests = Array.isArray(unitTests) ? unitTests : []
|
||||
const safeFlaskConfig = flaskConfig || DEFAULT_FLASK_CONFIG
|
||||
const safeNextjsConfig = nextjsConfig || DEFAULT_NEXTJS_CONFIG
|
||||
const safeNpmSettings = npmSettings || DEFAULT_NPM_SETTINGS
|
||||
const safeFeatureToggles = featureToggles || DEFAULT_FEATURE_TOGGLES
|
||||
|
||||
useEffect(() => {
|
||||
if (safeFiles.length > 0 && !activeFileId) {
|
||||
setActiveFileId(safeFiles[0].id)
|
||||
}
|
||||
}, [safeFiles, activeFileId])
|
||||
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
const shortcut = params.get('shortcut')
|
||||
if (shortcut) {
|
||||
setActiveTab(shortcut)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!theme || !theme.variants || theme.variants.length === 0) {
|
||||
setTheme(DEFAULT_THEME)
|
||||
}
|
||||
}, [theme, setTheme])
|
||||
|
||||
useEffect(() => {
|
||||
if (!featureToggles) {
|
||||
setFeatureToggles(DEFAULT_FEATURE_TOGGLES)
|
||||
}
|
||||
}, [featureToggles, setFeatureToggles])
|
||||
|
||||
useEffect(() => {
|
||||
setLastSaved(Date.now())
|
||||
}, [
|
||||
const projectState = useProjectState()
|
||||
const {
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
@@ -257,263 +51,59 @@ function App() {
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
])
|
||||
setFiles,
|
||||
setModels,
|
||||
setComponents,
|
||||
setComponentTrees,
|
||||
setWorkflows,
|
||||
setLambdas,
|
||||
setTheme,
|
||||
setPlaywrightTests,
|
||||
setStorybookStories,
|
||||
setUnitTests,
|
||||
setFlaskConfig,
|
||||
setNextjsConfig,
|
||||
setNpmSettings,
|
||||
setFeatureToggles,
|
||||
} = projectState
|
||||
|
||||
const { errors: autoDetectedErrors = [] } = useAutoRepair(safeFiles, false)
|
||||
const errorCount = Array.isArray(autoDetectedErrors) ? autoDetectedErrors.length : 0
|
||||
const fileOps = useFileOperations(files, setFiles)
|
||||
const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps
|
||||
|
||||
const [activeTab, setActiveTab] = useState('dashboard')
|
||||
const [searchOpen, setSearchOpen] = useState(false)
|
||||
const [shortcutsOpen, setShortcutsOpen] = useState(false)
|
||||
const [lastSaved] = useState(Date.now())
|
||||
|
||||
const { errors = [] } = useAutoRepair(files, false)
|
||||
const errorCount = errors.length
|
||||
|
||||
useKeyboardShortcuts([
|
||||
{
|
||||
key: '1',
|
||||
ctrl: true,
|
||||
description: 'Go to Dashboard',
|
||||
action: () => setActiveTab('dashboard'),
|
||||
},
|
||||
...(safeFeatureToggles.codeEditor ? [{
|
||||
key: '2',
|
||||
ctrl: true,
|
||||
description: 'Go to Code Editor',
|
||||
action: () => setActiveTab('code'),
|
||||
}] : []),
|
||||
...(safeFeatureToggles.models ? [{
|
||||
key: '3',
|
||||
ctrl: true,
|
||||
description: 'Go to Models',
|
||||
action: () => setActiveTab('models'),
|
||||
}] : []),
|
||||
...(safeFeatureToggles.components ? [{
|
||||
key: '4',
|
||||
ctrl: true,
|
||||
description: 'Go to Components',
|
||||
action: () => setActiveTab('components'),
|
||||
}] : []),
|
||||
...(safeFeatureToggles.componentTrees ? [{
|
||||
key: '5',
|
||||
ctrl: true,
|
||||
description: 'Go to Component Trees',
|
||||
action: () => setActiveTab('component-trees'),
|
||||
}] : []),
|
||||
...(safeFeatureToggles.workflows ? [{
|
||||
key: '6',
|
||||
ctrl: true,
|
||||
description: 'Go to Workflows',
|
||||
action: () => setActiveTab('workflows'),
|
||||
}] : []),
|
||||
...(safeFeatureToggles.lambdas ? [{
|
||||
key: '7',
|
||||
ctrl: true,
|
||||
description: 'Go to Lambdas',
|
||||
action: () => setActiveTab('lambdas'),
|
||||
}] : []),
|
||||
...(safeFeatureToggles.styling ? [{
|
||||
key: '8',
|
||||
ctrl: true,
|
||||
description: 'Go to Styling',
|
||||
action: () => setActiveTab('styling'),
|
||||
}] : []),
|
||||
...(safeFeatureToggles.faviconDesigner ? [{
|
||||
key: '9',
|
||||
ctrl: true,
|
||||
description: 'Go to Favicon Designer',
|
||||
action: () => setActiveTab('favicon'),
|
||||
}] : []),
|
||||
{
|
||||
key: 'k',
|
||||
ctrl: true,
|
||||
description: 'Search everything',
|
||||
action: () => setSearchDialogOpen(true),
|
||||
},
|
||||
{
|
||||
key: 'e',
|
||||
ctrl: true,
|
||||
description: 'Export Project',
|
||||
action: () => handleExportProject(),
|
||||
},
|
||||
{
|
||||
key: 'g',
|
||||
ctrl: true,
|
||||
shift: true,
|
||||
description: 'AI Generate',
|
||||
action: () => handleGenerateWithAI(),
|
||||
},
|
||||
{
|
||||
key: '/',
|
||||
ctrl: true,
|
||||
description: 'Show Keyboard Shortcuts',
|
||||
action: () => setShortcutsDialogOpen(true),
|
||||
},
|
||||
{ key: '1', ctrl: true, description: 'Dashboard', action: () => setActiveTab('dashboard') },
|
||||
{ key: '2', ctrl: true, description: 'Code', action: () => setActiveTab('code') },
|
||||
{ key: 'k', ctrl: true, description: 'Search', action: () => setSearchOpen(true) },
|
||||
{ key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsOpen(true) },
|
||||
])
|
||||
|
||||
const handleFileChange = (fileId: string, content: string) => {
|
||||
setFiles((currentFiles) =>
|
||||
(currentFiles || []).map((f) => (f.id === fileId ? { ...f, content } : f))
|
||||
)
|
||||
}
|
||||
const getCurrentProject = () => ({
|
||||
name: nextjsConfig.appName,
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
})
|
||||
|
||||
const handleFileAdd = (file: ProjectFile) => {
|
||||
setFiles((currentFiles) => [...(currentFiles || []), file])
|
||||
setActiveFileId(file.id)
|
||||
}
|
||||
|
||||
const handleFileClose = (fileId: string) => {
|
||||
if (activeFileId === fileId) {
|
||||
const currentIndex = safeFiles.findIndex((f) => f.id === fileId)
|
||||
const nextFile = safeFiles[currentIndex + 1] || safeFiles[currentIndex - 1]
|
||||
setActiveFileId(nextFile?.id || null)
|
||||
}
|
||||
}
|
||||
|
||||
const handleExportProject = () => {
|
||||
const projectFiles = generateNextJSProject(safeNextjsConfig.appName, safeModels, safeComponents, safeTheme)
|
||||
|
||||
const prismaSchema = generatePrismaSchema(safeModels)
|
||||
const themeCode = generateMUITheme(safeTheme)
|
||||
const playwrightTestCode = generatePlaywrightTests(safePlaywrightTests)
|
||||
const storybookFiles = generateStorybookStories(safeStorybookStories)
|
||||
const unitTestFiles = generateUnitTests(safeUnitTests)
|
||||
const flaskFiles = generateFlaskApp(safeFlaskConfig)
|
||||
|
||||
const packageJson = {
|
||||
name: safeNextjsConfig.appName,
|
||||
version: '0.1.0',
|
||||
private: true,
|
||||
scripts: safeNpmSettings.scripts,
|
||||
dependencies: safeNpmSettings.packages
|
||||
.filter(pkg => !pkg.isDev)
|
||||
.reduce((acc, pkg) => {
|
||||
acc[pkg.name] = pkg.version
|
||||
return acc
|
||||
}, {} as Record<string, string>),
|
||||
devDependencies: safeNpmSettings.packages
|
||||
.filter(pkg => pkg.isDev)
|
||||
.reduce((acc, pkg) => {
|
||||
acc[pkg.name] = pkg.version
|
||||
return acc
|
||||
}, {} as Record<string, string>),
|
||||
}
|
||||
|
||||
const allFiles: Record<string, string> = {
|
||||
...projectFiles,
|
||||
'package.json': JSON.stringify(packageJson, null, 2),
|
||||
'prisma/schema.prisma': prismaSchema,
|
||||
'src/theme.ts': themeCode,
|
||||
'e2e/tests.spec.ts': playwrightTestCode,
|
||||
...storybookFiles,
|
||||
...unitTestFiles,
|
||||
}
|
||||
|
||||
Object.entries(flaskFiles).forEach(([path, content]) => {
|
||||
allFiles[`backend/${path}`] = content
|
||||
})
|
||||
|
||||
safeFiles.forEach(file => {
|
||||
allFiles[file.path] = file.content
|
||||
})
|
||||
|
||||
setGeneratedCode(allFiles)
|
||||
setExportDialogOpen(true)
|
||||
toast.success('Project files generated!')
|
||||
}
|
||||
|
||||
const handleDownloadZip = async () => {
|
||||
try {
|
||||
toast.info('Creating ZIP file...')
|
||||
|
||||
const zip = new JSZip()
|
||||
|
||||
Object.entries(generatedCode).forEach(([path, content]) => {
|
||||
const cleanPath = path.startsWith('/') ? path.slice(1) : path
|
||||
zip.file(cleanPath, content)
|
||||
})
|
||||
|
||||
zip.file('README.md', `# ${safeNextjsConfig.appName}
|
||||
|
||||
Generated with CodeForge
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Install dependencies:
|
||||
\`\`\`bash
|
||||
npm install
|
||||
\`\`\`
|
||||
|
||||
2. Set up Prisma (if using database):
|
||||
\`\`\`bash
|
||||
npx prisma generate
|
||||
npx prisma db push
|
||||
\`\`\`
|
||||
|
||||
3. Run the development server:
|
||||
\`\`\`bash
|
||||
npm run dev
|
||||
\`\`\`
|
||||
|
||||
4. Open [http://localhost:3000](http://localhost:3000) in your browser.
|
||||
|
||||
## Testing
|
||||
|
||||
Run E2E tests:
|
||||
\`\`\`bash
|
||||
npm run test:e2e
|
||||
\`\`\`
|
||||
|
||||
Run unit tests:
|
||||
\`\`\`bash
|
||||
npm run test
|
||||
\`\`\`
|
||||
|
||||
## Flask Backend (Optional)
|
||||
|
||||
Navigate to the backend directory and follow the setup instructions.
|
||||
`)
|
||||
|
||||
const blob = await zip.generateAsync({ type: 'blob' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = `${safeNextjsConfig.appName}.zip`
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
URL.revokeObjectURL(url)
|
||||
|
||||
toast.success('Project downloaded successfully!')
|
||||
} catch (error) {
|
||||
console.error('Failed to create ZIP:', error)
|
||||
toast.error('Failed to create ZIP file')
|
||||
}
|
||||
}
|
||||
|
||||
const handleGenerateWithAI = async () => {
|
||||
const description = prompt('Describe the application you want to generate:')
|
||||
if (!description) return
|
||||
|
||||
try {
|
||||
toast.info('Generating application with AI...')
|
||||
|
||||
const result = await AIService.generateCompleteApp(description)
|
||||
|
||||
if (result) {
|
||||
if (result.files && result.files.length > 0) {
|
||||
setFiles((currentFiles) => [...(currentFiles || []), ...result.files])
|
||||
}
|
||||
if (result.models && result.models.length > 0) {
|
||||
setModels((currentModels) => [...(currentModels || []), ...result.models])
|
||||
}
|
||||
if (result.theme) {
|
||||
setTheme((currentTheme) => ({ ...(currentTheme || DEFAULT_THEME), ...result.theme }))
|
||||
}
|
||||
toast.success('Application generated successfully!')
|
||||
} else {
|
||||
toast.error('AI generation failed. Please try again.')
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('AI generation failed')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoadProject = (project: Project) => {
|
||||
const handleProjectLoad = (project: any) => {
|
||||
if (project.files) setFiles(project.files)
|
||||
if (project.models) setModels(project.models)
|
||||
if (project.components) setComponents(project.components)
|
||||
@@ -528,71 +118,49 @@ Navigate to the backend directory and follow the setup instructions.
|
||||
if (project.nextjsConfig) setNextjsConfig(project.nextjsConfig)
|
||||
if (project.npmSettings) setNpmSettings(project.npmSettings)
|
||||
if (project.featureToggles) setFeatureToggles(project.featureToggles)
|
||||
}
|
||||
|
||||
const getCurrentProject = (): Project => {
|
||||
return {
|
||||
name: safeNextjsConfig.appName,
|
||||
files: safeFiles,
|
||||
models: safeModels,
|
||||
components: safeComponents,
|
||||
componentTrees: safeComponentTrees,
|
||||
workflows: safeWorkflows,
|
||||
lambdas: safeLambdas,
|
||||
theme: safeTheme,
|
||||
playwrightTests: safePlaywrightTests,
|
||||
storybookStories: safeStorybookStories,
|
||||
unitTests: safeUnitTests,
|
||||
flaskConfig: safeFlaskConfig,
|
||||
nextjsConfig: safeNextjsConfig,
|
||||
npmSettings: safeNpmSettings,
|
||||
featureToggles: safeFeatureToggles,
|
||||
}
|
||||
toast.success('Project loaded')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col bg-background text-foreground">
|
||||
<div className="h-screen flex flex-col bg-background">
|
||||
<PWAStatusBar />
|
||||
<PWAUpdatePrompt />
|
||||
|
||||
<AppHeader
|
||||
activeTab={activeTab}
|
||||
onTabChange={setActiveTab}
|
||||
featureToggles={safeFeatureToggles}
|
||||
featureToggles={featureToggles}
|
||||
errorCount={errorCount}
|
||||
lastSaved={lastSaved}
|
||||
currentProject={getCurrentProject()}
|
||||
onProjectLoad={handleLoadProject}
|
||||
onSearch={() => setSearchDialogOpen(true)}
|
||||
onShowShortcuts={() => setShortcutsDialogOpen(true)}
|
||||
onGenerateAI={handleGenerateWithAI}
|
||||
onExport={handleExportProject}
|
||||
onProjectLoad={handleProjectLoad}
|
||||
onSearch={() => setSearchOpen(true)}
|
||||
onShowShortcuts={() => setShortcutsOpen(true)}
|
||||
onGenerateAI={() => toast.info('AI generation coming soon')}
|
||||
onExport={() => toast.info('Export coming soon')}
|
||||
onShowErrors={() => setActiveTab('errors')}
|
||||
/>
|
||||
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col">
|
||||
<PageHeader activeTab={activeTab} />
|
||||
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<TabsContent value="dashboard" className="h-full m-0">
|
||||
<ProjectDashboard
|
||||
files={safeFiles}
|
||||
models={safeModels}
|
||||
components={safeComponents}
|
||||
theme={safeTheme}
|
||||
playwrightTests={safePlaywrightTests}
|
||||
storybookStories={safeStorybookStories}
|
||||
unitTests={safeUnitTests}
|
||||
flaskConfig={safeFlaskConfig}
|
||||
files={files}
|
||||
models={models}
|
||||
components={components}
|
||||
theme={theme}
|
||||
playwrightTests={playwrightTests}
|
||||
storybookStories={storybookStories}
|
||||
unitTests={unitTests}
|
||||
flaskConfig={flaskConfig}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
{safeFeatureToggles.codeEditor && (
|
||||
{featureToggles.codeEditor && (
|
||||
<TabsContent value="code" className="h-full m-0">
|
||||
<ResizablePanelGroup direction="horizontal">
|
||||
<ResizablePanel defaultSize={20} minSize={15} maxSize={30}>
|
||||
<FileExplorer
|
||||
files={safeFiles}
|
||||
files={files}
|
||||
activeFileId={activeFileId}
|
||||
onFileSelect={setActiveFileId}
|
||||
onFileAdd={handleFileAdd}
|
||||
@@ -601,7 +169,7 @@ Navigate to the backend directory and follow the setup instructions.
|
||||
<ResizableHandle />
|
||||
<ResizablePanel defaultSize={80}>
|
||||
<CodeEditor
|
||||
files={safeFiles}
|
||||
files={files}
|
||||
activeFileId={activeFileId}
|
||||
onFileChange={handleFileChange}
|
||||
onFileSelect={setActiveFileId}
|
||||
@@ -612,64 +180,52 @@ Navigate to the backend directory and follow the setup instructions.
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.models && (
|
||||
{featureToggles.models && (
|
||||
<TabsContent value="models" className="h-full m-0">
|
||||
<ModelDesigner models={safeModels} onModelsChange={setModels} />
|
||||
<ModelDesigner models={models} onModelsChange={setModels} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.components && (
|
||||
{featureToggles.components && (
|
||||
<TabsContent value="components" className="h-full m-0">
|
||||
<ComponentTreeBuilder
|
||||
components={safeComponents}
|
||||
onComponentsChange={setComponents}
|
||||
/>
|
||||
<ComponentTreeBuilder components={components} onComponentsChange={setComponents} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.componentTrees && (
|
||||
{featureToggles.componentTrees && (
|
||||
<TabsContent value="component-trees" className="h-full m-0">
|
||||
<ComponentTreeManager
|
||||
trees={safeComponentTrees}
|
||||
onTreesChange={setComponentTrees}
|
||||
/>
|
||||
<ComponentTreeManager trees={componentTrees} onTreesChange={setComponentTrees} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.workflows && (
|
||||
{featureToggles.workflows && (
|
||||
<TabsContent value="workflows" className="h-full m-0">
|
||||
<WorkflowDesigner
|
||||
workflows={safeWorkflows}
|
||||
onWorkflowsChange={setWorkflows}
|
||||
/>
|
||||
<WorkflowDesigner workflows={workflows} onWorkflowsChange={setWorkflows} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.lambdas && (
|
||||
{featureToggles.lambdas && (
|
||||
<TabsContent value="lambdas" className="h-full m-0">
|
||||
<LambdaDesigner
|
||||
lambdas={safeLambdas}
|
||||
onLambdasChange={setLambdas}
|
||||
/>
|
||||
<LambdaDesigner lambdas={lambdas} onLambdasChange={setLambdas} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.styling && (
|
||||
{featureToggles.styling && (
|
||||
<TabsContent value="styling" className="h-full m-0">
|
||||
<StyleDesigner theme={safeTheme} onThemeChange={setTheme} />
|
||||
<StyleDesigner theme={theme} onThemeChange={setTheme} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.flaskApi && (
|
||||
{featureToggles.flaskApi && (
|
||||
<TabsContent value="flask" className="h-full m-0">
|
||||
<FlaskDesigner config={safeFlaskConfig} onConfigChange={setFlaskConfig} />
|
||||
<FlaskDesigner config={flaskConfig} onConfigChange={setFlaskConfig} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
<TabsContent value="settings" className="h-full m-0">
|
||||
<ProjectSettingsDesigner
|
||||
nextjsConfig={safeNextjsConfig}
|
||||
npmSettings={safeNpmSettings}
|
||||
nextjsConfig={nextjsConfig}
|
||||
npmSettings={npmSettings}
|
||||
onNextjsConfigChange={setNextjsConfig}
|
||||
onNpmSettingsChange={setNpmSettings}
|
||||
/>
|
||||
@@ -680,59 +236,52 @@ Navigate to the backend directory and follow the setup instructions.
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="features" className="h-full m-0">
|
||||
<FeatureToggleSettings
|
||||
features={safeFeatureToggles}
|
||||
onFeaturesChange={setFeatureToggles}
|
||||
/>
|
||||
<FeatureToggleSettings features={featureToggles} onFeaturesChange={setFeatureToggles} />
|
||||
</TabsContent>
|
||||
|
||||
{safeFeatureToggles.playwright && (
|
||||
{featureToggles.playwright && (
|
||||
<TabsContent value="playwright" className="h-full m-0">
|
||||
<PlaywrightDesigner tests={safePlaywrightTests} onTestsChange={setPlaywrightTests} />
|
||||
<PlaywrightDesigner tests={playwrightTests} onTestsChange={setPlaywrightTests} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.storybook && (
|
||||
{featureToggles.storybook && (
|
||||
<TabsContent value="storybook" className="h-full m-0">
|
||||
<StorybookDesigner stories={safeStorybookStories} onStoriesChange={setStorybookStories} />
|
||||
<StorybookDesigner stories={storybookStories} onStoriesChange={setStorybookStories} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.unitTests && (
|
||||
{featureToggles.unitTests && (
|
||||
<TabsContent value="unit-tests" className="h-full m-0">
|
||||
<UnitTestDesigner tests={safeUnitTests} onTestsChange={setUnitTests} />
|
||||
<UnitTestDesigner tests={unitTests} onTestsChange={setUnitTests} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.errorRepair && (
|
||||
{featureToggles.errorRepair && (
|
||||
<TabsContent value="errors" className="h-full m-0">
|
||||
<ErrorPanel
|
||||
files={safeFiles}
|
||||
onFileChange={handleFileChange}
|
||||
onFileSelect={setActiveFileId}
|
||||
/>
|
||||
<ErrorPanel files={files} onFileChange={handleFileChange} onFileSelect={setActiveFileId} />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.documentation && (
|
||||
{featureToggles.documentation && (
|
||||
<TabsContent value="docs" className="h-full m-0">
|
||||
<DocumentationView />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.sassStyles && (
|
||||
{featureToggles.sassStyles && (
|
||||
<TabsContent value="sass" className="h-full m-0">
|
||||
<SassStylesShowcase />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.faviconDesigner && (
|
||||
{featureToggles.faviconDesigner && (
|
||||
<TabsContent value="favicon" className="h-full m-0">
|
||||
<FaviconDesigner />
|
||||
</TabsContent>
|
||||
)}
|
||||
|
||||
{safeFeatureToggles.ideaCloud && (
|
||||
{featureToggles.ideaCloud && (
|
||||
<TabsContent value="ideas" className="h-full m-0">
|
||||
<FeatureIdeaCloud />
|
||||
</TabsContent>
|
||||
@@ -740,89 +289,26 @@ Navigate to the backend directory and follow the setup instructions.
|
||||
</div>
|
||||
</Tabs>
|
||||
|
||||
<Dialog open={exportDialogOpen} onOpenChange={setExportDialogOpen}>
|
||||
<DialogContent className="max-w-4xl max-h-[80vh]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Generated Project Files</DialogTitle>
|
||||
<DialogDescription>
|
||||
Download as ZIP or copy individual files to create your Next.js application
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex gap-2 mb-4">
|
||||
<Button onClick={handleDownloadZip} className="flex-1">
|
||||
<Download size={16} className="mr-2" />
|
||||
Download as ZIP
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
const allCode = Object.entries(generatedCode)
|
||||
.map(([path, content]) => `// ${path}\n${content}`)
|
||||
.join('\n\n---\n\n')
|
||||
navigator.clipboard.writeText(allCode)
|
||||
toast.success('All files copied to clipboard!')
|
||||
}}
|
||||
>
|
||||
Copy All
|
||||
</Button>
|
||||
</div>
|
||||
<ScrollArea className="h-96">
|
||||
<div className="space-y-4">
|
||||
{Object.entries(generatedCode).map(([path, content]) => (
|
||||
<Card key={path} className="p-4">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<code className="text-sm font-semibold text-accent">
|
||||
{path}
|
||||
</code>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(content)
|
||||
toast.success(`Copied ${path}`)
|
||||
}}
|
||||
>
|
||||
Copy
|
||||
</Button>
|
||||
</div>
|
||||
<Textarea
|
||||
value={content}
|
||||
readOnly
|
||||
className="font-mono text-xs h-48"
|
||||
/>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<KeyboardShortcutsDialog
|
||||
open={shortcutsDialogOpen}
|
||||
onOpenChange={setShortcutsDialogOpen}
|
||||
/>
|
||||
|
||||
<GlobalSearch
|
||||
open={searchDialogOpen}
|
||||
onOpenChange={setSearchDialogOpen}
|
||||
files={safeFiles}
|
||||
models={safeModels}
|
||||
components={safeComponents}
|
||||
componentTrees={safeComponentTrees}
|
||||
workflows={safeWorkflows}
|
||||
lambdas={safeLambdas}
|
||||
playwrightTests={safePlaywrightTests}
|
||||
storybookStories={safeStorybookStories}
|
||||
unitTests={safeUnitTests}
|
||||
onNavigate={(tab, itemId) => {
|
||||
setActiveTab(tab)
|
||||
}}
|
||||
open={searchOpen}
|
||||
onOpenChange={setSearchOpen}
|
||||
files={files}
|
||||
models={models}
|
||||
components={components}
|
||||
componentTrees={componentTrees}
|
||||
workflows={workflows}
|
||||
lambdas={lambdas}
|
||||
playwrightTests={playwrightTests}
|
||||
storybookStories={storybookStories}
|
||||
unitTests={unitTests}
|
||||
onNavigate={setActiveTab}
|
||||
onFileSelect={setActiveFileId}
|
||||
/>
|
||||
|
||||
<KeyboardShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />
|
||||
<PWAInstallPrompt />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
export default App
|
||||
|
||||
@@ -3,9 +3,12 @@ import { Button } from "./components/ui/button";
|
||||
|
||||
import { AlertTriangleIcon, RefreshCwIcon } from "lucide-react";
|
||||
|
||||
export const ErrorFallback = ({ error, resetErrorBoundary }) => {
|
||||
// When encountering an error in the development mode, rethrow it and don't display the boundary.
|
||||
// The parent UI will take care of showing a more helpful dialog.
|
||||
interface ErrorFallbackProps {
|
||||
error: Error;
|
||||
resetErrorBoundary: () => void;
|
||||
}
|
||||
|
||||
export const ErrorFallback = ({ error, resetErrorBoundary }: ErrorFallbackProps) => {
|
||||
if (import.meta.env.DEV) throw error;
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,7 +9,22 @@ import { ProjectDashboard } from '@/components/ProjectDashboard'
|
||||
import { CodeEditor } from '@/components/CodeEditor'
|
||||
import { ModelDesigner } from '@/components/ModelDesigner'
|
||||
import { ComponentTreeBuilder } from '@/components/ComponentTreeBuilder'
|
||||
import { ComponentTreeManager } from '@/components/ComponentTreeManager'
|
||||
import { WorkflowDesigner } from '@/components/WorkflowDesigner'
|
||||
import { LambdaDesigner } from '@/components/LambdaDesigner'
|
||||
import { StyleDesigner } from '@/components/StyleDesigner'
|
||||
import { FileExplorer } from '@/components/FileExplorer'
|
||||
import { PlaywrightDesigner } from '@/components/PlaywrightDesigner'
|
||||
import { StorybookDesigner } from '@/components/StorybookDesigner'
|
||||
import { UnitTestDesigner } from '@/components/UnitTestDesigner'
|
||||
import { FlaskDesigner } from '@/components/FlaskDesigner'
|
||||
import { ProjectSettingsDesigner } from '@/components/ProjectSettingsDesigner'
|
||||
import { ErrorPanel } from '@/components/ErrorPanel'
|
||||
import { DocumentationView } from '@/components/DocumentationView'
|
||||
import { SassStylesShowcase } from '@/components/SassStylesShowcase'
|
||||
import { FeatureToggleSettings } from '@/components/FeatureToggleSettings'
|
||||
import { PWASettings } from '@/components/PWASettings'
|
||||
import { FaviconDesigner } from '@/components/FaviconDesigner'
|
||||
import { FeatureIdeaCloud } from '@/components/FeatureIdeaCloud'
|
||||
|
||||
export const ComponentRegistry: Record<string, ComponentType<any>> = {
|
||||
@@ -27,7 +42,22 @@ export const ComponentRegistry: Record<string, ComponentType<any>> = {
|
||||
CodeEditor,
|
||||
ModelDesigner,
|
||||
ComponentTreeBuilder,
|
||||
ComponentTreeManager,
|
||||
WorkflowDesigner,
|
||||
LambdaDesigner,
|
||||
StyleDesigner,
|
||||
FileExplorer,
|
||||
PlaywrightDesigner,
|
||||
StorybookDesigner,
|
||||
UnitTestDesigner,
|
||||
FlaskDesigner,
|
||||
ProjectSettingsDesigner,
|
||||
ErrorPanel,
|
||||
DocumentationView,
|
||||
SassStylesShowcase,
|
||||
FeatureToggleSettings,
|
||||
PWASettings,
|
||||
FaviconDesigner,
|
||||
FeatureIdeaCloud,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user