feat(PBI-59): JobsBoard 3-kolom SplitPane client component

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scrum4Me Agent 2026-05-07 18:48:17 +02:00
parent e276cac922
commit cd4ca4279f

View file

@ -0,0 +1,96 @@
'use client'
import { useEffect } from 'react'
import { SplitPane } from '@/components/split-pane/split-pane'
import JobCard from './job-card'
import JobDetailPane from './job-detail-pane'
import SprintSubTasksPane from './sprint-sub-tasks-pane'
import { useJobsStore } from '@/stores/jobs-store'
import useJobsRealtime from '@/hooks/use-jobs-realtime'
import type { JobWithRelations } from '@/actions/jobs-page'
interface JobsBoardProps {
initialActiveJobs: JobWithRelations[]
initialDoneJobs: JobWithRelations[]
}
function jobToCardProps(j: JobWithRelations) {
return {
id: j.id,
kind: j.kind,
status: j.status,
taskCode: j.taskCode,
taskTitle: j.taskTitle,
ideaCode: j.ideaCode,
ideaTitle: j.ideaTitle,
sprintGoal: j.sprintGoal,
sprintCode: j.sprintCode,
productName: j.productName,
branch: j.branch,
error: j.error,
summary: j.summary,
}
}
export default function JobsBoard({ initialActiveJobs, initialDoneJobs }: JobsBoardProps) {
const { activeJobs, doneJobs, selectedJobId, initJobs, setSelectedJobId } = useJobsStore()
useJobsRealtime()
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => { initJobs(initialActiveJobs, initialDoneJobs) }, [])
const selectedJob = [...activeJobs, ...doneJobs].find(j => j.id === selectedJobId) ?? null
const leftPane = (
<div className="overflow-y-auto h-full p-2 space-y-2">
{activeJobs.map(j => (
<JobCard
key={j.id}
{...jobToCardProps(j)}
isSelected={j.id === selectedJobId}
onClick={() => setSelectedJobId(j.id)}
/>
))}
{activeJobs.length === 0 && (
<p className="text-sm text-muted-foreground text-center py-8">Geen actieve jobs</p>
)}
</div>
)
const middlePane = (
<div className="flex flex-col h-full overflow-hidden">
<SprintSubTasksPane
jobId={selectedJobId}
isSprintJob={selectedJob?.kind === 'SPRINT_IMPLEMENTATION'}
/>
<div className="flex-1 overflow-y-auto">
<JobDetailPane job={selectedJob} />
</div>
</div>
)
const rightPane = (
<div className="overflow-y-auto h-full p-2 space-y-2">
{doneJobs.map(j => (
<JobCard
key={j.id}
{...jobToCardProps(j)}
isSelected={j.id === selectedJobId}
onClick={() => setSelectedJobId(j.id)}
/>
))}
{doneJobs.length === 0 && (
<p className="text-sm text-muted-foreground text-center py-8">Nog geen afgeronde jobs</p>
)}
</div>
)
return (
<SplitPane
panes={[leftPane, middlePane, rightPane]}
defaultSplit={[25, 50, 25]}
cookieKey="jobs"
tabLabels={['Actief', 'Details', 'Klaar']}
/>
)
}