mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-26 22:54:54 +00:00
Generated by Spark: half the app is gone, it was a code gen
This commit is contained in:
517
src/App.tsx
517
src/App.tsx
@@ -1,138 +1,403 @@
|
||||
import { useState } from 'react'
|
||||
import { useKV } from '@github/spark/hooks'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet'
|
||||
import { List, Stack, House, Wrench } from '@phosphor-icons/react'
|
||||
import { DockerBuildDebugger } from '@/components/DockerBuildDebugger'
|
||||
import { motion } from 'framer-motion'
|
||||
console.log('[APP_ROUTER] 🚀 App.router.tsx loading - BEGIN')
|
||||
console.time('[APP_ROUTER] Component initialization')
|
||||
|
||||
type View = 'home' | 'docker-debugger'
|
||||
import { useState, Suspense, useEffect } from 'react'
|
||||
console.log('[APP_ROUTER] ✅ React hooks imported')
|
||||
|
||||
function App() {
|
||||
const [currentView, setCurrentView] = useKV<View>('current-view', 'home')
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
||||
import { BrowserRouter, useLocation } from 'react-router-dom'
|
||||
console.log('[APP_ROUTER] ✅ React Router imported')
|
||||
|
||||
const handleNavigation = (view: View) => {
|
||||
setCurrentView(view)
|
||||
setIsMenuOpen(false)
|
||||
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<number | null>(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 (
|
||||
<div className="min-h-screen bg-background">
|
||||
<div className="relative overflow-hidden">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-primary/20 via-background to-background" />
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#4f4f4f12_1px,transparent_1px),linear-gradient(to_bottom,#4f4f4f12_1px,transparent_1px)] bg-[size:4rem_4rem]" />
|
||||
|
||||
<div className="relative">
|
||||
<header className="border-b border-border/40 backdrop-blur-sm sticky top-0 z-40">
|
||||
<div className="container mx-auto px-4 sm:px-6 py-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-2 rounded-lg bg-primary/10 border border-primary/20">
|
||||
<Stack size={28} weight="bold" className="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-xl sm:text-2xl font-bold tracking-tight">DevTools Hub</h1>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground">Your developer toolkit</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Sheet open={isMenuOpen} onOpenChange={setIsMenuOpen}>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="outline" size="icon" className="gap-2">
|
||||
<List size={20} weight="bold" />
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent>
|
||||
<SheetHeader>
|
||||
<SheetTitle>Navigation</SheetTitle>
|
||||
</SheetHeader>
|
||||
<nav className="mt-6 space-y-2">
|
||||
<Button
|
||||
variant={currentView === 'home' ? 'secondary' : 'ghost'}
|
||||
className="w-full justify-start gap-3"
|
||||
onClick={() => handleNavigation('home')}
|
||||
>
|
||||
<House size={20} weight="bold" />
|
||||
Home
|
||||
</Button>
|
||||
<Button
|
||||
variant={currentView === 'docker-debugger' ? 'secondary' : 'ghost'}
|
||||
className="w-full justify-start gap-3"
|
||||
onClick={() => handleNavigation('docker-debugger')}
|
||||
>
|
||||
<Wrench size={20} weight="bold" />
|
||||
Docker Build Debugger
|
||||
</Button>
|
||||
</nav>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="container mx-auto px-4 sm:px-6 py-8">
|
||||
{currentView === 'home' && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="space-y-6"
|
||||
>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold mb-2">Welcome to DevTools Hub</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Select a tool from the menu to get started
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<Card
|
||||
className="border-border/50 bg-card/50 backdrop-blur-sm cursor-pointer hover:border-accent/50 hover:shadow-lg hover:shadow-accent/5 transition-all"
|
||||
onClick={() => handleNavigation('docker-debugger')}
|
||||
>
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="p-2 rounded-lg bg-accent/10 border border-accent/20">
|
||||
<Wrench size={24} weight="bold" className="text-accent" />
|
||||
</div>
|
||||
<CardTitle>Docker Build Debugger</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Analyze Docker build errors and get instant solutions with an intelligent knowledge base
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Paste your build logs and get detailed error analysis with recommended fixes
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{currentView === 'docker-debugger' && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<div className="mb-6">
|
||||
<h2 className="text-2xl font-bold mb-2">Docker Build Debugger</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Analyze errors and get instant solutions
|
||||
</p>
|
||||
</div>
|
||||
<DockerBuildDebugger />
|
||||
</motion.div>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
<div className="h-screen flex flex-col bg-background">
|
||||
<Suspense fallback={<div className="h-1 bg-primary animate-pulse" />}>
|
||||
<PWAStatusBar />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PWAUpdatePrompt />
|
||||
</Suspense>
|
||||
<AppHeader
|
||||
activeTab={currentPage}
|
||||
onTabChange={navigateToPage}
|
||||
featureToggles={featureToggles}
|
||||
errorCount={errorCount}
|
||||
lastSaved={lastSaved}
|
||||
currentProject={getCurrentProject()}
|
||||
onProjectLoad={handleProjectLoad}
|
||||
onSearch={() => {
|
||||
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')
|
||||
}}
|
||||
/>
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<RouterProvider
|
||||
featureToggles={featureToggles}
|
||||
stateContext={{
|
||||
files,
|
||||
models,
|
||||
components,
|
||||
componentTrees,
|
||||
workflows,
|
||||
lambdas,
|
||||
theme,
|
||||
playwrightTests,
|
||||
storybookStories,
|
||||
unitTests,
|
||||
flaskConfig,
|
||||
nextjsConfig,
|
||||
npmSettings,
|
||||
featureToggles,
|
||||
activeFileId,
|
||||
}}
|
||||
actionContext={{
|
||||
handleFileChange,
|
||||
setActiveFileId,
|
||||
handleFileClose,
|
||||
handleFileAdd,
|
||||
setModels,
|
||||
setComponents,
|
||||
setComponentTrees,
|
||||
setWorkflows,
|
||||
setLambdas,
|
||||
setTheme,
|
||||
setPlaywrightTests,
|
||||
setStorybookStories,
|
||||
setUnitTests,
|
||||
setFlaskConfig,
|
||||
setNextjsConfig,
|
||||
setNpmSettings,
|
||||
setFeatureToggles,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
<GlobalSearch
|
||||
open={searchOpen}
|
||||
onOpenChange={setSearchOpen}
|
||||
files={files}
|
||||
models={models}
|
||||
components={components}
|
||||
componentTrees={componentTrees}
|
||||
workflows={workflows}
|
||||
lambdas={lambdas}
|
||||
playwrightTests={playwrightTests}
|
||||
storybookStories={storybookStories}
|
||||
unitTests={unitTests}
|
||||
onNavigate={(page) => {
|
||||
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')
|
||||
}}
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
<KeyboardShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PreviewDialog open={previewOpen} onOpenChange={setPreviewOpen} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PWAInstallPrompt />
|
||||
</Suspense>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
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 (
|
||||
<div className="fixed inset-0 bg-background z-50 flex items-center justify-center">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="w-12 h-12 border-4 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">Loading CodeForge...</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
console.log('[APP_ROUTER] ✅ App ready, rendering router')
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<AppLayout />
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
|
||||
console.log('[APP_ROUTER] ✅ App component defined')
|
||||
console.timeEnd('[APP_ROUTER] Component initialization')
|
||||
|
||||
export default App
|
||||
|
||||
@@ -355,6 +355,16 @@
|
||||
"shortcut": "ctrl+shift+d",
|
||||
"order": 24,
|
||||
"props": {}
|
||||
},
|
||||
{
|
||||
"id": "docker-debugger",
|
||||
"title": "Docker Debugger",
|
||||
"icon": "Wrench",
|
||||
"component": "DockerBuildDebugger",
|
||||
"enabled": true,
|
||||
"toggleKey": "dockerDebugger",
|
||||
"order": 25,
|
||||
"props": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -151,6 +151,11 @@ export const ComponentRegistry = {
|
||||
() => import('@/components/DataBindingDesigner').then(m => ({ default: m.DataBindingDesigner })),
|
||||
'DataBindingDesigner'
|
||||
),
|
||||
|
||||
DockerBuildDebugger: lazyWithPreload(
|
||||
() => import('@/components/DockerBuildDebugger').then(m => ({ default: m.DockerBuildDebugger })),
|
||||
'DockerBuildDebugger'
|
||||
),
|
||||
} as const
|
||||
|
||||
export const DialogRegistry = {
|
||||
|
||||
Reference in New Issue
Block a user