Files
ExecuBoard/app/page.tsx
2025-08-01 00:55:05 +08:00

447 lines
25 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState, useEffect } from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, ResponsiveContainer } from "recharts"
import {
TrendingUp,
TrendingDown,
Calendar,
AlertTriangle,
Target,
Users,
DollarSign,
Activity,
Zap,
Award,
} from "lucide-react"
import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
// 使用真實資料庫數據
import { KPI } from '@/lib/database'
// 預設 KPI 數據(當資料庫無數據時使用)
const defaultKpiData = [
{ id: '1', name: "營收成長率", current_value: 85, target_value: 100, category: "financial", weight: 30, color: "emerald" },
{ id: '2', name: "團隊滿意度", current_value: 92, target_value: 90, category: "team", weight: 25, color: "blue" },
{ id: '3', name: "市場佔有率", current_value: 68, target_value: 75, category: "operational", weight: 20, color: "purple" },
{ id: '4', name: "創新指數", current_value: 45, target_value: 80, category: "innovation", weight: 25, color: "orange" },
]
const teamRankingData = [
{ name: "業務部", performance: 95, color: "#10b981" },
{ name: "行銷部", performance: 88, color: "#3b82f6" },
{ name: "產品部", performance: 82, color: "#8b5cf6" },
{ name: "營運部", performance: 76, color: "#f59e0b" },
{ name: "人資部", performance: 71, color: "#ef4444" },
]
const reviewReminders = [
{
id: 1,
employee: "陳雅雯",
role: "業務副總",
dueDate: "2024-02-15",
type: "季度審查",
priority: "high",
color: "red",
},
{
id: 2,
employee: "王志明",
role: "技術長",
dueDate: "2024-02-18",
type: "一對一面談",
priority: "medium",
color: "yellow",
},
{
id: 3,
employee: "李美玲",
role: "行銷長",
dueDate: "2024-02-20",
type: "目標設定",
priority: "low",
color: "green",
},
]
const chartConfig = {
performance: {
label: "Performance %",
color: "hsl(var(--chart-1))",
},
}
function CircularProgress({ value, size = 120, color = "blue" }: { value: number; size?: number; color?: string }) {
const radius = (size - 20) / 2
const circumference = 2 * Math.PI * radius
const strokeDasharray = circumference
const strokeDashoffset = circumference - (value / 100) * circumference
const colorMap = {
emerald: value >= 70 ? "#10b981" : "#ef4444",
blue: value >= 70 ? "#3b82f6" : "#ef4444",
purple: value >= 70 ? "#8b5cf6" : "#ef4444",
orange: value >= 70 ? "#f59e0b" : "#ef4444",
}
return (
<div className="relative" style={{ width: size, height: size }}>
<svg width={size} height={size} className="transform -rotate-90">
<circle cx={size / 2} cy={size / 2} r={radius} stroke="#e5e7eb" strokeWidth="8" fill="none" />
<circle
cx={size / 2}
cy={size / 2}
r={radius}
stroke={colorMap[color as keyof typeof colorMap]}
strokeWidth="8"
fill="none"
strokeDasharray={strokeDasharray}
strokeDashoffset={strokeDashoffset}
strokeLinecap="round"
className="transition-all duration-1000 ease-out"
/>
</svg>
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-2xl font-bold text-gray-800">{value}%</span>
</div>
</div>
)
}
export default function Dashboard() {
const [mounted, setMounted] = useState(false)
const [kpiData, setKpiData] = useState<KPI[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
setMounted(true)
fetchKPIData()
}, [])
const fetchKPIData = async () => {
try {
setLoading(true)
// 使用預設用戶 ID實際應用中應該從認證系統獲取
const response = await fetch('/api/kpi?userId=user_admin')
if (response.ok) {
const data = await response.json()
setKpiData(data)
} else {
// 如果 API 失敗,使用預設數據
setKpiData(defaultKpiData as any)
}
} catch (error) {
console.error('獲取 KPI 數據失敗:', error)
setError('無法載入 KPI 數據')
// 使用預設數據
setKpiData(defaultKpiData as any)
} finally {
setLoading(false)
}
}
if (!mounted) return null
// 轉換數據格式以匹配 UI 需求
const displayKpiData = kpiData.map(kpi => ({
...kpi,
current: kpi.current_value,
target: kpi.target_value,
color: kpi.category === 'financial' ? 'emerald' :
kpi.category === 'team' ? 'blue' :
kpi.category === 'operational' ? 'purple' : 'orange'
}))
const underperformingKPIs = displayKpiData.filter((kpi) => kpi.current < 70)
const overallScore = Math.round(displayKpiData.reduce((acc, kpi) => acc + (kpi.current * kpi.weight) / 100, 0))
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 p-3 sm:p-6">
<div className="max-w-7xl mx-auto space-y-4 sm:space-y-6">
{/* Header */}
<div className="flex flex-col space-y-4 sm:flex-row sm:items-center sm:justify-between sm:space-y-0">
<div className="flex flex-col sm:flex-row sm:items-center space-y-2 sm:space-y-0 sm:space-x-4">
<img
src="data:image/png;base64,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"
alt="公司 Logo"
className="h-10 w-auto sm:h-12 md:hidden"
/>
<div>
<h1 className="text-xl sm:text-2xl lg:text-3xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
</h1>
<p className="text-sm sm:text-base text-gray-600 mt-1"> KPI </p>
</div>
</div>
<div className="flex flex-col sm:flex-row items-start sm:items-center space-y-2 sm:space-y-0 sm:space-x-4">
<Badge
variant="outline"
className={`text-sm sm:text-lg px-3 py-1 sm:px-4 sm:py-2 border-2 ${
overallScore >= 80
? "border-emerald-400 text-emerald-700 bg-emerald-50"
: overallScore >= 60
? "border-yellow-400 text-yellow-700 bg-yellow-50"
: "border-red-400 text-red-700 bg-red-50"
}`}
>
: {overallScore}%
</Badge>
<Avatar className="h-8 w-8 sm:h-10 sm:w-10 ring-2 ring-blue-200">
<AvatarImage src="/placeholder.svg?height=40&width=40" />
<AvatarFallback className="bg-gradient-to-br from-blue-500 to-purple-500 text-white">CEO</AvatarFallback>
</Avatar>
</div>
</div>
{/* Performance Alerts */}
{underperformingKPIs.length > 0 && (
<Alert className="border-red-200 bg-gradient-to-r from-red-50 to-pink-50 shadow-lg">
<AlertTriangle className="h-4 w-4 text-red-600" />
<AlertTitle className="text-red-800 font-semibold"></AlertTitle>
<AlertDescription className="text-red-700 text-sm sm:text-base">
{underperformingKPIs.length} KPI 70% : {underperformingKPIs.map((kpi) => kpi.name).join(", ")}
</AlertDescription>
</Alert>
)}
{/* KPI Overview Cards */}
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 sm:gap-6">
{loading ? (
// 載入中狀態
Array.from({ length: 4 }).map((_, index) => (
<Card key={index} className="relative overflow-hidden shadow-lg border-0 bg-gradient-to-br from-gray-50 to-gray-100">
<CardHeader className="pb-2">
<div className="animate-pulse">
<div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
<div className="h-3 bg-gray-200 rounded w-1/2"></div>
</div>
</CardHeader>
<CardContent className="flex flex-col items-center space-y-4">
<div className="animate-pulse">
<div className="w-24 h-24 bg-gray-200 rounded-full"></div>
</div>
</CardContent>
</Card>
))
) : (
displayKpiData.map((kpi) => (
<Card
key={kpi.id}
className={`relative overflow-hidden shadow-lg hover:shadow-xl transition-all duration-300 border-0 ${
kpi.color === "emerald"
? "bg-gradient-to-br from-emerald-50 to-green-100"
: kpi.color === "blue"
? "bg-gradient-to-br from-blue-50 to-cyan-100"
: kpi.color === "purple"
? "bg-gradient-to-br from-purple-50 to-violet-100"
: "bg-gradient-to-br from-orange-50 to-amber-100"
}`}
>
<CardHeader className="pb-2">
<div className="flex items-center justify-between">
<CardTitle className="text-sm font-medium text-gray-700">{kpi.name}</CardTitle>
<div
className={`p-2 rounded-full ${
kpi.category === "financial"
? "bg-emerald-100"
: kpi.category === "team"
? "bg-blue-100"
: kpi.category === "operational"
? "bg-purple-100"
: "bg-orange-100"
}`}
>
{kpi.category === "financial" && <DollarSign className="h-4 w-4 text-emerald-600" />}
{kpi.category === "team" && <Users className="h-4 w-4 text-blue-600" />}
{kpi.category === "operational" && <Activity className="h-4 w-4 text-purple-600" />}
{kpi.category === "innovation" && <Zap className="h-4 w-4 text-orange-600" />}
</div>
</div>
</CardHeader>
<CardContent className="flex flex-col items-center space-y-4">
<CircularProgress value={kpi.current} size={100} color={kpi.color} />
<div className="text-center space-y-1">
<div className="flex items-center justify-center space-x-2">
<span className="text-xs sm:text-sm text-gray-600">: {kpi.target}%</span>
{kpi.current >= kpi.target ? (
<TrendingUp className="h-3 w-3 sm:h-4 sm:w-4 text-emerald-500" />
) : (
<TrendingDown className="h-3 w-3 sm:h-4 sm:w-4 text-red-500" />
)}
</div>
<Badge
variant={kpi.current >= 70 ? "default" : "destructive"}
className={`text-xs ${
kpi.current >= 70
? "bg-gradient-to-r from-green-500 to-emerald-500"
: "bg-gradient-to-r from-red-500 to-pink-500"
}`}
>
: {kpi.weight}%
</Badge>
</div>
</CardContent>
</Card>
))
)}
</div>
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4 sm:gap-6">
{/* Team Performance Ranking */}
<Card className="shadow-lg bg-gradient-to-br from-white to-blue-50">
<CardHeader>
<CardTitle className="flex items-center space-x-2 text-base sm:text-lg">
<div className="p-2 bg-blue-100 rounded-full">
<Users className="h-4 w-4 sm:h-5 sm:w-5 text-blue-600" />
</div>
<span className="bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
</span>
</CardTitle>
<CardDescription className="text-sm text-gray-600"></CardDescription>
</CardHeader>
<CardContent>
<ChartContainer config={chartConfig} className="h-[250px] sm:h-[300px]">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={teamRankingData} layout="horizontal">
<CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
<XAxis type="number" domain={[0, 100]} />
<YAxis dataKey="name" type="category" width={60} className="text-xs sm:text-sm" />
<ChartTooltip content={<ChartTooltipContent />} />
<Bar dataKey="performance" fill={(entry) => entry.color} radius={[0, 8, 8, 0]} />
</BarChart>
</ResponsiveContainer>
</ChartContainer>
</CardContent>
</Card>
{/* Review Reminders */}
<Card className="shadow-lg bg-gradient-to-br from-white to-purple-50">
<CardHeader>
<CardTitle className="flex items-center space-x-2 text-base sm:text-lg">
<div className="p-2 bg-purple-100 rounded-full">
<Calendar className="h-4 w-4 sm:h-5 sm:w-5 text-purple-600" />
</div>
<span className="bg-gradient-to-r from-purple-600 to-pink-600 bg-clip-text text-transparent">
</span>
</CardTitle>
<CardDescription className="text-sm text-gray-600"></CardDescription>
</CardHeader>
<CardContent className="space-y-3 sm:space-y-4">
{reviewReminders.map((review) => (
<div
key={review.id}
className={`flex flex-col sm:flex-row sm:items-center sm:justify-between p-3 sm:p-4 border-l-4 rounded-lg hover:shadow-md transition-all duration-200 space-y-2 sm:space-y-0 ${
review.priority === "high"
? "border-red-400 bg-gradient-to-r from-red-50 to-pink-50"
: review.priority === "medium"
? "border-yellow-400 bg-gradient-to-r from-yellow-50 to-amber-50"
: "border-green-400 bg-gradient-to-r from-green-50 to-emerald-50"
}`}
>
<div className="flex items-center space-x-3">
<Avatar className="h-8 w-8 sm:h-10 sm:w-10 ring-2 ring-white shadow-md">
<AvatarImage src={`/placeholder.svg?height=40&width=40&text=${review.employee.charAt(0)}`} />
<AvatarFallback
className={`${
review.priority === "high"
? "bg-gradient-to-br from-red-400 to-pink-500"
: review.priority === "medium"
? "bg-gradient-to-br from-yellow-400 to-amber-500"
: "bg-gradient-to-br from-green-400 to-emerald-500"
} text-white`}
>
{review.employee.charAt(0) || "U"}
</AvatarFallback>
</Avatar>
<div>
<p className="font-medium text-gray-900 text-sm sm:text-base">{review.employee}</p>
<p className="text-xs sm:text-sm text-gray-600">{review.role}</p>
</div>
</div>
<div className="flex sm:flex-col items-start sm:items-end space-x-2 sm:space-x-0 sm:space-y-1">
<Badge
variant="outline"
className={`text-xs border-2 ${
review.priority === "high"
? "border-red-300 text-red-700 bg-red-50"
: review.priority === "medium"
? "border-yellow-300 text-yellow-700 bg-yellow-50"
: "border-green-300 text-green-700 bg-green-50"
}`}
>
{review.type}
</Badge>
<p className="text-xs sm:text-sm text-gray-600 font-medium">{review.dueDate}</p>
</div>
</div>
))}
<Button
className="w-full mt-4 bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white border-0 shadow-lg"
variant="outline"
>
</Button>
</CardContent>
</Card>
</div>
{/* Quick Actions */}
<Card className="shadow-lg bg-gradient-to-br from-white to-indigo-50">
<CardHeader>
<CardTitle className="text-base sm:text-lg flex items-center space-x-2">
<div className="p-2 bg-indigo-100 rounded-full">
<Award className="h-5 w-5 text-indigo-600" />
</div>
<span className="bg-gradient-to-r from-indigo-600 to-blue-600 bg-clip-text text-transparent">
</span>
</CardTitle>
<CardDescription className="text-sm text-gray-600"></CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4">
<Button
variant="outline"
className="h-16 sm:h-20 flex flex-col space-y-1 sm:space-y-2 bg-gradient-to-br from-emerald-50 to-green-100 border-emerald-200 hover:from-emerald-100 hover:to-green-200 text-emerald-700 hover:text-emerald-800 text-xs sm:text-sm shadow-md hover:shadow-lg transition-all duration-200"
>
<Target className="h-4 w-4 sm:h-6 sm:w-6" />
<span> KPI</span>
</Button>
<Button
variant="outline"
className="h-16 sm:h-20 flex flex-col space-y-1 sm:space-y-2 bg-gradient-to-br from-blue-50 to-cyan-100 border-blue-200 hover:from-blue-100 hover:to-cyan-200 text-blue-700 hover:text-blue-800 text-xs sm:text-sm shadow-md hover:shadow-lg transition-all duration-200"
>
<Calendar className="h-4 w-4 sm:h-6 sm:w-6" />
<span></span>
</Button>
<Button
variant="outline"
className="h-16 sm:h-20 flex flex-col space-y-1 sm:space-y-2 bg-gradient-to-br from-purple-50 to-violet-100 border-purple-200 hover:from-purple-100 hover:to-violet-200 text-purple-700 hover:text-purple-800 text-xs sm:text-sm shadow-md hover:shadow-lg transition-all duration-200"
>
<TrendingUp className="h-4 w-4 sm:h-6 sm:w-6" />
<span></span>
</Button>
<Button
variant="outline"
className="h-16 sm:h-20 flex flex-col space-y-1 sm:space-y-2 bg-gradient-to-br from-orange-50 to-amber-100 border-orange-200 hover:from-orange-100 hover:to-amber-200 text-orange-700 hover:text-orange-800 text-xs sm:text-sm shadow-md hover:shadow-lg transition-all duration-200"
>
<Users className="h-4 w-4 sm:h-6 sm:w-6" />
<span></span>
</Button>
</div>
</CardContent>
</Card>
</div>
</div>
)
}