'use client' import { useRef, useState, useTransition } from 'react' import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { Textarea } from '@/components/ui/textarea' import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog' import { useDirtyCloseGuard, DirtyCloseGuardDialog, } from '@/components/shared/use-dirty-close-guard' import { useDialogSubmitShortcut } from '@/components/shared/use-dialog-submit-shortcut' import { entityDialogContentClasses, entityDialogFooterClasses, entityDialogHeaderClasses, } from '@/components/shared/entity-dialog-layout' import { useUserSettingsStore } from '@/stores/user-settings/store' import { debugProps } from '@/lib/debug' interface NewSprintMetadataDialogProps { open: boolean productId: string onOpenChange: (open: boolean) => void } function todayLocalDate(): string { return new Date().toLocaleDateString('en-CA') } function plusWeeks(weeks: number): string { const d = new Date() d.setDate(d.getDate() + weeks * 7) return d.toLocaleDateString('en-CA') } export function NewSprintMetadataDialog({ open, productId, onOpenChange, }: NewSprintMetadataDialogProps) { const [sprintGoal, setSprintGoal] = useState('') const [startDate, setStartDate] = useState(todayLocalDate()) const [endDate, setEndDate] = useState(plusWeeks(2)) const [error, setError] = useState(null) const [dirty, setDirty] = useState(false) const [isPending, startTransition] = useTransition() const formRef = useRef(null) const setPendingSprintDraft = useUserSettingsStore( (s) => s.setPendingSprintDraft, ) function reset() { setSprintGoal('') setStartDate(todayLocalDate()) setEndDate(plusWeeks(2)) setError(null) setDirty(false) } const closeGuard = useDirtyCloseGuard(dirty, () => { onOpenChange(false) reset() }) function handleSubmit(e: React.FormEvent) { e.preventDefault() const goal = sprintGoal.trim() if (!goal) return setError(null) startTransition(async () => { try { await setPendingSprintDraft(productId, { goal, startAt: startDate || undefined, endAt: endDate || undefined, pbiIntent: {}, storyOverrides: {}, }) reset() onOpenChange(false) } catch (err) { const message = err instanceof Error ? err.message : 'Onbekende fout bij opslaan' setError(message) toast.error(message) } }) } const handleKeyDown = useDialogSubmitShortcut(() => formRef.current?.requestSubmit(), ) return ( <> { if (!o) closeGuard.attemptClose() else onOpenChange(o) }} >
Nieuwe sprint

Geef het sprint-doel en periode op. Je selecteert daarna PBI's en stories via vinkjes in de backlog.

setDirty(true)} className="flex-1 overflow-y-auto px-6 py-6 space-y-6" >