From d03df529d35002828f069fb2e0633008165646ac Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Sat, 25 Apr 2026 19:17:00 +0200 Subject: [PATCH] feat(todos): make product optional in createTodoAction; fix promote scopes - createTodoAction: productId is now optional; validates with productAccessFilter when provided so team members can link todos - promoteTodoToPbiAction: use productAccessFilter for product lookup; remove product_id from todo WHERE (was breaking unlinked todos) - promoteTodoToStoryAction: only enforce product match when todo has a product_id (null means unlinked, any product is acceptable) Co-Authored-By: Claude Sonnet 4.6 --- actions/todos.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/actions/todos.ts b/actions/todos.ts index ab9ea7e..86c8ad6 100644 --- a/actions/todos.ts +++ b/actions/todos.ts @@ -18,15 +18,16 @@ export async function createTodoAction(_prevState: unknown, formData: FormData) if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const title = (formData.get('title') as string)?.trim() - const productId = (formData.get('productId') as string)?.trim() + const productId = (formData.get('productId') as string)?.trim() || null if (!title) return { error: 'Titel is verplicht' } - if (!productId) return { error: 'Product is verplicht' } - const product = await prisma.product.findFirst({ - where: { id: productId, user_id: session.userId, archived: false }, - }) - if (!product) return { error: 'Product niet gevonden' } + if (productId) { + const product = await prisma.product.findFirst({ + where: { id: productId, ...productAccessFilter(session.userId), archived: false }, + }) + if (!product) return { error: 'Product niet gevonden' } + } await prisma.todo.create({ data: { user_id: session.userId, product_id: productId, title } }) revalidatePath('/todos') @@ -78,12 +79,12 @@ export async function promoteTodoToPbiAction(_prevState: unknown, formData: Form if (!parsed.success) return { error: parsed.error.flatten().fieldErrors } const product = await prisma.product.findFirst({ - where: { id: parsed.data.productId, user_id: session.userId }, + where: { id: parsed.data.productId, ...productAccessFilter(session.userId) }, }) if (!product) return { error: 'Product niet gevonden' } const todo = await prisma.todo.findFirst({ - where: { id: parsed.data.todoId, user_id: session.userId, product_id: parsed.data.productId }, + where: { id: parsed.data.todoId, user_id: session.userId }, }) if (!todo) return { error: 'Todo niet gevonden' } @@ -140,7 +141,7 @@ export async function promoteTodoToStoryAction(_prevState: unknown, formData: Fo where: { id: parsed.data.pbiId, product: productAccessFilter(session.userId) }, }) if (!pbi) return { error: 'PBI niet gevonden' } - if (todo.product_id !== pbi.product_id) return { error: 'Todo hoort niet bij dit product' } + if (todo.product_id !== null && todo.product_id !== pbi.product_id) return { error: 'Todo hoort niet bij dit product' } const last = await prisma.story.findFirst({ where: { pbi_id: parsed.data.pbiId, priority: parsed.data.priority },