/** * ApprovalCard - 核鑰授權卡片 * ============================ * Phase 19.5 - Nuclear Key UX 整合 * * 高風險操作需要儀式感授權: * - 長按確認 (NuclearKeyButton) * - 風險等級視覺化 * - 支援 Y 鍵快捷鍵 * * @see ADR-032 GenUI Dynamic Rendering * @see AWOOOI_AGENTIC_WORKSPACE_ROADMAP.md - Nuclear Key UX * @author Claude Code (首席架構師) * @version 2.0.0 - Nuclear Key 整合 * @date 2026-03-28 (台北時間) */ import React, { useState, useCallback } from 'react' import { ShieldAlert, Terminal, Clock, User } from 'lucide-react' import { useTranslations } from 'next-intl' import { NuclearKeyButton } from './NuclearKeyButton' interface ApprovalCardProps { data: { approvalId: string riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL' kubectl: string requestedBy?: string requestedAt?: string description?: string } } /** 風險等級映射 (API → NuclearKeyButton) */ const mapRiskLevel = (level: string): 'low' | 'medium' | 'high' | 'critical' => { const mapping: Record = { LOW: 'low', MEDIUM: 'medium', HIGH: 'high', CRITICAL: 'critical', } return mapping[level] ?? 'medium' } export const ApprovalCard: React.FC = ({ data }) => { const t = useTranslations('nuclearKey') const tApproval = useTranslations('approval') const [isExecuting, setIsExecuting] = useState(false) const [executionResult, setExecutionResult] = useState<'success' | 'error' | null>(null) const isCritical = data.riskLevel === 'CRITICAL' || data.riskLevel === 'HIGH' const nuclearRiskLevel = mapRiskLevel(data.riskLevel) const handleAuthorize = useCallback(async () => { setIsExecuting(true) setExecutionResult(null) try { // 實際呼叫審批 API const response = await fetch(`/api/v1/approvals/${data.approvalId}/execute`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, }) if (response.ok) { setExecutionResult('success') } else { setExecutionResult('error') } } catch { setExecutionResult('error') } finally { setIsExecuting(false) } }, [data.approvalId]) return (
{/* Header - Responsive layout */}
Approval Required // {data.approvalId}
{data.riskLevel}
{/* Metadata */} {(data.requestedBy || data.requestedAt) && (
{data.requestedBy && (
{data.requestedBy}
)} {data.requestedAt && (
{data.requestedAt}
)}
)} {/* Description */} {data.description && (

{data.description}

)} {/* Target Action */}
{data.kubectl}
{/* Nuclear Key Authorization */}
{executionResult === 'success' ? (
{t('executionAuthorized')} {t('authorized')}
) : executionResult === 'error' ? (
{t('executionFailed')}
) : ( )}
) } const Label = ({ children }: { children: React.ReactNode }) => ( {children} )