feat: plan_snapshot field on ClaudeJob + architecture doc (#23)
* feat: add plan_snapshot field to ClaudeJob schema Nullable String? column on claude_jobs captures the task's implementation_plan at claim time — immutable baseline for drift detection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: update ClaudeJob lifecycle with plan_snapshot Document state machine snapshot capture/reset, plan_snapshot field rationale, and drift-detection baseline semantics. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: remove duplicate header labels on backlog page Both the product H1 + description in the page header and the "Product Backlog" panel-title in the PBI panel duplicated info already visible in the NavBar. Removed both, keeping the right-aligned action bars (activate/sprint/settings, plus filters/+PBI) intact. PanelNavBar component is unchanged — Stories and Taken panels keep their titles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8877ea469d
commit
794f7afd2e
6 changed files with 89 additions and 94 deletions
|
|
@ -24,7 +24,6 @@ import { toast } from 'sonner'
|
|||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||
import { PanelNavBar } from '@/components/shared/panel-nav-bar'
|
||||
import { useSelectionStore } from '@/stores/selection-store'
|
||||
import { usePlannerStore } from '@/stores/planner-store'
|
||||
import { useBacklogStore } from '@/stores/backlog-store'
|
||||
|
|
@ -330,92 +329,87 @@ export function PbiList({ productId, isDemo }: PbiListProps) {
|
|||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<PanelNavBar
|
||||
title="Product Backlog"
|
||||
actions={
|
||||
<>
|
||||
{filterPriority !== 'all' && (
|
||||
<button
|
||||
onClick={() => setFilterPriority('all')}
|
||||
className="flex items-center gap-1 text-xs text-primary hover:underline"
|
||||
aria-label="Wis prioriteitsfilter"
|
||||
>
|
||||
<Badge className={cn('text-xs', PRIORITY_COLORS[filterPriority])}>
|
||||
{PRIORITY_LABELS[filterPriority]}
|
||||
</Badge>
|
||||
<span>×</span>
|
||||
</button>
|
||||
)}
|
||||
{filterStatus !== 'all' && (
|
||||
<button
|
||||
onClick={() => setFilterStatus('all')}
|
||||
className="flex items-center gap-1 text-xs text-primary hover:underline"
|
||||
aria-label="Wis statusfilter"
|
||||
>
|
||||
<Badge className={cn('text-xs', PBI_STATUS_COLORS[filterStatus])}>
|
||||
{PBI_STATUS_LABELS[filterStatus]}
|
||||
</Badge>
|
||||
<span>×</span>
|
||||
</button>
|
||||
)}
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
render={
|
||||
<Button variant="outline" size="sm" className="h-7 text-xs">
|
||||
{`Filters${activeFilterCount > 0 ? ` (${activeFilterCount})` : ''}`}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<PopoverContent align="end" className="w-72 space-y-4">
|
||||
<FilterPills
|
||||
label="Sorteren op"
|
||||
options={SORT_OPTIONS}
|
||||
value={sortMode}
|
||||
onChange={setSortMode}
|
||||
/>
|
||||
<FilterPills
|
||||
label="Prioriteit"
|
||||
options={PRIORITY_OPTIONS}
|
||||
value={filterPriority}
|
||||
onChange={setFilterPriority}
|
||||
/>
|
||||
<FilterPills
|
||||
label="Status"
|
||||
options={STATUS_OPTIONS}
|
||||
value={filterStatus}
|
||||
onChange={setFilterStatus}
|
||||
/>
|
||||
<div className="flex justify-end pt-1 border-t border-border">
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-7 text-xs"
|
||||
disabled={activeFilterCount === 0}
|
||||
onClick={() => {
|
||||
setFilterPriority('all')
|
||||
setFilterStatus('all')
|
||||
setSortMode('priority')
|
||||
}}
|
||||
>
|
||||
Wis filters
|
||||
</Button>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<DemoTooltip show={isDemo}>
|
||||
<div className="flex items-center justify-end gap-2 px-4 py-2 border-b border-border bg-surface-container-low shrink-0">
|
||||
{filterPriority !== 'all' && (
|
||||
<button
|
||||
onClick={() => setFilterPriority('all')}
|
||||
className="flex items-center gap-1 text-xs text-primary hover:underline"
|
||||
aria-label="Wis prioriteitsfilter"
|
||||
>
|
||||
<Badge className={cn('text-xs', PRIORITY_COLORS[filterPriority])}>
|
||||
{PRIORITY_LABELS[filterPriority]}
|
||||
</Badge>
|
||||
<span>×</span>
|
||||
</button>
|
||||
)}
|
||||
{filterStatus !== 'all' && (
|
||||
<button
|
||||
onClick={() => setFilterStatus('all')}
|
||||
className="flex items-center gap-1 text-xs text-primary hover:underline"
|
||||
aria-label="Wis statusfilter"
|
||||
>
|
||||
<Badge className={cn('text-xs', PBI_STATUS_COLORS[filterStatus])}>
|
||||
{PBI_STATUS_LABELS[filterStatus]}
|
||||
</Badge>
|
||||
<span>×</span>
|
||||
</button>
|
||||
)}
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
render={
|
||||
<Button variant="outline" size="sm" className="h-7 text-xs">
|
||||
{`Filters${activeFilterCount > 0 ? ` (${activeFilterCount})` : ''}`}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<PopoverContent align="end" className="w-72 space-y-4">
|
||||
<FilterPills
|
||||
label="Sorteren op"
|
||||
options={SORT_OPTIONS}
|
||||
value={sortMode}
|
||||
onChange={setSortMode}
|
||||
/>
|
||||
<FilterPills
|
||||
label="Prioriteit"
|
||||
options={PRIORITY_OPTIONS}
|
||||
value={filterPriority}
|
||||
onChange={setFilterPriority}
|
||||
/>
|
||||
<FilterPills
|
||||
label="Status"
|
||||
options={STATUS_OPTIONS}
|
||||
value={filterStatus}
|
||||
onChange={setFilterStatus}
|
||||
/>
|
||||
<div className="flex justify-end pt-1 border-t border-border">
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-7 text-xs"
|
||||
disabled={isDemo}
|
||||
onClick={() => !isDemo && setDialogState({ mode: 'create', productId, defaultPriority: 2 })}
|
||||
disabled={activeFilterCount === 0}
|
||||
onClick={() => {
|
||||
setFilterPriority('all')
|
||||
setFilterStatus('all')
|
||||
setSortMode('priority')
|
||||
}}
|
||||
>
|
||||
+ PBI
|
||||
Wis filters
|
||||
</Button>
|
||||
</DemoTooltip>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<DemoTooltip show={isDemo}>
|
||||
<Button
|
||||
size="sm"
|
||||
className="h-7 text-xs"
|
||||
disabled={isDemo}
|
||||
onClick={() => !isDemo && setDialogState({ mode: 'create', productId, defaultPriority: 2 })}
|
||||
>
|
||||
+ PBI
|
||||
</Button>
|
||||
</DemoTooltip>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
{pbis.length === 0 ? (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue