'use client'; import { useEffect, useState, useCallback } from 'react'; import Link from 'next/link'; const API_BASE = process.env.NEXT_PUBLIC_API_BASE ?? 'https://cypher.arcrun.dev'; type User = { email: string; display_name: string; avatar_url?: string; api_key: string; provider: string; created_at: string; }; export default function DashboardPage() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [copied, setCopied] = useState(false); const [rotating, setRotating] = useState(false); const [revoking, setRevoking] = useState(false); const [error, setError] = useState(''); const [showKey, setShowKey] = useState(false); const fetchUser = useCallback(async () => { try { const res = await fetch(`${API_BASE}/me`, { credentials: 'include' }); if (res.status === 401) { window.location.href = '/login?redirect=/dashboard'; return; } if (!res.ok) throw new Error('Failed to fetch user'); const data = await res.json() as User; setUser(data); } catch { setError('無法載入用戶資訊,請重新整理。'); } finally { setLoading(false); } }, []); useEffect(() => { fetchUser(); }, [fetchUser]); const copyKey = async () => { if (!user) return; await navigator.clipboard.writeText(user.api_key); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const rotateKey = async () => { if (!confirm('確定要 Rotate API Key 嗎?舊 Key 的 workflow credentials 不會自動遷移。')) return; setRotating(true); setError(''); try { const res = await fetch(`${API_BASE}/me/api-key/rotate`, { method: 'PUT', credentials: 'include', }); if (!res.ok) throw new Error('rotate failed'); const data = await res.json() as { api_key: string; message: string }; setUser(prev => prev ? { ...prev, api_key: data.api_key } : null); setShowKey(true); } catch { setError('Rotate 失敗,請稍後重試。'); } finally { setRotating(false); } }; const revokeKey = async () => { if (!confirm('確定要 Revoke API Key 嗎?所有使用此 Key 的服務將立即失效。')) return; setRevoking(true); setError(''); try { const res = await fetch(`${API_BASE}/me/api-key`, { method: 'DELETE', credentials: 'include', }); if (!res.ok) throw new Error('revoke failed'); window.location.href = '/login?revoked=1'; } catch { setError('Revoke 失敗,請稍後重試。'); } finally { setRevoking(false); } }; const logout = async () => { await fetch(`${API_BASE}/auth/logout`, { method: 'POST', credentials: 'include' }); window.location.href = '/'; }; if (loading) { return (
載入中...
); } if (!user) { return (

{error || '請先登入。'}

前往登入
); } const maskedKey = showKey ? user.api_key : user.api_key.slice(0, 8) + '••••••••••••••••••••••••'; return (
{/* Nav */}

歡迎,{user.display_name}

登入方式:{user.provider} · 帳號建立於 {new Date(user.created_at).toLocaleDateString('zh-TW')}

{error && (
{error}
)} {/* API Key Card */}

您的 API Key

{maskedKey}
# 使用方式
Authorization: Bearer {user.api_key.slice(0, 8)}...
# 或
X-Arcrun-API-Key: {user.api_key.slice(0, 8)}...
{/* Quick Start */}

快速開始

1.
安裝 CLI
npm install -g arcrun
2.
初始化(已有 API Key 可直接輸入)
acr init
3.
設定服務認證
acr auth-recipe scaffold notion
查看 20 個支援服務 → API 文件 →
); }