feat: shared backlog filter popover + sprint header polish (v1.3.3) (#184)
- Move sprint switcher into sprint header, centered between title and actions - Extract BacklogFilterPopover as shared component used by sprint and product backlog - Add sort options (code/priority/status) with single-pill asc/desc toggle - Default sprint backlog status filter to OPEN, remove "alleen niet klaar" button - Persist collapsed state and filter popover open in localStorage - Fix hydration flicker: defer localStorage read to useEffect with prefsLoaded gate for writes - Increase sprint switcher text size for readability Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a9b53dedf0
commit
1f8cbacb0a
9 changed files with 424 additions and 330 deletions
|
|
@ -33,6 +33,8 @@ import {
|
|||
import { updateSprintGoalAction, updateSprintDatesAction, completeSprintAction, setAllSprintTasksDoneAction } from '@/actions/sprints'
|
||||
import type { SprintStory } from './sprint-backlog'
|
||||
import { debugProps } from '@/lib/debug'
|
||||
import { SprintSwitcher } from '@/components/shared/sprint-switcher'
|
||||
import type { SprintSwitcherItem } from '@/lib/sprint-switcher-data'
|
||||
|
||||
interface Sprint {
|
||||
id: string
|
||||
|
|
@ -49,6 +51,9 @@ interface SprintHeaderProps {
|
|||
sprint: Sprint
|
||||
isDemo: boolean
|
||||
sprintStories: SprintStory[]
|
||||
switcherSprints: SprintSwitcherItem[]
|
||||
switcherActiveSprint: SprintSwitcherItem | null
|
||||
switcherBuildingSprintIds: string[]
|
||||
}
|
||||
|
||||
interface ActionResult {
|
||||
|
|
@ -63,7 +68,7 @@ function toDateInputValue(d: Date | null) {
|
|||
return d.toISOString().slice(0, 10)
|
||||
}
|
||||
|
||||
export function SprintHeader({ productId: _productId, productName, sprint, isDemo, sprintStories }: SprintHeaderProps) {
|
||||
export function SprintHeader({ productId, productName, sprint, isDemo, sprintStories, switcherSprints, switcherActiveSprint, switcherBuildingSprintIds }: SprintHeaderProps) {
|
||||
const [editingGoal, setEditingGoal] = useState(false)
|
||||
const [editingDates, setEditingDates] = useState(false)
|
||||
const [completeOpen, setCompleteOpen] = useState(false)
|
||||
|
|
@ -132,7 +137,7 @@ export function SprintHeader({ productId: _productId, productName, sprint, isDem
|
|||
|
||||
return (
|
||||
<div className="px-4 py-3 border-b border-border bg-surface-container-low shrink-0" {...debugProps('sprint-header', 'SprintHeader', 'components/sprint/sprint-header.tsx')}>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs text-muted-foreground">{productName}</span>
|
||||
|
|
@ -162,7 +167,16 @@ export function SprintHeader({ productId: _productId, productName, sprint, isDem
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 shrink-0" data-debug-id="sprint-header__actions">
|
||||
<div className="shrink-0">
|
||||
<SprintSwitcher
|
||||
productId={productId}
|
||||
sprints={switcherSprints}
|
||||
activeSprint={switcherActiveSprint}
|
||||
buildingSprintIds={switcherBuildingSprintIds}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end gap-2 flex-1 shrink-0" data-debug-id="sprint-header__actions">
|
||||
<DemoTooltip show={isDemo}>
|
||||
<Button size="sm" variant="ghost" disabled={isDemo} className="text-muted-foreground" data-debug-id="sprint-header__dates" onClick={() => !isDemo && setEditingDates(true)}>
|
||||
{sprint.start_date && sprint.end_date
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue