diff --git a/frontend/src/app/App.tsx b/frontend/src/app/App.tsx
index 6edcc08..0aa4c3a 100644
--- a/frontend/src/app/App.tsx
+++ b/frontend/src/app/App.tsx
@@ -1,5 +1,10 @@
-import { DesignSystemPreview } from '@/features/design-system/DesignSystemPreview'
+import { AppShell } from './layout/AppShell'
+import { Router } from './router'
export function App() {
- return
+ return (
+
+
+
+ )
}
diff --git a/frontend/src/app/layout/AppShell.tsx b/frontend/src/app/layout/AppShell.tsx
index 5a77878..ca55491 100644
--- a/frontend/src/app/layout/AppShell.tsx
+++ b/frontend/src/app/layout/AppShell.tsx
@@ -13,7 +13,7 @@ export function AppShell({ children }: AppShellProps) {
- {children}
+ {children}
)
diff --git a/frontend/src/app/layout/Sidebar.tsx b/frontend/src/app/layout/Sidebar.tsx
index 193c256..8eaf12b 100644
--- a/frontend/src/app/layout/Sidebar.tsx
+++ b/frontend/src/app/layout/Sidebar.tsx
@@ -1,9 +1,27 @@
export function Sidebar() {
+ const navItems = [
+ { href: '#/tickets', label: 'Tickets' },
+ { href: '#/tickets/new', label: 'Create Ticket' },
+ { href: '#/solutions', label: 'Solutions' },
+ { href: '#/design-system', label: 'Design System' }
+ ]
+
return (
)
}
diff --git a/frontend/src/app/router.tsx b/frontend/src/app/router.tsx
index 1c57d86..eb33387 100644
--- a/frontend/src/app/router.tsx
+++ b/frontend/src/app/router.tsx
@@ -1,5 +1,30 @@
-import { App } from './App'
+import * as React from 'react'
+
+import { DesignSystemPreview } from '@/features/design-system/DesignSystemPreview'
+
+function getRoute() {
+ return window.location.hash.replace(/^#/, '') || '/tickets'
+}
export function Router() {
- return
+ const [route, setRoute] = React.useState(getRoute)
+
+ React.useEffect(() => {
+ const handleHashChange = () => setRoute(getRoute())
+ window.addEventListener('hashchange', handleHashChange)
+ return () => window.removeEventListener('hashchange', handleHashChange)
+ }, [])
+
+ if (route === '/design-system') {
+ return
+ }
+
+ return (
+
+
+
+ )
}
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts
new file mode 100644
index 0000000..8745e42
--- /dev/null
+++ b/frontend/src/lib/api.ts
@@ -0,0 +1,17 @@
+const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:8000/api'
+
+export async function apiRequest(path: string, init?: RequestInit): Promise {
+ const response = await fetch(`${API_BASE_URL}${path}`, {
+ headers: {
+ 'content-type': 'application/json',
+ ...init?.headers
+ },
+ ...init
+ })
+
+ if (!response.ok) {
+ throw new Error(`API request failed: ${response.status}`)
+ }
+
+ return response.json() as Promise
+}
diff --git a/frontend/src/lib/format.ts b/frontend/src/lib/format.ts
new file mode 100644
index 0000000..a1d2fe1
--- /dev/null
+++ b/frontend/src/lib/format.ts
@@ -0,0 +1,6 @@
+export function formatDateTime(value: string) {
+ return new Intl.DateTimeFormat('zh-CN', {
+ dateStyle: 'medium',
+ timeStyle: 'short'
+ }).format(new Date(value))
+}
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/frontend/src/vite-env.d.ts
@@ -0,0 +1 @@
+///