feat(granskning): concept review queue (UI migration PR 6) (#1126)

* feat(granskning): concept scene 11 for the review queue

Reskins /pending to the concept: serif header with a Godkann alla primary,
Vantar/Godkanda/Avvisade seg with a count chip on the queue, source filter
as the far-right context picker, and op rows in the concept's row language
(source line, title, risk chip, inline Godkann pill + quiet Avvisa, hover
checkbox). Row click opens the detail as a right slide-over (convention 13)
with the operation preview, period-lock banner, and approve/reject in the
footer. The select-all header becomes the standard bulkbar that pops in on
first selection, carrying the type quick-picks as quiet links. All existing
functionality is preserved: bulk approve/reject with confirm dialogs,
rejection category + feedback, high-risk warnings, period-lock gating,
conversation deep-link filter, realtime refetch, auto-expired markers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(bookkeeping): concept seg styling for the Verifikat/Utkast toggle

The toggle used the old bordered container with a beige active tab: the
inverse of the concept seg used on every other page (muted container,
card-white active with hairline border). Founder feedback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(granskning): match concept scene 11 row language

Founder feedback against the rendered concept: the seg becomes
Vantar/Historik (Historik merges committed + rejected via two parallel
fetches, newest resolution first, distinguished by Godkand/Avvisad chips
with the rejection reason in the sub line); op rows get the concept's
actor circle with a thread line, uppercase source line, and the three
tinted action pills under the text (Godkann sage, Avvisa terracotta,
Visa detaljer neutral) instead of right-aligned hover actions. Risk chip
stays on the right edge; hover checkboxes and the bulkbar are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(granskning): curved actor thread + boxed, legible detail panel

Founder feedback vs the rendered concept: the thread under the actor icon
now elbows toward the action row (rounded border corner) instead of a
straight line, and the slide-over frames the operation in its own bordered
box with the warning/rejection notes as separate boxed lines. preview_data
arrays shaped like a kontering (account/debit/credit rows, e.g.
preview_lines) now render as a proper Konto/Beskrivning/Debet/Kredit table
instead of the generic '3 rader' dump, so the panel actually says what the
agent is about to post.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(granskning): carry #842 failed_partial rendering through the rework

The failed_partial status (irreversible posting followed by a failed
step) landed on main while the review-queue rework was in flight; the
Historik rows and the detail slide-over now render its warning chip,
explanation, and posted_ids like main did.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-07-23 21:51:41 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 7a6f9dd167
commit 008b4710d3
4 changed files with 597 additions and 325 deletions
+19 -5
View File
@@ -693,24 +693,38 @@ export default function JournalEntryList() {
<div className="flex flex-wrap items-center gap-2">
{/* Verifikat vs Utkast. Drafts live in their own view with a count badge so
they don't sink to the last page of the committed list. */}
<div className="inline-flex shrink-0 rounded-md border border-border p-0.5">
<div className="inline-flex shrink-0 gap-0.5 rounded-lg bg-muted/70 p-[3px]" role="tablist">
<button
type="button"
role="tab"
aria-selected={listMode === 'committed'}
onClick={() => switchMode('committed')}
className={`h-7 rounded px-3 text-xs font-medium transition-colors ${listMode === 'committed' ? 'bg-secondary text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
className={cn(
'rounded-md px-3.5 py-[5px] text-[12.5px] transition-colors duration-150',
listMode === 'committed'
? 'border border-border bg-card font-medium text-foreground'
: 'text-muted-foreground hover:text-foreground',
)}
>
{t('mode_vouchers')}
</button>
<button
type="button"
role="tab"
aria-selected={listMode === 'drafts'}
onClick={() => switchMode('drafts')}
className={`inline-flex h-7 items-center gap-1.5 rounded px-3 text-xs font-medium transition-colors ${listMode === 'drafts' ? 'bg-secondary text-foreground' : 'text-muted-foreground hover:text-foreground'}`}
className={cn(
'inline-flex items-center gap-1.5 rounded-md px-3.5 py-[5px] text-[12.5px] transition-colors duration-150',
listMode === 'drafts'
? 'border border-border bg-card font-medium text-foreground'
: 'text-muted-foreground hover:text-foreground',
)}
>
{t('mode_drafts')}
{draftCount > 0 && (
<Badge variant="secondary" className="h-4 min-w-4 justify-center px-1 text-[10px] tabular-nums">
<span className="rounded-full bg-secondary px-1.5 text-[10px] font-medium tabular-nums">
{draftCount}
</Badge>
</span>
)}
</button>
</div>