diff --git a/apps/web/src/app/[locale]/authorizations/page.tsx b/apps/web/src/app/[locale]/authorizations/page.tsx
new file mode 100644
index 00000000..8b1ec701
--- /dev/null
+++ b/apps/web/src/app/[locale]/authorizations/page.tsx
@@ -0,0 +1,29 @@
+'use client'
+
+/**
+ * Authorizations Page - 授權中心
+ * ==============================
+ * Phase 7.0: 防禦性路由佔位
+ *
+ * Nothing.tech 空態設計:
+ * - 畫面正中央極簡文字
+ * - 等寬字體 + 淺灰色
+ */
+
+import { AppLayout } from '@/components/layout'
+
+export default function AuthorizationsPage({
+ params,
+}: {
+ params: { locale: string }
+}) {
+ return (
+
+
+
+ [ 授權中心建置中 / AUTHORIZATIONS_MODULE_UNDER_CONSTRUCTION ]
+
+
+
+ )
+}
diff --git a/apps/web/src/app/[locale]/knowledge-base/page.tsx b/apps/web/src/app/[locale]/knowledge-base/page.tsx
new file mode 100644
index 00000000..ceef3747
--- /dev/null
+++ b/apps/web/src/app/[locale]/knowledge-base/page.tsx
@@ -0,0 +1,29 @@
+'use client'
+
+/**
+ * Knowledge Base Page - 知識殿堂
+ * ==============================
+ * Phase 7.0: 防禦性路由佔位
+ *
+ * Nothing.tech 空態設計:
+ * - 畫面正中央極簡文字
+ * - 等寬字體 + 淺灰色
+ */
+
+import { AppLayout } from '@/components/layout'
+
+export default function KnowledgeBasePage({
+ params,
+}: {
+ params: { locale: string }
+}) {
+ return (
+
+
+
+ [ 知識殿堂建置中 / KNOWLEDGE_BASE_MODULE_UNDER_CONSTRUCTION ]
+
+
+
+ )
+}
diff --git a/apps/web/src/app/[locale]/settings/page.tsx b/apps/web/src/app/[locale]/settings/page.tsx
new file mode 100644
index 00000000..72b36f18
--- /dev/null
+++ b/apps/web/src/app/[locale]/settings/page.tsx
@@ -0,0 +1,29 @@
+'use client'
+
+/**
+ * Settings Page - 系統設定
+ * ========================
+ * Phase 7.0: 防禦性路由佔位
+ *
+ * Nothing.tech 空態設計:
+ * - 畫面正中央極簡文字
+ * - 等寬字體 + 淺灰色
+ */
+
+import { AppLayout } from '@/components/layout'
+
+export default function SettingsPage({
+ params,
+}: {
+ params: { locale: string }
+}) {
+ return (
+
+
+
+ [ 系統設定建置中 / SETTINGS_MODULE_UNDER_CONSTRUCTION ]
+
+
+
+ )
+}
diff --git a/apps/web/src/components/layout/sidebar.tsx b/apps/web/src/components/layout/sidebar.tsx
index 7cdd39fe..5e544c4e 100644
--- a/apps/web/src/components/layout/sidebar.tsx
+++ b/apps/web/src/components/layout/sidebar.tsx
@@ -1,24 +1,26 @@
'use client'
/**
- * Sidebar - 高透光玻璃側邊欄
- * ==========================
- * CPO-102: Nothing.tech 明亮工業風側邊導航
- * Phase 2.5: lucide-react 純代碼視覺 (符合第七章憲法)
+ * Sidebar - Phase 7.0 極簡五柱導航
+ * =================================
+ * Nothing.tech 視覺憲法:
+ * - 純白背景 (bg-white)
+ * - 極細右邊框 (border-r-[0.5px] border-neutral-200)
+ * - 無陰影
+ * - 單色圖示
*
- * Features:
- * - backdrop-blur 毛玻璃效果
- * - 固定寬度 (w-64)
- * - 折疊/展開動畫 - 機械爪開合意象
- * - i18n 導航標籤
- * - 當前路由高亮
- * - lucide-react 圖示 (無實體圖片依賴)
+ * 5 大核心樞紐:
+ * 1. 全局戰情室 (/)
+ * 2. 授權中心 (/authorizations) - 含動態徽章
+ * 3. 行動日誌 (/action-logs)
+ * 4. 知識殿堂 (/knowledge-base)
+ * 5. 系統設定 (/settings)
*/
-import { useCallback } from 'react'
+import { useEffect, useState } from 'react'
import { useTranslations } from 'next-intl'
import { usePathname } from 'next/navigation'
-import { StatusOrb } from '@/components/ui/status-orb'
+import Link from 'next/link'
import { cn } from '@/lib/utils'
import {
LayoutDashboard,
@@ -26,12 +28,10 @@ import {
Zap,
BookOpen,
Settings,
- Bot,
- Eye,
ChevronLeft,
ChevronRight,
- Sparkles,
} from 'lucide-react'
+import { apiClient } from '@/lib/api-client'
// =============================================================================
// Types
@@ -44,22 +44,23 @@ interface SidebarProps {
className?: string
}
-// =============================================================================
-// Navigation Items (using lucide-react icons)
-// =============================================================================
-
type NavItemConfig = {
id: string
href: string
labelKey: string
Icon: typeof LayoutDashboard
+ badge?: boolean // 是否顯示動態徽章
}
+// =============================================================================
+// Phase 7.0: 5 大核心樞紐
+// =============================================================================
+
const NAV_ITEMS: NavItemConfig[] = [
- { id: 'dashboard', href: '/demo', labelKey: 'dashboard', Icon: LayoutDashboard },
- { id: 'approvals', href: '/approvals', labelKey: 'approvals', Icon: ShieldCheck },
- { id: 'actions', href: '/action-logs', labelKey: 'actions', Icon: Zap },
- { id: 'knowledge', href: '/knowledge', labelKey: 'knowledge', Icon: BookOpen },
+ { id: 'warroom', href: '/', labelKey: 'dashboard', Icon: LayoutDashboard },
+ { id: 'authorizations', href: '/authorizations', labelKey: 'approvals', Icon: ShieldCheck, badge: true },
+ { id: 'action-logs', href: '/action-logs', labelKey: 'actions', Icon: Zap },
+ { id: 'knowledge-base', href: '/knowledge-base', labelKey: 'knowledge', Icon: BookOpen },
{ id: 'settings', href: '/settings', labelKey: 'settings', Icon: Settings },
]
@@ -75,11 +76,31 @@ export function Sidebar({
}: SidebarProps) {
const t = useTranslations('nav')
const tBrand = useTranslations('brand')
- const tClawbot = useTranslations('openclaw')
const pathname = usePathname()
+ const [pendingCount, setPendingCount] = useState(0)
+
+ // 載入待簽核數量 (動態徽章)
+ useEffect(() => {
+ const fetchPendingCount = async () => {
+ try {
+ const data = await apiClient.getPendingApprovals()
+ setPendingCount(data.count || 0)
+ } catch {
+ setPendingCount(0)
+ }
+ }
+
+ fetchPendingCount()
+ // 每 30 秒刷新
+ const interval = setInterval(fetchPendingCount, 30000)
+ return () => clearInterval(interval)
+ }, [])
const isActive = (href: string) => {
- const fullHref = `/${locale}${href}`
+ const fullHref = `/${locale}${href === '/' ? '' : href}`
+ if (href === '/') {
+ return pathname === `/${locale}` || pathname === `/${locale}/`
+ }
return pathname === fullHref || pathname.startsWith(fullHref + '/')
}
@@ -88,150 +109,111 @@ export function Sidebar({
className={cn(
'fixed left-0 top-0 h-screen z-40',
'flex flex-col',
- // 玻璃效果
- 'bg-white/70 backdrop-blur-[20px]',
- 'border-r border-black/[0.06]',
+ // Phase 7.0: 純白極簡
+ 'bg-white',
+ 'border-r-[0.5px] border-neutral-200',
// 寬度動畫
'transition-all duration-300 ease-out',
- collapsed ? 'w-16' : 'w-64',
+ collapsed ? 'w-16' : 'w-56',
className
)}
>
- {/* Logo - lucide-react + CSS Typography (第七章規範) */}
+ {/* Logo 區 - 極簡化 */}
-
- {/* Bot Icon + 呼吸燈效果 */}
-
-
-
-
- {/* Breathing indicator */}
-
-
-
-
-
-
- {/* 品牌字體排版 - i18n 規範 */}
- {!collapsed && (
-
-
- {tBrand('name')}
-
-
- {tBrand('version')} | {tBrand('tagline')}
-
-
- )}
-
+ {collapsed ? (
+
+ A
+
+ ) : (
+
+ {tBrand('name')}
+
+ )}
- {/* Navigation - lucide-react Icons */}
-