feat(backlog): add EmptyPanel shared component, replace inline empty states
EmptyPanel takes title?, message, and optional action with DemoTooltip. Replaces duplicate inline empty-state markup in pbi-list and story-panel. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
75bbb1ad73
commit
57e2d49949
3 changed files with 46 additions and 21 deletions
35
components/backlog/empty-panel.tsx
Normal file
35
components/backlog/empty-panel.tsx
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
'use client'
|
||||
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
||||
|
||||
interface EmptyPanelProps {
|
||||
title?: string
|
||||
message: string
|
||||
action?: {
|
||||
label: string
|
||||
onClick: () => void
|
||||
disabled?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export function EmptyPanel({ title, message, action }: EmptyPanelProps) {
|
||||
return (
|
||||
<div className="p-8 text-center text-muted-foreground space-y-3">
|
||||
{title && <p className="text-sm font-medium text-foreground">{title}</p>}
|
||||
<p className="text-sm">{message}</p>
|
||||
{action && (
|
||||
<DemoTooltip show={action.disabled ?? false}>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={action.disabled}
|
||||
onClick={action.disabled ? undefined : action.onClick}
|
||||
>
|
||||
{action.label}
|
||||
</Button>
|
||||
</DemoTooltip>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import { reorderPbisAction, updatePbiPriorityAction } from '@/actions/stories'
|
|||
import { cn } from '@/lib/utils'
|
||||
import { PbiDialog, type PbiDialogState } from './pbi-dialog'
|
||||
import { BacklogCard } from './backlog-card'
|
||||
import { EmptyPanel } from './empty-panel'
|
||||
import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
||||
import { PRIORITY_COLORS } from '@/components/shared/priority-select'
|
||||
import { PBI_STATUS_LABELS, PBI_STATUS_COLORS } from '@/components/shared/pbi-status-select'
|
||||
|
|
@ -417,14 +418,10 @@ export function PbiList({ productId, pbis, isDemo }: PbiListProps) {
|
|||
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
{pbis.length === 0 ? (
|
||||
<div className="p-8 text-center text-muted-foreground text-sm space-y-3">
|
||||
<p>Nog geen PBI's aangemaakt.</p>
|
||||
<DemoTooltip show={isDemo}>
|
||||
<Button size="sm" variant="outline" disabled={isDemo} onClick={() => !isDemo && setDialogState({ mode: 'create', productId, defaultPriority: 2 })}>
|
||||
Maak je eerste PBI aan
|
||||
</Button>
|
||||
</DemoTooltip>
|
||||
</div>
|
||||
<EmptyPanel
|
||||
message="Nog geen PBI's aangemaakt."
|
||||
action={{ label: 'Maak je eerste PBI aan', onClick: () => setDialogState({ mode: 'create', productId, defaultPriority: 2 }), disabled: isDemo }}
|
||||
/>
|
||||
) : (
|
||||
<DndContext
|
||||
id="pbi-list"
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { usePlannerStore } from '@/stores/planner-store'
|
|||
import { reorderStoriesAction } from '@/actions/stories'
|
||||
import { StoryDialog, type StoryDialogState } from './story-dialog'
|
||||
import { BacklogCard } from './backlog-card'
|
||||
import { EmptyPanel } from './empty-panel'
|
||||
import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
|
|
@ -242,20 +243,12 @@ export function StoryPanel({ productId, storiesByPbi, isDemo }: StoryPanelProps)
|
|||
|
||||
<div className="flex-1 overflow-y-auto p-4">
|
||||
{selectedPbiId === null ? (
|
||||
<p className="text-sm text-muted-foreground text-center mt-8">
|
||||
Selecteer een PBI om de stories te bekijken.
|
||||
</p>
|
||||
<EmptyPanel message="Selecteer een PBI om de stories te bekijken." />
|
||||
) : rawStories.length === 0 ? (
|
||||
<div className="text-center mt-8 space-y-3">
|
||||
<p className="text-sm text-muted-foreground">Nog geen stories voor dit PBI.</p>
|
||||
{selectedPbiId && (
|
||||
<DemoTooltip show={isDemo}>
|
||||
<Button size="sm" variant="outline" disabled={isDemo} onClick={() => !isDemo && setStoryDialogState({ mode: 'create', pbiId: selectedPbiId, productId, defaultPriority: 2 })}>
|
||||
Maak je eerste story aan
|
||||
</Button>
|
||||
</DemoTooltip>
|
||||
)}
|
||||
</div>
|
||||
<EmptyPanel
|
||||
message="Nog geen stories voor dit PBI."
|
||||
action={{ label: 'Maak je eerste story aan', onClick: () => setStoryDialogState({ mode: 'create', pbiId: selectedPbiId, productId, defaultPriority: 2 }), disabled: isDemo }}
|
||||
/>
|
||||
) : (
|
||||
<DndContext
|
||||
id="story-panel"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue