Files
Jakob Wennberg 02a5d10538 refactor(ui): migrate remaining inline pages to the concept design language (#1470)
* refactor(ui): migrate remaining inline pages to the concept design language

Catch-up pass for surfaces the 2026-07 UI migration missed:

- Bankavstämning: de-boxed toolbar, dry-table sections (preview, omatchade
  verifikationer, ignorerade, matchade), instructional copy moved behind the
  page "?" (HelpPopover via FocusedReport, sv+en), AttnLine for the dirty-
  dates hint, EmptyState for the blank page, space-y-8 rhythm.
- Report detail views (trial balance, income statement, balance sheet,
  resultat-/balansrapport, reskontror, huvudbok, grundbok, dimension-P&L):
  shared Skeleton/Error/EmptyState shells, border-2 totals bands flattened
  to hairline cards with font-display tabular-nums headline numbers,
  ReportSectionTable rebuilt on the group-band idiom, font-mono money ->
  tabular-nums, house tablist for Förenklad/Detaljerad, GL filter de-boxed
  onto Input primitives, verdicts follow chips-mark-exceptions.
- Extensions browse: PageHeader, locked section headers, rounded-lg
  secondary icon tiles, flat hover shift on cards, p-6 content.
- Återkommande fakturor: page-level list moved off ui/table onto dry-table
  with hover-revealed quiet row actions; Skeleton loading.
- Help: EmptyState for no search hits, flat hover shift on resource links.
- Chart of accounts: spinner loading blocks -> Skeleton rows.
- Kunskap graph + salary calendar popovers: rounded-lg, Input/Textarea
  primitives instead of hand-rolled shadow-sm controls.

No logic, endpoint, or data changes. Verified via sandbox screenshots;
lint 0 errors, 13214 tests green.

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

* fix(ui): review triage: skip empty industry sectors, keyboard path to schedule edit

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

---------

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 16:40:19 +02:00

87 lines
2.6 KiB
TypeScript

'use client'
import { useEffect, useState } from 'react'
import { useTranslations } from 'next-intl'
import { Skeleton } from '@/components/ui/skeleton'
import { EmptyState } from '@/components/ui/empty-state'
import { Brain } from 'lucide-react'
import type { LedgerContext } from '@/lib/agent-context/ledger-context'
import type { DeepLedgerContext } from '@/lib/agent-context/ledger-deep'
import type { AgentCompetence } from '@/lib/agent-context/agent-competence'
import { AgentKnowledgeView } from './AgentKnowledgeView'
interface KnowledgePayload {
context: LedgerContext
deep: DeepLedgerContext
competence: AgentCompetence
companyName: string
}
/**
* Client wrapper for the "Vad din agent vet" view inside the assistant
* settings hub. Fetches the ledger context from /api/agent/knowledge on mount
* (lazy: this panel only renders when the Kunskap tab is opened, since Radix
* unmounts inactive tabs). Fetching client-side rather than via a server prop
* is deliberate: the settings sections mount as propless components in BOTH
* the full-page rail and the routed settings modal, so a server fetch wouldn't
* reach the modal.
*/
export function AgentKnowledgePanel() {
const t = useTranslations('agentKnowledge')
const [payload, setPayload] = useState<KnowledgePayload | null>(null)
const [error, setError] = useState(false)
useEffect(() => {
let cancelled = false
fetch('/api/agent/knowledge')
.then((res) => {
if (!res.ok) throw new Error(`knowledge fetch failed: ${res.status}`)
return res.json()
})
.then((json) => {
if (!cancelled) setPayload(json.data as KnowledgePayload)
})
.catch(() => {
if (!cancelled) setError(true)
})
return () => {
cancelled = true
}
}, [])
if (error) {
return (
<EmptyState
icon={Brain}
title={t('load_error_title')}
description={t('load_error_description')}
/>
)
}
if (!payload) {
// Mirrors the loaded layout: graph hero, section header, two profile cards.
return (
<div className="space-y-8">
<Skeleton className="h-96 w-full rounded-lg" />
<div className="space-y-4">
<Skeleton className="h-4 w-40" />
<div className="grid gap-4 md:grid-cols-2">
<Skeleton className="h-48 w-full rounded-lg" />
<Skeleton className="h-48 w-full rounded-lg" />
</div>
</div>
</div>
)
}
return (
<AgentKnowledgeView
context={payload.context}
deep={payload.deep}
competence={payload.competence}
companyName={payload.companyName}
/>
)
}