writekit/studio/src/App.tsx

93 lines
3.7 KiB
TypeScript
Raw Normal View History

2026-01-09 00:16:46 +02:00
import { lazy, Suspense } from 'react'
import { useStore } from '@nanostores/react'
import { $router } from './stores/router'
import { Sidebar, Header } from './components/layout'
import { Toasts } from './components/ui'
import { Icons } from './components/shared/Icons'
import {
PostsPageSkeleton,
AnalyticsPageSkeleton,
SettingsPageSkeleton,
GeneralPageSkeleton,
DesignPageSkeleton,
EngagementPageSkeleton,
APIPageSkeleton,
BillingPageSkeleton,
HomePageSkeleton,
} from './components/shared'
const HomePage = lazy(() => import('./pages/HomePage'))
const PostsPage = lazy(() => import('./pages/PostsPage'))
const PostEditorPage = lazy(() => import('./pages/PostEditorPage'))
const AnalyticsPage = lazy(() => import('./pages/AnalyticsPage'))
const GeneralPage = lazy(() => import('./pages/GeneralPage'))
const DesignPage = lazy(() => import('./pages/DesignPage'))
const DomainPage = lazy(() => import('./pages/DomainPage'))
const EngagementPage = lazy(() => import('./pages/EngagementPage'))
const MonetizationPage = lazy(() => import('./pages/MonetizationPage'))
const PluginsPage = lazy(() => import('./pages/PluginsPage'))
const APIPage = lazy(() => import('./pages/APIPage'))
const DataPage = lazy(() => import('./pages/DataPage'))
const BillingPage = lazy(() => import('./pages/BillingPage'))
const routes = {
home: { Component: HomePage, Skeleton: HomePageSkeleton },
postNew: { Component: PostEditorPage, Skeleton: SettingsPageSkeleton, fullWidth: true },
postEdit: { Component: PostEditorPage, Skeleton: SettingsPageSkeleton, fullWidth: true },
posts: { Component: PostsPage, Skeleton: PostsPageSkeleton },
analytics: { Component: AnalyticsPage, Skeleton: AnalyticsPageSkeleton },
general: { Component: GeneralPage, Skeleton: GeneralPageSkeleton },
design: { Component: DesignPage, Skeleton: DesignPageSkeleton },
domain: { Component: DomainPage, Skeleton: SettingsPageSkeleton },
engagement: { Component: EngagementPage, Skeleton: EngagementPageSkeleton },
monetization: { Component: MonetizationPage, Skeleton: SettingsPageSkeleton },
plugins: { Component: PluginsPage, Skeleton: SettingsPageSkeleton },
api: { Component: APIPage, Skeleton: APIPageSkeleton },
data: { Component: DataPage, Skeleton: SettingsPageSkeleton },
billing: { Component: BillingPage, Skeleton: BillingPageSkeleton },
} as const
function Router() {
const page = useStore($router)
const routeKey = page?.route ?? 'home'
const route = routes[routeKey as keyof typeof routes] || routes.home
const { Component: PageComponent, Skeleton } = route
return (
<Suspense fallback={<Skeleton />}>
<PageComponent />
</Suspense>
)
}
export default function App() {
const page = useStore($router)
const routeKey = page?.route ?? 'home'
const route = routes[routeKey as keyof typeof routes]
const isFullWidth = route && 'fullWidth' in route && route.fullWidth
return (
<div className="min-h-screen bg-bg text-text font-sans antialiased">
<Header className={isFullWidth ? 'hidden' : ''} />
<a
href="/"
target="_blank"
className={`fixed top-4 right-4 z-40 items-center gap-2 px-3 py-1.5 text-xs text-muted border border-border bg-surface hover:text-text hover:border-muted transition-colors ${isFullWidth ? 'hidden' : 'hidden lg:flex'}`}
>
<Icons.ExternalLink className="text-sm" />
<span>View Site</span>
</a>
<div className="flex">
<div className={`fixed left-0 top-0 h-screen ${isFullWidth ? 'hidden' : 'hidden lg:block'}`}>
<Sidebar />
</div>
<main className={isFullWidth ? 'flex-1' : 'flex-1 lg:ml-56 p-6 lg:p-10'}>
<Router />
</main>
</div>
<Toasts />
</div>
)
}