feat(ST-1112): wire TaskDialog into sprint page via searchParams

Sprint page now reads ?newTask, ?storyId, and ?editTask query params.
For edit mode: fetches the task server-side with productAccessFilter
scope (invalid/foreign IDs redirect to closePath). Renders TaskDialog
when either param is present. closePath is the sprint route without
query params.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-29 23:46:56 +02:00
parent 45adaa2f76
commit e27d25a662

View file

@ -1,19 +1,29 @@
import { notFound, redirect } from 'next/navigation'
import { getSession } from '@/lib/auth'
import { getAccessibleProduct } from '@/lib/product-access'
import { productAccessFilter } from '@/lib/product-access'
import { prisma } from '@/lib/prisma'
import { SprintBoardClient } from '@/components/sprint/sprint-board-client'
import { SprintHeader } from '@/components/sprint/sprint-header'
import type { SprintStory, PbiWithStories, ProductMember } from '@/components/sprint/sprint-backlog'
import type { Task } from '@/components/sprint/task-list'
import { TaskDialog } from '@/app/_components/tasks/task-dialog'
import type { TaskDialogTask } from '@/app/_components/tasks/task-dialog'
import Link from 'next/link'
interface Props {
params: Promise<{ id: string }>
searchParams: Promise<{
newTask?: string
storyId?: string
editTask?: string
}>
}
export default async function SprintBoardPage({ params }: Props) {
export default async function SprintBoardPage({ params, searchParams }: Props) {
const { id } = await params
const { newTask, storyId: storyIdParam, editTask } = await searchParams
const session = await getSession()
if (!session.userId) redirect('/login')
@ -104,6 +114,31 @@ export default async function SprintBoardPage({ params }: Props) {
const sprintStoryIdList = sprintStories.map(s => s.id)
const isDemo = session.isDemo ?? false
const closePath = `/products/${id}/sprint`
// Fetch task for edit mode (auth-scoped)
let editTaskData: TaskDialogTask | null = null
if (editTask) {
const t = await prisma.task.findFirst({
where: {
id: editTask,
story: { product: productAccessFilter(session.userId) },
},
select: {
id: true,
title: true,
description: true,
implementation_plan: true,
priority: true,
status: true,
created_at: true,
},
})
if (!t) redirect(closePath)
editTaskData = t
}
const showDialog = !!newTask || !!editTaskData
return (
<div className="flex flex-col h-full">
@ -134,6 +169,16 @@ export default async function SprintBoardPage({ params }: Props) {
Product Backlog
</Link>
</div>
{showDialog && (
<TaskDialog
task={editTaskData ?? undefined}
storyId={storyIdParam}
productId={id}
closePath={closePath}
isDemo={isDemo}
/>
)}
</div>
)
}