refactor(PBI-49): migrate 17 shared/ components to debugProps helper

Replace hardcoded data-debug-id + data-debug-label attribute pairs with
{...debugProps(id, component, file)} spread in all 17 components/shared/
files. Existing debug-ids preserved unchanged.
This commit is contained in:
Scrum4Me Agent 2026-05-09 20:47:51 +02:00
parent a7cc48a230
commit f555cb547b
17 changed files with 40 additions and 28 deletions

View file

@ -5,6 +5,7 @@ import { useTransition } from 'react'
import { toast } from 'sonner'
import { DemoTooltip } from '@/components/shared/demo-tooltip'
import { setActiveProductAction } from '@/actions/active-product'
import { debugProps } from '@/lib/debug'
interface Props {
productId: string
@ -28,7 +29,7 @@ export function ActivateProductButton({ productId, isDemo, redirectTo, label = '
}
return (
<span data-debug-id="activate-product-button" data-debug-label="ActivateProductButton — shared/activate-product-button.tsx">
<span {...debugProps('activate-product-button', 'ActivateProductButton', 'shared/activate-product-button.tsx')}>
<DemoTooltip show={isDemo}>
<button
onClick={() => !isDemo && handleActivate()}

View file

@ -3,6 +3,7 @@
import { useEffect } from 'react'
import { useSearchParams, useRouter, usePathname } from 'next/navigation'
import { toast } from 'sonner'
import { debugProps } from '@/lib/debug'
const ALERT_MESSAGES: Record<string, string> = {
product_unavailable: 'Je actieve product is niet meer beschikbaar',
@ -24,5 +25,5 @@ export function AlertToast() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [alert])
return <span data-debug-id="alert-toast" data-debug-label="AlertToast — shared/alert-toast.tsx" hidden />
return <span {...debugProps('alert-toast', 'AlertToast', 'shared/alert-toast.tsx')} hidden />
}

View file

@ -1,3 +1,5 @@
import { debugProps } from '@/lib/debug'
interface AppIconProps {
size?: number
className?: string
@ -13,8 +15,7 @@ export function AppIcon({ size = 32, className }: AppIconProps) {
xmlns="http://www.w3.org/2000/svg"
className={className}
aria-label="Scrum4Me"
data-debug-id="app-icon"
data-debug-label="AppIcon — shared/app-icon.tsx"
{...debugProps('app-icon', 'AppIcon', 'shared/app-icon.tsx')}
>
<defs>
<linearGradient id="s4m-bg" x1="0" y1="0" x2="512" y2="512" gradientUnits="userSpaceOnUse">

View file

@ -1,4 +1,5 @@
import { cn } from '@/lib/utils'
import { debugProps } from '@/lib/debug'
interface CodeBadgeProps {
code: string | null | undefined
@ -9,8 +10,7 @@ export function CodeBadge({ code, className }: CodeBadgeProps) {
if (!code) return null
return (
<span
data-debug-id="code-badge"
data-debug-label="CodeBadge — shared/code-badge.tsx"
{...debugProps('code-badge', 'CodeBadge', 'shared/code-badge.tsx')}
className={cn(
'inline-flex items-center rounded-md border border-border bg-surface-container px-1.5 py-0.5 font-mono text-[11px] leading-none text-muted-foreground',
className,

View file

@ -1,6 +1,7 @@
'use client'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { debugProps } from '@/lib/debug'
interface DemoTooltipProps {
show: boolean
@ -10,10 +11,10 @@ interface DemoTooltipProps {
// Wraps children with a "Niet beschikbaar in demo-modus" tooltip when show=true.
// Uses a span trigger so tooltip works on disabled elements.
export function DemoTooltip({ show, children }: DemoTooltipProps) {
if (!show) return <span data-debug-id="demo-tooltip" data-debug-label="DemoTooltip — shared/demo-tooltip.tsx">{children}</span>
if (!show) return <span {...debugProps('demo-tooltip', 'DemoTooltip', 'shared/demo-tooltip.tsx')}>{children}</span>
return (
<span data-debug-id="demo-tooltip" data-debug-label="DemoTooltip — shared/demo-tooltip.tsx">
<span {...debugProps('demo-tooltip', 'DemoTooltip', 'shared/demo-tooltip.tsx')}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger render={<span className="inline-flex" />}>

View file

@ -1,11 +1,12 @@
'use client'
import { debugProps } from '@/lib/debug'
// Shows a warning banner on screens narrower than 1024px.
export function MinWidthBanner() {
return (
<div
data-debug-id="min-width-banner"
data-debug-label="MinWidthBanner — shared/min-width-banner.tsx"
{...debugProps('min-width-banner', 'MinWidthBanner', 'shared/min-width-banner.tsx')}
className="lg:hidden bg-warning/10 border-b border-warning/30 px-4 py-2 text-center text-xs text-warning"
>
Scrum4Me is ontworpen voor schermen van minimaal 1024px breed. Sommige functies zijn mogelijk niet goed bruikbaar op dit scherm.

View file

@ -20,6 +20,7 @@ import { NotificationsBell } from '@/components/shared/notifications-bell'
import { SoloNavStatusIndicators } from '@/components/solo/nav-status-indicators'
import { cn } from '@/lib/utils'
import { setActiveProductAction } from '@/actions/active-product'
import { debugProps } from '@/lib/debug'
interface NavBarProps {
isDemo: boolean
@ -112,8 +113,7 @@ export function NavBar({
return (
<header
data-debug-id="nav-bar"
data-debug-label="NavBar — shared/nav-bar.tsx"
{...debugProps('nav-bar', 'NavBar', 'shared/nav-bar.tsx')}
className="bg-surface-container-low border-b border-border h-14 flex items-center px-4 shrink-0"
>
{/* Links: logo + nav */}

View file

@ -11,6 +11,7 @@ import { Bell } from 'lucide-react'
import { useNotificationsStore } from '@/stores/notifications-store'
import { NotificationsSheet } from '@/components/notifications/notifications-sheet'
import { cn } from '@/lib/utils'
import { debugProps } from '@/lib/debug'
interface NotificationsBellProps {
currentUserId: string
@ -27,7 +28,7 @@ export function NotificationsBell({ currentUserId, isDemo }: NotificationsBellPr
)
return (
<span data-debug-id="notifications-bell" data-debug-label="NotificationsBell — shared/notifications-bell.tsx">
<span {...debugProps('notifications-bell', 'NotificationsBell', 'shared/notifications-bell.tsx')}>
<NotificationsSheet
currentUserId={currentUserId}
isDemo={isDemo}

View file

@ -1,4 +1,5 @@
import { cn } from '@/lib/utils'
import { debugProps } from '@/lib/debug'
interface PanelNavBarProps {
title: string
@ -9,8 +10,7 @@ interface PanelNavBarProps {
export function PanelNavBar({ title, actions, className }: PanelNavBarProps) {
return (
<div
data-debug-id="panel-nav-bar"
data-debug-label="PanelNavBar — shared/panel-nav-bar.tsx"
{...debugProps('panel-nav-bar', 'PanelNavBar', 'shared/panel-nav-bar.tsx')}
className={cn('flex items-center justify-between px-4 py-2 border-b border-border bg-surface-container-low shrink-0', className)}
>
<span className="text-sm font-medium text-foreground">{title}</span>

View file

@ -3,6 +3,7 @@
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select'
import { cn } from '@/lib/utils'
import type { PbiStatusApi } from '@/lib/task-status'
import { debugProps } from '@/lib/debug'
export const PBI_STATUS_LABELS: Record<PbiStatusApi, string> = {
ready: 'Klaar voor sprint',
@ -26,7 +27,7 @@ interface PbiStatusSelectProps {
export function PbiStatusSelect({ value, onChange, className }: PbiStatusSelectProps) {
return (
<span data-debug-id="pbi-status-select" data-debug-label="PbiStatusSelect — shared/pbi-status-select.tsx">
<span {...debugProps('pbi-status-select', 'PbiStatusSelect', 'shared/pbi-status-select.tsx')}>
<Select
value={value}
onValueChange={(v) => { if (v) onChange(v as PbiStatusApi) }}

View file

@ -2,6 +2,7 @@
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select'
import { cn } from '@/lib/utils'
import { debugProps } from '@/lib/debug'
export const PRIORITY_LABELS: Record<number, string> = {
1: 'Kritiek',
@ -25,7 +26,7 @@ interface PrioritySelectProps {
export function PrioritySelect({ value, onChange, className }: PrioritySelectProps) {
return (
<span data-debug-id="priority-select" data-debug-label="PrioritySelect — shared/priority-select.tsx">
<span {...debugProps('priority-select', 'PrioritySelect', 'shared/priority-select.tsx')}>
<Select
value={String(value)}
onValueChange={(v) => { if (v) onChange(parseInt(v)) }}

View file

@ -2,6 +2,7 @@
import { useEffect } from 'react'
import { useProductStore } from '@/stores/product-store'
import { debugProps } from '@/lib/debug'
export function SetCurrentProduct({ id, name }: { id: string; name: string }) {
const { setCurrentProduct, clearCurrentProduct } = useProductStore()
@ -11,5 +12,5 @@ export function SetCurrentProduct({ id, name }: { id: string; name: string }) {
return () => clearCurrentProduct()
}, [id, name, setCurrentProduct, clearCurrentProduct])
return <span data-debug-id="set-current-product" data-debug-label="SetCurrentProduct — shared/set-current-product.tsx" hidden />
return <span {...debugProps('set-current-product', 'SetCurrentProduct', 'shared/set-current-product.tsx')} hidden />
}

View file

@ -15,6 +15,7 @@ import {
import { cn } from '@/lib/utils'
import { setActiveSprintAction } from '@/actions/active-sprint'
import type { SprintStatusApi } from '@/lib/task-status'
import { debugProps } from '@/lib/debug'
type SprintItem = { id: string; code: string; sprint_goal: string; status: SprintStatusApi }
@ -68,7 +69,7 @@ export function SprintSwitcher({
if (sprints.length === 0) {
return (
<span data-debug-id="sprint-switcher" data-debug-label="SprintSwitcher — shared/sprint-switcher.tsx">
<span {...debugProps('sprint-switcher', 'SprintSwitcher', 'shared/sprint-switcher.tsx')}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger
@ -85,7 +86,7 @@ export function SprintSwitcher({
}
return (
<span data-debug-id="sprint-switcher" data-debug-label="SprintSwitcher — shared/sprint-switcher.tsx">
<span {...debugProps('sprint-switcher', 'SprintSwitcher', 'shared/sprint-switcher.tsx')}>
<DropdownMenu>
<DropdownMenuTrigger
disabled={isPending}

View file

@ -1,6 +1,7 @@
'use client'
import { DebugToggle } from './status-bar-debug-toggle'
import { debugProps } from '@/lib/debug'
const buildDate = process.env.NEXT_PUBLIC_BUILD_DATE
? new Date(process.env.NEXT_PUBLIC_BUILD_DATE).toLocaleDateString('nl-NL', {
@ -17,8 +18,7 @@ export function StatusBar() {
return (
<footer
className="shrink-0 border-t border-border bg-surface-container-low h-14 px-4 flex items-center justify-between text-sm text-muted-foreground select-none"
data-debug-id="status-bar"
data-debug-label="StatusBar — shared/status-bar.tsx"
{...debugProps('status-bar', 'StatusBar', 'shared/status-bar.tsx')}
>
<span>© {new Date().getFullYear()} Scrum4Me</span>
<span>v{version} · gebouwd op {buildDate}{isDev && <DebugToggle />}</span>

View file

@ -1,3 +1,5 @@
import { debugProps } from '@/lib/debug'
interface StoryLogEntry {
id: string
type: string
@ -35,8 +37,7 @@ export function StoryLog({ logs, repoUrl }: StoryLogProps) {
if (logs.length === 0) {
return (
<p
data-debug-id="story-log"
data-debug-label="StoryLog — shared/story-log.tsx"
{...debugProps('story-log', 'StoryLog', 'shared/story-log.tsx')}
className="text-sm text-muted-foreground text-center py-4"
>
Nog geen activiteit. Gebruik de REST API om logs toe te voegen.
@ -46,8 +47,7 @@ export function StoryLog({ logs, repoUrl }: StoryLogProps) {
return (
<div
data-debug-id="story-log"
data-debug-label="StoryLog — shared/story-log.tsx"
{...debugProps('story-log', 'StoryLog', 'shared/story-log.tsx')}
className="space-y-3"
>
{logs.map(log => {

View file

@ -2,6 +2,7 @@
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { cn } from '@/lib/utils'
import { debugProps } from '@/lib/debug'
type AvatarSize = 'xs' | 'sm' | 'md' | 'lg'
@ -23,7 +24,7 @@ export function UserAvatar({ userId, username, size = 'md', className }: UserAva
const initials = username.slice(0, 2).toUpperCase()
return (
<span data-debug-id="user-avatar" data-debug-label="UserAvatar — shared/user-avatar.tsx">
<span {...debugProps('user-avatar', 'UserAvatar', 'shared/user-avatar.tsx')}>
<Avatar className={cn(SIZE_CLASSES[size], className)}>
<AvatarImage src={`/api/users/${userId}/avatar`} alt={username} />
<AvatarFallback className="bg-primary-container text-primary-container-foreground font-medium">

View file

@ -15,6 +15,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { debugProps } from '@/lib/debug'
const ROLE_LABELS: Record<string, string> = {
PRODUCT_OWNER: 'Product Owner',
@ -46,7 +47,7 @@ export function UserMenu({ userId, username, email, roles }: UserMenuProps) {
}
return (
<span data-debug-id="user-menu" data-debug-label="UserMenu — shared/user-menu.tsx">
<span {...debugProps('user-menu', 'UserMenu', 'shared/user-menu.tsx')}>
<DropdownMenu>
<DropdownMenuTrigger
className="rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background"