'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { StatusDot } from '@/components/status-badge'; import { ProgressRing } from '@/components/progress-ring'; import { useUser } from '@/components/user-context'; import { calculateProgress, getDaysRemaining, formatDateRange, isKRActive, getTodayInTokyo } from '@/lib/kr-utils'; import { PERIOD_TYPES, REASON_CODES } from '@/lib/constants'; import type { KR, User } from '@/types/database'; import { Target, Clock, AlertTriangle, CheckCircle, History } from 'lucide-react'; import { fetchApi } from '@/lib/api-client'; interface KRWithRelations extends KR { owner: User | null; project: { id: string; name: string; status: string } | null; } export default function MyKRsPage() { const { currentUser, users } = useUser(); const [krs, setKRs] = useState([]); const [isLoading, setIsLoading] = useState(true); // Group KRs by owner for owner view const krsByOwner = users.map(user => ({ user, krs: krs.filter(kr => kr.owner_user_id === user.id && isKRActive(kr)) })).filter(group => group.krs.length > 0 || group.user.role !== 'owner') // Filter out users with no active KRs unless it's a member/pm we want to track .sort((a, b) => { // Sort by KR count descending (users with KRs first) if (a.krs.length > 0 && b.krs.length === 0) return -1; if (a.krs.length === 0 && b.krs.length > 0) return 1; return 0; }); useEffect(() => { async function fetchKRs() { try { const res = await fetchApi('/api/krs'); if (res.ok) { const data = await res.json(); setKRs(data); } } catch (error) { console.error('Failed to fetch KRs:', error); } finally { setIsLoading(false); } } fetchKRs(); }, []); const myKRs = krs.filter(kr => kr.owner_user_id === currentUser?.id); const activeKRs = myKRs.filter(isKRActive); const completedKRs = activeKRs.filter(kr => calculateProgress(kr) >= 1); const pastKRs = myKRs.filter(kr => !isKRActive(kr)); const isOwner = currentUser?.role === 'owner'; if (isLoading) { return (
{[1, 2, 3].map(i => (
))}
); } return (

{isOwner ? '全员 KR 概览' : '我的 KR'}

{isOwner ? '查看所有成员的当前周期目标执行情况' : `${currentUser?.name} 负责的执行目标` }

{isOwner ? (
{krsByOwner.map(({ user, krs }) => (
{user.name[0]}

{user.name}

{krs.length} 个进行中的 KR

{krs.length === 0 ? (

暂无进行中的 KR

) : (
{krs.map(kr => )}
)}
))} {krsByOwner.length === 0 && (

没有任何成员有正在进行的 KR

)}
) : ( <>

{activeKRs.length}

进行中

{completedKRs.length}

已达标

{activeKRs.filter(kr => kr.status === 'red').length}

需关注

进行中 ({activeKRs.length}) 已结束 ({pastKRs.length}) 全部 ({myKRs.length}) {activeKRs.length === 0 ? (

暂无进行中的 KR

) : ( activeKRs.map(kr => ) )}
{pastKRs.length === 0 ? (

暂无已结束的 KR

) : ( pastKRs.map(kr => ) )}
{myKRs.length === 0 ? (

暂无 KR

) : ( myKRs.map(kr => ) )}
)}
); } function KRCard({ kr, showEnded }: { kr: KRWithRelations; showEnded?: boolean }) { const progress = calculateProgress(kr); const daysLeft = getDaysRemaining(kr.period_end); const isActive = isKRActive(kr); return (

{kr.title}

{showEnded && ( 已结束 )}
{kr.project?.name} {PERIOD_TYPES[kr.period_type]} {formatDateRange(kr.period_start, kr.period_end)}
{kr.reason_code && kr.status !== 'green' && (
{REASON_CODES[kr.reason_code]} {kr.note && ` - ${kr.note}`}
)}

{kr.current_value}/{kr.target_value}

{kr.unit}

{isActive && (

剩余 {daysLeft} 天

)}
); }