Scrum4Me/components/sprint/sprint-switcher.tsx
Madhura68 125855c603 fix(PBI-63): sprint-switcher naar productpagina-header in productstijl
- Verwijdert setActiveSprintCookie uit sprint board page (kon geen cookie
  schrijven vanuit een Server Component — alleen Server Action / Route Handler)
- Verplaatst sprint-pulldown uit NavBar naar de productpagina action-row
  (dezelfde rij als 'Sprint starten' / 'Instellingen')
- Nieuwe SprintSwitcher-component in zelfde stijl als product-dropdown:
  truncated tekst + ChevronDown, geen status-badges
- NavBar krijgt activeSprintId voor sprint-link href; layout fetcht alleen
  nog activeSprint-id (geen volledige sprints[] meer)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:24:40 +02:00

84 lines
2.5 KiB
TypeScript

'use client'
import { useTransition } from 'react'
import { usePathname, useRouter } from 'next/navigation'
import { ChevronDown } from 'lucide-react'
import { toast } from 'sonner'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { cn } from '@/lib/utils'
import { setActiveSprintAction } from '@/actions/active-sprint'
type SprintItem = { id: string; code: string }
interface SprintSwitcherProps {
productId: string
sprints: SprintItem[]
activeSprintId: string | null
className?: string
}
export function SprintSwitcher({
productId,
sprints,
activeSprintId,
className,
}: SprintSwitcherProps) {
const router = useRouter()
const pathname = usePathname()
const [isPending, startTransition] = useTransition()
if (sprints.length === 0) return null
const active = sprints.find(s => s.id === activeSprintId) ?? sprints[0]
function handleSwitch(sprintId: string) {
if (sprintId === active.id) return
startTransition(async () => {
const result = await setActiveSprintAction(productId, sprintId)
if (result?.error) {
toast.error(typeof result.error === 'string' ? result.error : 'Wisselen mislukt')
return
}
if (pathname.includes('/sprint')) {
router.push(`/products/${productId}/sprint/${sprintId}`)
} else {
router.refresh()
}
})
}
return (
<DropdownMenu>
<DropdownMenuTrigger
disabled={isPending}
className={cn(
'flex items-center gap-1 text-sm font-medium text-foreground hover:text-primary transition-colors px-2 rounded-md hover:bg-surface-container focus:outline-none',
className,
)}
>
<span className="truncate max-w-[180px]">
{active.code.length > 22 ? active.code.slice(0, 22) + '…' : active.code}
</span>
<ChevronDown className="w-3.5 h-3.5 shrink-0 text-muted-foreground" />
</DropdownMenuTrigger>
<DropdownMenuContent align="center" className="w-56">
{sprints.map(s => (
<DropdownMenuItem
key={s.id}
onClick={() => handleSwitch(s.id)}
className={cn(
s.id === active.id && 'bg-primary-container text-primary-container-foreground font-medium',
)}
>
<span className="truncate">{s.code}</span>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
)
}