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 */} -