92 lines
3.7 KiB
TypeScript
92 lines
3.7 KiB
TypeScript
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>
|
|
)
|
|
}
|