feat: add all application source code

- apps/api: FastAPI backend with Dockerfile
- apps/web: Next.js frontend with Dockerfile
- apps/sensor: Signal collection agent
- packages: shared packages

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
OG T
2026-03-22 18:57:44 +08:00
parent a840bf975b
commit 196d269b92
245 changed files with 42207 additions and 6 deletions

View File

@@ -0,0 +1,148 @@
'use client'
/**
* DataPincerCard - AWOOOI 數據鉗容器組件
* ========================================
* Nothing.tech 純白工業風視覺容器
*
* 視覺特徵:
* - awoooi-glass: 白玻璃毛玻璃效果
* - 極細灰色邊框 (border-nothing-mist)
* - 左側狀態指示細線 (無漸層、不遮蔽數據)
*
* i18n: 100% 使用 useTranslations禁止任何寫死字串
* 符合 AWOOOI L1 契約 - 視覺憲法
*/
import { type ReactNode } from 'react'
import { cn } from '@/lib/utils'
// ==================== Types ====================
export type CardStatus = 'healthy' | 'warning' | 'critical' | 'thinking' | 'idle'
interface DataPincerCardProps {
children: ReactNode
title?: string
status?: CardStatus
className?: string
/** 是否顯示左側狀態指示線 */
showStatusLine?: boolean
/** 卡片尺寸 */
size?: 'sm' | 'md' | 'lg'
}
// ==================== Config ====================
const statusLineColors: Record<CardStatus, string> = {
healthy: 'bg-status-healthy',
warning: 'bg-status-warning',
critical: 'bg-status-critical',
thinking: 'bg-status-thinking',
idle: 'bg-nothing-gray-300',
}
const sizeConfig = {
sm: 'p-3',
md: 'p-4',
lg: 'p-6',
}
// ==================== Component ====================
export function DataPincerCard({
children,
title,
status = 'idle',
className,
showStatusLine = true,
size = 'md',
}: DataPincerCardProps) {
return (
<div
className={cn(
// awoooi-glass 白玻璃效果
'relative overflow-hidden rounded-xl',
'bg-white/70 backdrop-blur-[16px]',
// 極細灰色邊框 (border-nothing-mist)
'border border-nothing-gray-200/60',
// 輕柔陰影
'shadow-[0_2px_12px_rgba(0,0,0,0.04)]',
// 尺寸
sizeConfig[size],
// 過渡動畫
'transition-all duration-200',
// Hover 效果
'hover:shadow-[0_4px_20px_rgba(0,0,0,0.06)]',
'hover:border-nothing-gray-300/80',
className
)}
>
{/* 左側狀態指示細線 - 無漸層、不遮蔽數據 */}
{showStatusLine && (
<div
className={cn(
'absolute left-0 top-0 bottom-0 w-1 rounded-l-xl',
statusLineColors[status],
// 思考狀態時呼吸動畫
status === 'thinking' && 'animate-pulse'
)}
/>
)}
{/* 標題 (如有) */}
{title && (
<div className="mb-4 pb-3 border-b border-nothing-gray-200/40">
<h3 className="font-mono text-xs uppercase tracking-wider text-ink-secondary">
{title}
</h3>
</div>
)}
{/* 內容 */}
<div className={cn(showStatusLine && 'pl-2')}>
{children}
</div>
</div>
)
}
// ==================== Variants ====================
/** 大型數據面板 */
export function DataPincerPanel({
children,
title,
status = 'idle',
className,
}: Omit<DataPincerCardProps, 'size' | 'showStatusLine'>) {
return (
<DataPincerCard
title={title}
status={status}
size="lg"
showStatusLine={true}
className={cn('min-h-[200px]', className)}
>
{children}
</DataPincerCard>
)
}
/** 緊湊型狀態卡片 */
export function DataPincerCompact({
children,
status = 'idle',
className,
}: Omit<DataPincerCardProps, 'size' | 'title'>) {
return (
<DataPincerCard
status={status}
size="sm"
showStatusLine={true}
className={className}
>
{children}
</DataPincerCard>
)
}

View File

@@ -0,0 +1,14 @@
/**
* AWOOOI Cyber Components
* =======================
* Nothing.tech 純白工業風視覺組件庫
*
* 命名規範: Data Pincer (數據鉗) 系列
*/
export {
DataPincerCard,
DataPincerPanel,
DataPincerCompact,
type CardStatus,
} from './data-pincer-card'