diff --git a/src/App.router.tsx b/src/App.router.tsx index db25702..a4b0a90 100644 --- a/src/App.router.tsx +++ b/src/App.router.tsx @@ -1,403 +1,5 @@ -console.log('[APP_ROUTER] ๐Ÿš€ App.router.tsx loading - BEGIN') -console.time('[APP_ROUTER] Component initialization') +import AppRouterBootstrap from '@/components/app/AppRouterBootstrap' -import { useState, Suspense, useEffect } from 'react' -console.log('[APP_ROUTER] โœ… React hooks imported') - -import { BrowserRouter, useLocation } from 'react-router-dom' -console.log('[APP_ROUTER] โœ… React Router imported') - -import { AppHeader } from '@/components/organisms' -console.log('[APP_ROUTER] โœ… Header components imported') - -import { LoadingFallback } from '@/components/molecules' -console.log('[APP_ROUTER] โœ… LoadingFallback imported') - -import { useProjectState } from '@/hooks/use-project-state' -import { useFileOperations } from '@/hooks/use-file-operations' -import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts' -import { useSeedData } from '@/hooks/data/use-seed-data' -import { useRouterNavigation } from '@/hooks/use-router-navigation' -console.log('[APP_ROUTER] โœ… Custom hooks imported') - -import { getPageShortcuts } from '@/config/page-loader' -console.log('[APP_ROUTER] โœ… Page config imported') - -import { toast } from 'sonner' -console.log('[APP_ROUTER] โœ… Toast imported') - -import { DialogRegistry, PWARegistry, preloadCriticalComponents } from '@/lib/component-registry' -console.log('[APP_ROUTER] โœ… Component registry imported') - -import { RouterProvider } from '@/router' -console.log('[APP_ROUTER] โœ… Router provider imported') - -const { GlobalSearch, KeyboardShortcutsDialog, PreviewDialog } = DialogRegistry -const { PWAInstallPrompt, PWAUpdatePrompt, PWAStatusBar } = PWARegistry -console.log('[APP_ROUTER] โœ… Dialog and PWA components registered') - -console.log('[APP_ROUTER] ๐ŸŽฏ App component function executing') - -function AppLayout() { - console.log('[APP_ROUTER] ๐Ÿ—๏ธ AppLayout component rendering') - const location = useLocation() - const { currentPage, navigateToPage } = useRouterNavigation() - - console.log('[APP_ROUTER] ๐Ÿ“ Current location:', location.pathname) - console.log('[APP_ROUTER] ๐Ÿ“„ Current page:', currentPage) - - console.log('[APP_ROUTER] ๐Ÿ“Š Initializing project state hook') - const projectState = useProjectState() - console.log('[APP_ROUTER] โœ… Project state initialized') - - 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, - } = projectState - - console.log('[APP_ROUTER] ๐Ÿ“ Initializing file operations') - const fileOps = useFileOperations(files, setFiles) - console.log('[APP_ROUTER] โœ… File operations initialized') - - const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps - - console.log('[APP_ROUTER] ๐Ÿ’พ Initializing state variables') - const [searchOpen, setSearchOpen] = useState(false) - const [shortcutsOpen, setShortcutsOpen] = useState(false) - const [previewOpen, setPreviewOpen] = useState(false) - const [lastSaved] = useState(Date.now()) - const [errorCount] = useState(0) - console.log('[APP_ROUTER] โœ… State variables initialized') - - const shortcuts = getPageShortcuts(featureToggles) - console.log('[APP_ROUTER] โŒจ๏ธ Keyboard shortcuts configured:', shortcuts.length) - - console.log('[APP_ROUTER] โŒจ๏ธ Setting up keyboard shortcuts') - useKeyboardShortcuts([ - ...shortcuts.map(s => ({ - key: s.key, - ctrl: s.ctrl, - shift: s.shift, - description: s.description, - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Shortcut triggered, navigating to:', s.action) - navigateToPage(s.action) - } - })), - { - key: 'k', - ctrl: true, - description: 'Search', - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Search shortcut triggered') - setSearchOpen(true) - } - }, - { - key: '/', - ctrl: true, - description: 'Shortcuts', - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Shortcuts dialog triggered') - setShortcutsOpen(true) - } - }, - { - key: 'p', - ctrl: true, - description: 'Preview', - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Preview shortcut triggered') - setPreviewOpen(true) - } - }, - ]) - console.log('[APP_ROUTER] โœ… Keyboard shortcuts configured') - - const getCurrentProject = () => ({ - name: nextjsConfig.appName, - files, - models, - components, - componentTrees, - workflows, - lambdas, - theme, - playwrightTests, - storybookStories, - unitTests, - flaskConfig, - nextjsConfig, - npmSettings, - featureToggles, - }) - - const handleProjectLoad = (project: any) => { - console.log('[APP_ROUTER] ๐Ÿ“ฆ Loading project:', project.name) - 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') - console.log('[APP_ROUTER] โœ… Project loaded successfully') - } - - useEffect(() => { - console.log('[APP_ROUTER] ๐Ÿ“ Route changed to:', location.pathname, '- Page:', currentPage) - }, [location, currentPage]) - - console.log('[APP_ROUTER] ๐ŸŽจ Rendering AppLayout UI') - - return ( -
- }> - - - - - - { - console.log('[APP_ROUTER] ๐Ÿ” Search opened') - setSearchOpen(true) - }} - onShowShortcuts={() => { - console.log('[APP_ROUTER] โŒจ๏ธ Shortcuts dialog opened') - setShortcutsOpen(true) - }} - onGenerateAI={() => { - console.log('[APP_ROUTER] ๐Ÿค– AI generation requested') - toast.info('AI generation coming soon') - }} - onExport={() => { - console.log('[APP_ROUTER] ๐Ÿ“ค Export requested') - toast.info('Export coming soon') - }} - onPreview={() => { - console.log('[APP_ROUTER] ๐Ÿ‘๏ธ Preview opened') - setPreviewOpen(true) - }} - onShowErrors={() => { - console.log('[APP_ROUTER] โš ๏ธ Navigating to errors page') - navigateToPage('errors') - }} - /> -
- -
- - - { - console.log('[APP_ROUTER] ๐Ÿ” Search navigation to:', page) - navigateToPage(page) - }} - onFileSelect={(fileId) => { - console.log('[APP_ROUTER] ๐Ÿ“„ File selected from search:', fileId) - setActiveFileId(fileId) - navigateToPage('code') - }} - /> - - - - - - - - - - - -
- ) +export default function App() { + return } - -function App() { - console.log('[APP_ROUTER] ๐Ÿ”ง Initializing App component') - console.time('[APP_ROUTER] App render') - - console.log('[APP_ROUTER] ๐ŸŒฑ Initializing seed data hook') - const { loadSeedData } = useSeedData() - const projectState = useProjectState() - const { featureToggles, files, setFiles, ...restState } = projectState - console.log('[APP_ROUTER] โœ… Hooks initialized') - - console.log('[APP_ROUTER] ๐Ÿ“ Initializing file operations for router context') - const fileOps = useFileOperations(files, setFiles) - - const [appReady, setAppReady] = useState(false) - console.log('[APP_ROUTER] ๐Ÿ’พ App ready state:', appReady) - - console.log('[APP_ROUTER] โฐ Setting up initialization effect') - useEffect(() => { - console.log('[APP_ROUTER] ๐Ÿš€ Initialization effect triggered') - console.time('[APP_ROUTER] Seed data loading') - - const timer = setTimeout(() => { - console.log('[APP_ROUTER] โฑ๏ธ Fallback timer triggered (100ms)') - setAppReady(true) - }, 100) - - console.log('[APP_ROUTER] ๐Ÿ“ฅ Starting seed data load') - loadSeedData() - .then(() => { - console.log('[APP_ROUTER] โœ… Seed data loaded successfully') - }) - .catch(err => { - console.error('[APP_ROUTER] โŒ Seed data loading failed:', err) - }) - .finally(() => { - console.log('[APP_ROUTER] ๐Ÿ Seed data loading complete') - clearTimeout(timer) - setAppReady(true) - console.timeEnd('[APP_ROUTER] Seed data loading') - console.log('[APP_ROUTER] โœ… App marked as ready') - - console.log('[APP_ROUTER] ๐Ÿš€ Preloading critical components') - preloadCriticalComponents() - }) - - return () => { - console.log('[APP_ROUTER] ๐Ÿงน Cleaning up initialization effect') - clearTimeout(timer) - } - }, [loadSeedData]) - - const stateContext = { - files, - ...restState, - activeFileId: fileOps.activeFileId, - } - - const actionContext = { - handleFileChange: fileOps.handleFileChange, - setActiveFileId: fileOps.setActiveFileId, - handleFileClose: fileOps.handleFileClose, - handleFileAdd: fileOps.handleFileAdd, - setFiles, - ...Object.fromEntries( - Object.entries(restState).filter(([key]) => key.startsWith('set')) - ), - } - - console.log('[APP_ROUTER] ๐ŸŽจ Rendering App component UI') - console.log('[APP_ROUTER] App state - appReady:', appReady) - console.timeEnd('[APP_ROUTER] App render') - - if (!appReady) { - console.log('[APP_ROUTER] โณ App not ready, showing loading screen') - return ( -
-
-
-

Loading CodeForge...

-
-
- ) - } - - console.log('[APP_ROUTER] โœ… App ready, rendering router') - return ( - - - - ) -} - -console.log('[APP_ROUTER] โœ… App component defined') -console.timeEnd('[APP_ROUTER] Component initialization') - -export default App diff --git a/src/App.tsx b/src/App.tsx index 6a21998..2a3bace 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,426 +1,5 @@ -console.log('[APP_ROUTER] ๐Ÿš€ App.router.tsx loading - BEGIN') -console.time('[APP_ROUTER] Component initialization') +import AppBootstrap from '@/components/app/AppBootstrap' -import { useState, Suspense, useEffect } from 'react' -console.log('[APP_ROUTER] โœ… React hooks imported') - -import { BrowserRouter, useLocation } from 'react-router-dom' -console.log('[APP_ROUTER] โœ… React Router imported') - -import { AppHeader } from '@/components/organisms' -import { NavigationMenu } from '@/components/organisms/NavigationMenu' -console.log('[APP_ROUTER] โœ… Header components imported') - -import { LoadingFallback } from '@/components/molecules' -console.log('[APP_ROUTER] โœ… LoadingFallback imported') - -import { useProjectState } from '@/hooks/use-project-state' -import { useFileOperations } from '@/hooks/use-file-operations' -import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts' -import { useSeedData } from '@/hooks/data/use-seed-data' -import { useRouterNavigation } from '@/hooks/use-router-navigation' -import { useComponentTreeLoader } from '@/hooks/use-component-tree-loader' -console.log('[APP_ROUTER] โœ… Custom hooks imported') - -import { getPageShortcuts } from '@/config/page-loader' -console.log('[APP_ROUTER] โœ… Page config imported') - -import { toast } from 'sonner' -console.log('[APP_ROUTER] โœ… Toast imported') - -import { DialogRegistry, PWARegistry, preloadCriticalComponents } from '@/lib/component-registry' -console.log('[APP_ROUTER] โœ… Component registry imported') - -import { RouterProvider } from '@/router' -console.log('[APP_ROUTER] โœ… Router provider imported') - -import { SidebarProvider, SidebarInset, Sidebar, SidebarContent, SidebarHeader } from '@/components/ui/sidebar' -console.log('[APP_ROUTER] โœ… Sidebar provider imported') - -const { GlobalSearch, KeyboardShortcutsDialog, PreviewDialog } = DialogRegistry -const { PWAInstallPrompt, PWAUpdatePrompt, PWAStatusBar } = PWARegistry -console.log('[APP_ROUTER] โœ… Dialog and PWA components registered') - -console.log('[APP_ROUTER] ๐ŸŽฏ App component function executing') - -function AppLayout() { - console.log('[APP_ROUTER] ๐Ÿ—๏ธ AppLayout component rendering') - const location = useLocation() - const { currentPage, navigateToPage } = useRouterNavigation() - - console.log('[APP_ROUTER] ๐Ÿ“ Current location:', location.pathname) - console.log('[APP_ROUTER] ๐Ÿ“„ Current page:', currentPage) - - console.log('[APP_ROUTER] ๐Ÿ“Š Initializing project state hook') - const projectState = useProjectState() - console.log('[APP_ROUTER] โœ… Project state initialized') - - 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, - } = projectState - - console.log('[APP_ROUTER] ๐Ÿ“ Initializing file operations') - const fileOps = useFileOperations(files, setFiles) - console.log('[APP_ROUTER] โœ… File operations initialized') - - const { activeFileId, setActiveFileId, handleFileChange, handleFileAdd, handleFileClose } = fileOps - - console.log('[APP_ROUTER] ๐Ÿ’พ Initializing state variables') - const [searchOpen, setSearchOpen] = useState(false) - const [shortcutsOpen, setShortcutsOpen] = useState(false) - const [previewOpen, setPreviewOpen] = useState(false) - const [lastSaved] = useState(Date.now()) - const [errorCount] = useState(0) - console.log('[APP_ROUTER] โœ… State variables initialized') - - const shortcuts = getPageShortcuts(featureToggles) - console.log('[APP_ROUTER] โŒจ๏ธ Keyboard shortcuts configured:', shortcuts.length) - - console.log('[APP_ROUTER] โŒจ๏ธ Setting up keyboard shortcuts') - useKeyboardShortcuts([ - ...shortcuts.map(s => ({ - key: s.key, - ctrl: s.ctrl, - shift: s.shift, - description: s.description, - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Shortcut triggered, navigating to:', s.action) - navigateToPage(s.action) - } - })), - { - key: 'k', - ctrl: true, - description: 'Search', - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Search shortcut triggered') - setSearchOpen(true) - } - }, - { - key: '/', - ctrl: true, - description: 'Shortcuts', - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Shortcuts dialog triggered') - setShortcutsOpen(true) - } - }, - { - key: 'p', - ctrl: true, - description: 'Preview', - action: () => { - console.log('[APP_ROUTER] โŒจ๏ธ Preview shortcut triggered') - setPreviewOpen(true) - } - }, - ]) - console.log('[APP_ROUTER] โœ… Keyboard shortcuts configured') - - const getCurrentProject = () => ({ - name: nextjsConfig.appName, - files, - models, - components, - componentTrees, - workflows, - lambdas, - theme, - playwrightTests, - storybookStories, - unitTests, - flaskConfig, - nextjsConfig, - npmSettings, - featureToggles, - }) - - const handleProjectLoad = (project: any) => { - console.log('[APP_ROUTER] ๐Ÿ“ฆ Loading project:', project.name) - 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') - console.log('[APP_ROUTER] โœ… Project loaded successfully') - } - - useEffect(() => { - console.log('[APP_ROUTER] ๐Ÿ“ Route changed to:', location.pathname, '- Page:', currentPage) - }, [location, currentPage]) - - console.log('[APP_ROUTER] ๐ŸŽจ Rendering AppLayout UI') - - return ( - - - - - }> - - - - - - -
- { - console.log('[APP_ROUTER] ๐Ÿ” Search opened') - setSearchOpen(true) - }} - onShowShortcuts={() => { - console.log('[APP_ROUTER] โŒจ๏ธ Shortcuts dialog opened') - setShortcutsOpen(true) - }} - onGenerateAI={() => { - console.log('[APP_ROUTER] ๐Ÿค– AI generation requested') - toast.info('AI generation coming soon') - }} - onExport={() => { - console.log('[APP_ROUTER] ๐Ÿ“ค Export requested') - toast.info('Export coming soon') - }} - onPreview={() => { - console.log('[APP_ROUTER] ๐Ÿ‘๏ธ Preview opened') - setPreviewOpen(true) - }} - onShowErrors={() => { - console.log('[APP_ROUTER] โš ๏ธ Navigating to errors page') - navigateToPage('errors') - }} - /> -
- -
-
-
- - - { - console.log('[APP_ROUTER] ๐Ÿ” Search navigation to:', page) - navigateToPage(page) - }} - onFileSelect={(fileId) => { - console.log('[APP_ROUTER] ๐Ÿ“„ File selected from search:', fileId) - setActiveFileId(fileId) - navigateToPage('code') - }} - /> - - - - - - - - - - - -
- ) +export default function App() { + return } - -function App() { - console.log('[APP_ROUTER] ๐Ÿ”ง Initializing App component') - console.time('[APP_ROUTER] App render') - - console.log('[APP_ROUTER] ๐ŸŒฑ Initializing seed data hook') - const { loadSeedData } = useSeedData() - const { loadComponentTrees } = useComponentTreeLoader() - const projectState = useProjectState() - const { featureToggles, files, setFiles, ...restState } = projectState - console.log('[APP_ROUTER] โœ… Hooks initialized') - - console.log('[APP_ROUTER] ๐Ÿ“ Initializing file operations for router context') - const fileOps = useFileOperations(files, setFiles) - - const [appReady, setAppReady] = useState(false) - console.log('[APP_ROUTER] ๐Ÿ’พ App ready state:', appReady) - - console.log('[APP_ROUTER] โฐ Setting up initialization effect') - useEffect(() => { - console.log('[APP_ROUTER] ๐Ÿš€ Initialization effect triggered') - console.time('[APP_ROUTER] Seed data loading') - - const timer = setTimeout(() => { - console.log('[APP_ROUTER] โฑ๏ธ Fallback timer triggered (100ms)') - setAppReady(true) - }, 100) - - console.log('[APP_ROUTER] ๐Ÿ“ฅ Starting seed data load') - loadSeedData() - .then(() => { - console.log('[APP_ROUTER] โœ… Seed data loaded successfully') - console.log('[APP_ROUTER] ๐Ÿ“ฆ Loading component trees from JSON') - return loadComponentTrees() - }) - .then(() => { - console.log('[APP_ROUTER] โœ… Component trees loaded successfully') - }) - .catch(err => { - console.error('[APP_ROUTER] โŒ Seed data loading failed:', err) - }) - .finally(() => { - console.log('[APP_ROUTER] ๐Ÿ Seed data loading complete') - clearTimeout(timer) - setAppReady(true) - console.timeEnd('[APP_ROUTER] Seed data loading') - console.log('[APP_ROUTER] โœ… App marked as ready') - - console.log('[APP_ROUTER] ๐Ÿš€ Preloading critical components') - preloadCriticalComponents() - }) - - return () => { - console.log('[APP_ROUTER] ๐Ÿงน Cleaning up initialization effect') - clearTimeout(timer) - } - }, [loadSeedData, loadComponentTrees]) - - const stateContext = { - files, - ...restState, - activeFileId: fileOps.activeFileId, - } - - const actionContext = { - handleFileChange: fileOps.handleFileChange, - setActiveFileId: fileOps.setActiveFileId, - handleFileClose: fileOps.handleFileClose, - handleFileAdd: fileOps.handleFileAdd, - setFiles, - ...Object.fromEntries( - Object.entries(restState).filter(([key]) => key.startsWith('set')) - ), - } - - console.log('[APP_ROUTER] ๐ŸŽจ Rendering App component UI') - console.log('[APP_ROUTER] App state - appReady:', appReady) - console.timeEnd('[APP_ROUTER] App render') - - if (!appReady) { - console.log('[APP_ROUTER] โณ App not ready, showing loading screen') - return ( -
-
-
-

Loading CodeForge...

-
-
- ) - } - - console.log('[APP_ROUTER] โœ… App ready, rendering router') - return ( - - - - ) -} - -console.log('[APP_ROUTER] โœ… App component defined') -console.timeEnd('[APP_ROUTER] Component initialization') - -export default App diff --git a/src/components/app/AppBootstrap.tsx b/src/components/app/AppBootstrap.tsx new file mode 100644 index 0000000..5474945 --- /dev/null +++ b/src/components/app/AppBootstrap.tsx @@ -0,0 +1,45 @@ +import { useEffect, useState } from 'react' +import { BrowserRouter } from 'react-router-dom' + +import AppLayout from '@/components/app/AppLayout' +import LoadingScreen from '@/components/app/LoadingScreen' +import { useComponentTreeLoader } from '@/hooks/use-component-tree-loader' +import { useSeedData } from '@/hooks/data/use-seed-data' +import { preloadCriticalComponents } from '@/lib/component-registry' + +export default function AppBootstrap() { + const { loadSeedData } = useSeedData() + const { loadComponentTrees } = useComponentTreeLoader() + const [appReady, setAppReady] = useState(false) + + useEffect(() => { + const timer = setTimeout(() => { + setAppReady(true) + }, 100) + + loadSeedData() + .then(() => loadComponentTrees()) + .catch(err => { + console.error('[APP_ROUTER] โŒ Seed data loading failed:', err) + }) + .finally(() => { + clearTimeout(timer) + setAppReady(true) + preloadCriticalComponents() + }) + + return () => { + clearTimeout(timer) + } + }, [loadSeedData, loadComponentTrees]) + + if (!appReady) { + return + } + + return ( + + + + ) +} diff --git a/src/components/app/AppDialogs.tsx b/src/components/app/AppDialogs.tsx new file mode 100644 index 0000000..588d52a --- /dev/null +++ b/src/components/app/AppDialogs.tsx @@ -0,0 +1,89 @@ +import { Suspense } from 'react' + +import { DialogRegistry, PWARegistry } from '@/lib/component-registry' +import type { + ComponentNode, + ComponentTree, + Lambda, + PlaywrightTest, + PrismaModel, + ProjectFile, + StorybookStory, + UnitTest, + Workflow, +} from '@/types/project' + +const { GlobalSearch, KeyboardShortcutsDialog, PreviewDialog } = DialogRegistry +const { PWAInstallPrompt } = PWARegistry + +interface AppDialogsProps { + searchOpen: boolean + onSearchOpenChange: (open: boolean) => void + shortcutsOpen: boolean + onShortcutsOpenChange: (open: boolean) => void + previewOpen: boolean + onPreviewOpenChange: (open: boolean) => void + files: ProjectFile[] + models: PrismaModel[] + components: ComponentNode[] + componentTrees: ComponentTree[] + workflows: Workflow[] + lambdas: Lambda[] + playwrightTests: PlaywrightTest[] + storybookStories: StorybookStory[] + unitTests: UnitTest[] + onNavigate: (page: string) => void + onFileSelect: (fileId: string) => void +} + +export default function AppDialogs({ + searchOpen, + onSearchOpenChange, + shortcutsOpen, + onShortcutsOpenChange, + previewOpen, + onPreviewOpenChange, + files, + models, + components, + componentTrees, + workflows, + lambdas, + playwrightTests, + storybookStories, + unitTests, + onNavigate, + onFileSelect, +}: AppDialogsProps) { + return ( + <> + + + + + + + + + + + + + + + ) +} diff --git a/src/components/app/AppLayout.tsx b/src/components/app/AppLayout.tsx new file mode 100644 index 0000000..1fb0ef0 --- /dev/null +++ b/src/components/app/AppLayout.tsx @@ -0,0 +1,92 @@ +import { useState } from 'react' +import { toast } from 'sonner' + +import AppDialogs from '@/components/app/AppDialogs' +import AppMainPanel from '@/components/app/AppMainPanel' +import { NavigationMenu } from '@/components/organisms/NavigationMenu' +import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar' +import appStrings from '@/data/app-shortcuts.json' +import useAppNavigation from '@/hooks/use-app-navigation' +import useAppProject from '@/hooks/use-app-project' +import useAppShortcuts from '@/hooks/use-app-shortcuts' + +export default function AppLayout() { + const { currentPage, navigateToPage } = useAppNavigation() + const { + files, + models, + components, + componentTrees, + workflows, + lambdas, + playwrightTests, + storybookStories, + unitTests, + featureToggles, + fileOps, + currentProject, + handleProjectLoad, + stateContext, + actionContext, + } = useAppProject() + const { searchOpen, setSearchOpen, shortcutsOpen, setShortcutsOpen, previewOpen, setPreviewOpen } = + useAppShortcuts({ featureToggles, navigateToPage }) + const [lastSaved] = useState(() => Date.now()) + const [errorCount] = useState(0) + + return ( + + + + +
+ setSearchOpen(true)} + onShowShortcuts={() => setShortcutsOpen(true)} + onGenerateAI={() => toast.info(appStrings.messages.aiComingSoon)} + onExport={() => toast.info(appStrings.messages.exportComingSoon)} + onPreview={() => setPreviewOpen(true)} + onShowErrors={() => navigateToPage('errors')} + stateContext={stateContext} + actionContext={actionContext} + /> +
+
+ + { + fileOps.setActiveFileId(fileId) + navigateToPage('code') + }} + /> +
+ ) +} diff --git a/src/components/app/AppMainPanel.tsx b/src/components/app/AppMainPanel.tsx new file mode 100644 index 0000000..18708d7 --- /dev/null +++ b/src/components/app/AppMainPanel.tsx @@ -0,0 +1,77 @@ +import { Suspense } from 'react' + +import { AppHeader } from '@/components/organisms' +import { PWARegistry } from '@/lib/component-registry' +import { RouterProvider } from '@/router' +import type { FeatureToggles, Project } from '@/types/project' + +const { PWAUpdatePrompt, PWAStatusBar } = PWARegistry + +interface AppMainPanelProps { + currentPage: string + navigateToPage: (page: string) => void + featureToggles: FeatureToggles + errorCount: number + lastSaved: number | null + currentProject: Project + onProjectLoad: (project: Project) => void + onSearch: () => void + onShowShortcuts: () => void + onGenerateAI: () => void + onExport: () => void + onPreview: () => void + onShowErrors: () => void + stateContext: any + actionContext: any +} + +export default function AppMainPanel({ + currentPage, + navigateToPage, + featureToggles, + errorCount, + lastSaved, + currentProject, + onProjectLoad, + onSearch, + onShowShortcuts, + onGenerateAI, + onExport, + onPreview, + onShowErrors, + stateContext, + actionContext, +}: AppMainPanelProps) { + return ( + <> + }> + + + + + + +
+ +
+ + ) +} diff --git a/src/components/app/AppRouterBootstrap.tsx b/src/components/app/AppRouterBootstrap.tsx new file mode 100644 index 0000000..83cb1f7 --- /dev/null +++ b/src/components/app/AppRouterBootstrap.tsx @@ -0,0 +1,42 @@ +import { useEffect, useState } from 'react' +import { BrowserRouter } from 'react-router-dom' + +import AppRouterLayout from '@/components/app/AppRouterLayout' +import LoadingScreen from '@/components/app/LoadingScreen' +import { useSeedData } from '@/hooks/data/use-seed-data' +import { preloadCriticalComponents } from '@/lib/component-registry' + +export default function AppRouterBootstrap() { + const { loadSeedData } = useSeedData() + const [appReady, setAppReady] = useState(false) + + useEffect(() => { + const timer = setTimeout(() => { + setAppReady(true) + }, 100) + + loadSeedData() + .catch(err => { + console.error('[APP_ROUTER] โŒ Seed data loading failed:', err) + }) + .finally(() => { + clearTimeout(timer) + setAppReady(true) + preloadCriticalComponents() + }) + + return () => { + clearTimeout(timer) + } + }, [loadSeedData]) + + if (!appReady) { + return + } + + return ( + + + + ) +} diff --git a/src/components/app/AppRouterLayout.tsx b/src/components/app/AppRouterLayout.tsx new file mode 100644 index 0000000..e097dbc --- /dev/null +++ b/src/components/app/AppRouterLayout.tsx @@ -0,0 +1,79 @@ +import { useState } from 'react' +import { toast } from 'sonner' + +import AppDialogs from '@/components/app/AppDialogs' +import AppMainPanel from '@/components/app/AppMainPanel' +import appStrings from '@/data/app-shortcuts.json' +import useAppNavigation from '@/hooks/use-app-navigation' +import useAppProject from '@/hooks/use-app-project' +import useAppShortcuts from '@/hooks/use-app-shortcuts' + +export default function AppRouterLayout() { + const { currentPage, navigateToPage } = useAppNavigation() + const { + files, + models, + components, + componentTrees, + workflows, + lambdas, + playwrightTests, + storybookStories, + unitTests, + featureToggles, + fileOps, + currentProject, + handleProjectLoad, + stateContext, + actionContext, + } = useAppProject() + const { searchOpen, setSearchOpen, shortcutsOpen, setShortcutsOpen, previewOpen, setPreviewOpen } = + useAppShortcuts({ featureToggles, navigateToPage }) + const [lastSaved] = useState(() => Date.now()) + const [errorCount] = useState(0) + + return ( +
+ setSearchOpen(true)} + onShowShortcuts={() => setShortcutsOpen(true)} + onGenerateAI={() => toast.info(appStrings.messages.aiComingSoon)} + onExport={() => toast.info(appStrings.messages.exportComingSoon)} + onPreview={() => setPreviewOpen(true)} + onShowErrors={() => navigateToPage('errors')} + stateContext={stateContext} + actionContext={actionContext} + /> + + { + fileOps.setActiveFileId(fileId) + navigateToPage('code') + }} + /> +
+ ) +} diff --git a/src/components/app/LoadingScreen.tsx b/src/components/app/LoadingScreen.tsx new file mode 100644 index 0000000..e571621 --- /dev/null +++ b/src/components/app/LoadingScreen.tsx @@ -0,0 +1,16 @@ +import appStrings from '@/data/app-shortcuts.json' + +interface LoadingScreenProps { + message?: string +} + +export default function LoadingScreen({ message = appStrings.messages.loading }: LoadingScreenProps) { + return ( +
+
+
+

{message}

+
+
+ ) +} diff --git a/src/data/app-shortcuts.json b/src/data/app-shortcuts.json new file mode 100644 index 0000000..25dad1c --- /dev/null +++ b/src/data/app-shortcuts.json @@ -0,0 +1,13 @@ +{ + "shortcuts": { + "search": "Search", + "shortcuts": "Shortcuts", + "preview": "Preview" + }, + "messages": { + "loading": "Loading CodeForge...", + "projectLoaded": "Project loaded", + "aiComingSoon": "AI generation coming soon", + "exportComingSoon": "Export coming soon" + } +} diff --git a/src/hooks/use-app-navigation.ts b/src/hooks/use-app-navigation.ts new file mode 100644 index 0000000..79c4d13 --- /dev/null +++ b/src/hooks/use-app-navigation.ts @@ -0,0 +1,15 @@ +import { useEffect } from 'react' +import { useLocation } from 'react-router-dom' + +import { useRouterNavigation } from '@/hooks/use-router-navigation' + +export default function useAppNavigation() { + const location = useLocation() + const { currentPage, navigateToPage } = useRouterNavigation() + + useEffect(() => { + console.log('[APP_ROUTER] ๐Ÿ“ Route changed to:', location.pathname, '- Page:', currentPage) + }, [currentPage, location.pathname]) + + return { currentPage, navigateToPage } +} diff --git a/src/hooks/use-app-project.ts b/src/hooks/use-app-project.ts new file mode 100644 index 0000000..debe2b9 --- /dev/null +++ b/src/hooks/use-app-project.ts @@ -0,0 +1,147 @@ +import { useMemo } from 'react' +import { toast } from 'sonner' +import appStrings from '@/data/app-shortcuts.json' +import { useFileOperations } from '@/hooks/use-file-operations' +import { useProjectState } from '@/hooks/use-project-state' +import type { Project } from '@/types/project' +export default function useAppProject() { + const projectState = useProjectState() + 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, + } = projectState + + const fileOps = useFileOperations(files, setFiles) + const currentProject = useMemo( + () => ({ + name: nextjsConfig.appName, + files, + models, + components, + componentTrees, + workflows, + lambdas, + theme, + playwrightTests, + storybookStories, + unitTests, + flaskConfig, + nextjsConfig, + npmSettings, + featureToggles, + }), + [ + componentTrees, + components, + featureToggles, + files, + flaskConfig, + lambdas, + models, + nextjsConfig, + npmSettings, + playwrightTests, + storybookStories, + theme, + unitTests, + workflows, + ] + ) + const handleProjectLoad = (project: Project) => { + 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(appStrings.messages.projectLoaded) + } + const stateContext = { + files, + models, + components, + componentTrees, + workflows, + lambdas, + theme, + playwrightTests, + storybookStories, + unitTests, + flaskConfig, + nextjsConfig, + npmSettings, + featureToggles, + activeFileId: fileOps.activeFileId, + } + const actionContext = { + handleFileChange: fileOps.handleFileChange, + setActiveFileId: fileOps.setActiveFileId, + handleFileClose: fileOps.handleFileClose, + handleFileAdd: fileOps.handleFileAdd, + setModels, + setComponents, + setComponentTrees, + setWorkflows, + setLambdas, + setTheme, + setPlaywrightTests, + setStorybookStories, + setUnitTests, + setFlaskConfig, + setNextjsConfig, + setNpmSettings, + setFeatureToggles, + } + + return { + files, + models, + components, + componentTrees, + workflows, + lambdas, + playwrightTests, + storybookStories, + unitTests, + featureToggles, + fileOps, + currentProject, + handleProjectLoad, + stateContext, + actionContext, + } +} diff --git a/src/hooks/use-app-shortcuts.ts b/src/hooks/use-app-shortcuts.ts new file mode 100644 index 0000000..b6cbcde --- /dev/null +++ b/src/hooks/use-app-shortcuts.ts @@ -0,0 +1,71 @@ +import { useState } from 'react' + +import appStrings from '@/data/app-shortcuts.json' +import { getPageShortcuts } from '@/config/page-loader' +import { useKeyboardShortcuts } from '@/hooks/use-keyboard-shortcuts' +import type { FeatureToggles } from '@/types/project' + +interface UseAppShortcutsParams { + featureToggles: FeatureToggles + navigateToPage: (page: string) => void +} + +export default function useAppShortcuts({ + featureToggles, + navigateToPage, +}: UseAppShortcutsParams) { + const [searchOpen, setSearchOpen] = useState(false) + const [shortcutsOpen, setShortcutsOpen] = useState(false) + const [previewOpen, setPreviewOpen] = useState(false) + + const shortcuts = getPageShortcuts(featureToggles) + + useKeyboardShortcuts([ + ...shortcuts.map(s => ({ + key: s.key, + ctrl: s.ctrl, + shift: s.shift, + description: s.description, + action: () => { + console.log('[APP_ROUTER] โŒจ๏ธ Shortcut triggered, navigating to:', s.action) + navigateToPage(s.action) + }, + })), + { + key: 'k', + ctrl: true, + description: appStrings.shortcuts.search, + action: () => { + console.log('[APP_ROUTER] โŒจ๏ธ Search shortcut triggered') + setSearchOpen(true) + }, + }, + { + key: '/', + ctrl: true, + description: appStrings.shortcuts.shortcuts, + action: () => { + console.log('[APP_ROUTER] โŒจ๏ธ Shortcuts dialog triggered') + setShortcutsOpen(true) + }, + }, + { + key: 'p', + ctrl: true, + description: appStrings.shortcuts.preview, + action: () => { + console.log('[APP_ROUTER] โŒจ๏ธ Preview shortcut triggered') + setPreviewOpen(true) + }, + }, + ]) + + return { + searchOpen, + setSearchOpen, + shortcutsOpen, + setShortcutsOpen, + previewOpen, + setPreviewOpen, + } +}