import { redirect } from 'next/navigation'; import { getCurrentUser, toPublicUser } from '@/lib/auth/getCurrentUser'; import { createDashboardService } from '@/lib/api/services'; import { Header } from '@/components/layout/Header'; import { ProjectNav } from '@/components/layout/ProjectNav'; import { DashboardWidget } from '@/components/project/DashboardWidget'; import { ForbiddenError } from '@/lib/errors'; export const dynamic = 'force-dynamic'; export default async function ProjectOverviewPage({ params, }: { params: Promise<{ projectId: string }>; }) { const user = await getCurrentUser(); if (!user) redirect('/login'); const { projectId } = await params; const service = createDashboardService(); let dashboard; try { dashboard = service.getProjectDashboard(user.id, Number(projectId)); } catch (error) { if (error instanceof ForbiddenError) { redirect('/dashboard'); } throw error; } const { project } = dashboard; return (

{project.name}

{project.status}
{project.description && (

{project.description}

)}
{dashboard.inProgressTodos.map((t) => (

{t.title} {t.dueDate ? `(期限: ${t.dueDate})` : ''}

))}
{dashboard.nearDueTodos.map((t) => (

{t.title}({t.dueDate})

))}
{dashboard.latestChat.map((m) => (

{m.body}

))}
{dashboard.latestBoard.map((t) => ( {t.isPinned === 1 ? '📌 ' : ''} {t.title} ))} {dashboard.latestNotes.map((n) => ( {n.isPinned === 1 ? '📌 ' : ''} {n.title} ))} {dashboard.recentFiles.map((f) => (

{f.originalName}

))}
{dashboard.nextMeeting && (

{dashboard.nextMeeting.title}({dashboard.nextMeeting.startAt})

)}
{dashboard.milestones.map((m) => (

{m.title} - {m.progress}%

))} {dashboard.recentActivity.map((l) => (

{l.action}({l.targetType})

))}
); }