Spaces:
Running
Running
| "use client"; | |
| import type { WorkPackage, WorkPackagePhase } from "@/lib/work-package-types"; | |
| import { WorkPackageCard } from "@/components/WorkPackageCard"; | |
| import { WorkPackageDetail } from "@/components/WorkPackageDetail"; | |
| import { Badge } from "@/components/ui/badge"; | |
| const PHASES: WorkPackagePhase[] = [ | |
| "Stakeholder Needs", | |
| "Specify Product", | |
| "Design Product", | |
| "Verify and Validate Product", | |
| ]; | |
| export function WorkPackageBoard(props: { | |
| workPackages: WorkPackage[]; | |
| activeWorkPackageId?: string; | |
| selectedWorkPackageId?: string; | |
| onSelect: (id: string) => void; | |
| onPrefill: (text: string) => void; | |
| detailOpen: boolean; | |
| onBackToBoard: () => void; | |
| }) { | |
| const { | |
| workPackages, | |
| activeWorkPackageId, | |
| selectedWorkPackageId, | |
| onSelect, | |
| onPrefill, | |
| detailOpen, | |
| onBackToBoard, | |
| } = props; | |
| const selectedWorkPackage = workPackages.find( | |
| (workPackage) => workPackage.id === selectedWorkPackageId, | |
| ); | |
| const phaseCount = PHASES.filter((phase) => | |
| workPackages.some((workPackage) => workPackage.phase === phase), | |
| ).length; | |
| return ( | |
| <div className="flex h-full min-h-0 flex-col rounded-2xl bg-muted/24"> | |
| <div className="px-3 py-3 md:px-4"> | |
| <div className="flex items-center justify-between gap-2"> | |
| <div> | |
| <div className="text-sm font-semibold">Work Package Zone</div> | |
| <div className="text-xs text-muted-foreground"> | |
| {detailOpen | |
| ? "Selected package detail view" | |
| : "Scrollable board of work package cards"} | |
| </div> | |
| </div> | |
| <div className="flex flex-wrap items-center gap-1"> | |
| <Badge variant="outline" className="text-[11px]"> | |
| {workPackages.length} packages | |
| </Badge> | |
| <Badge variant="outline" className="text-[11px]"> | |
| {phaseCount} phases | |
| </Badge> | |
| <Badge variant="outline" className="text-[11px]"> | |
| {detailOpen ? "detail" : "board"} | |
| </Badge> | |
| </div> | |
| </div> | |
| </div> | |
| {detailOpen ? ( | |
| <WorkPackageDetail | |
| workPackage={selectedWorkPackage} | |
| activeWorkPackageId={activeWorkPackageId} | |
| onPrefill={onPrefill} | |
| onBack={onBackToBoard} | |
| /> | |
| ) : ( | |
| <div className="min-h-0 flex-1 overflow-y-auto overscroll-contain"> | |
| <div className="px-3 pb-10 md:px-4"> | |
| {PHASES.map((phase) => { | |
| const items = workPackages.filter((wp) => wp.phase === phase); | |
| if (!items.length) return null; | |
| return ( | |
| <div key={phase} className="mb-6"> | |
| <div className="mb-2 flex items-center justify-between gap-2"> | |
| <div className="text-xs font-semibold text-muted-foreground"> | |
| {phase} | |
| </div> | |
| </div> | |
| <div className="grid grid-cols-2 gap-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5"> | |
| {items.map((wp) => ( | |
| <WorkPackageCard | |
| key={wp.id} | |
| wp={wp} | |
| activeWorkPackageId={activeWorkPackageId} | |
| selected={wp.id === selectedWorkPackageId} | |
| onSelect={() => onSelect(wp.id)} | |
| onPrefill={onPrefill} | |
| /> | |
| ))} | |
| </div> | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |