Scrum4Me/stores/jobs-store.ts
Janpeter Visser f166186374
feat(PBI-59): Jobs-pagina UI (vervolg na #149) (#150)
* feat(PBI-58): Vitest-tests voor SoloTaskCard veldmapping en 4-regels layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): server action fetchJobsPageData voor jobs-pagina

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): SSE-route /api/realtime/jobs voor user-scoped job-events

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): JobCard component voor jobs-pagina

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): JobDetailPane component voor jobs-pagina

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): API route GET /api/jobs/[id]/sub-tasks voor sprint task executions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): SprintSubTasksPane component voor jobs-pagina

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): Zustand store useJobsStore voor jobs-pagina

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): useJobsRealtime hook met SSE-verbinding en store-updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): /jobs server page met JobsBoard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(PBI-59): Jobs nav-link toevoegen aan NavBar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 19:16:20 +02:00

59 lines
1.6 KiB
TypeScript

import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
import type { JobWithRelations } from '@/actions/jobs-page'
type JobsState = {
activeJobs: JobWithRelations[]
doneJobs: JobWithRelations[]
selectedJobId: string | null
}
type JobsActions = {
initJobs(active: JobWithRelations[], done: JobWithRelations[]): void
setSelectedJobId(id: string | null): void
upsertJob(job: Partial<JobWithRelations> & { id: string; status: string }): void
}
export const useJobsStore = create<JobsState & JobsActions>()(
immer((set) => ({
activeJobs: [],
doneJobs: [],
selectedJobId: null,
initJobs(active, done) {
set((state) => {
state.activeJobs = active
state.doneJobs = done
})
},
setSelectedJobId(id) {
set((state) => {
state.selectedJobId = id
})
},
upsertJob(job) {
set((state) => {
const isDone = job.status.toUpperCase() === 'DONE'
if (isDone) {
state.activeJobs = state.activeJobs.filter(j => j.id !== job.id)
if (!state.doneJobs.find(j => j.id === job.id)) {
state.doneJobs.unshift(job as JobWithRelations)
if (state.doneJobs.length > 100) {
state.doneJobs = state.doneJobs.slice(0, 100)
}
}
} else {
const idx = state.activeJobs.findIndex(j => j.id === job.id)
if (idx !== -1) {
Object.assign(state.activeJobs[idx], job)
} else {
state.activeJobs.push(job as JobWithRelations)
}
}
})
},
}))
)