* 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>
61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
import { notFound } from 'next/navigation'
|
|
import { getTranslations } from 'next-intl/server'
|
|
import { getSector } from '@/lib/extensions/sectors'
|
|
import { resolveIcon } from '@/lib/extensions/icon-resolver'
|
|
import { sectorNameKey, sectorDescriptionKey } from '@/lib/extensions/i18n'
|
|
import type { SectorSlug } from '@/lib/extensions/types'
|
|
import ExtensionCard from '@/components/extensions/ExtensionCard'
|
|
import Link from 'next/link'
|
|
|
|
export default async function SectorExtensionsPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ sector: string }>
|
|
}) {
|
|
const { sector: sectorSlug } = await params
|
|
const sector = getSector(sectorSlug as SectorSlug)
|
|
|
|
if (!sector) notFound()
|
|
|
|
const t = await getTranslations('extensions')
|
|
|
|
const nameKey = sectorNameKey(sector.slug)
|
|
const descriptionKey = sectorDescriptionKey(sector.slug)
|
|
const sectorName = nameKey ? t(nameKey) : sector.name
|
|
const sectorDescription = descriptionKey ? t(descriptionKey) : sector.description
|
|
|
|
|
|
const Icon = resolveIcon(sector.icon)
|
|
|
|
return (
|
|
<div>
|
|
{/* Breadcrumb */}
|
|
<nav className="flex items-center gap-1.5 text-sm text-muted-foreground mb-6">
|
|
<Link href="/extensions" className="hover:text-foreground transition-colors">
|
|
{t('breadcrumb')}
|
|
</Link>
|
|
<span>/</span>
|
|
<span className="text-foreground">{sectorName}</span>
|
|
</nav>
|
|
|
|
{/* Header */}
|
|
<div className="flex items-start gap-4 mb-8">
|
|
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-secondary flex-shrink-0">
|
|
<Icon className="h-6 w-6 text-foreground" />
|
|
</div>
|
|
<div>
|
|
<h1 className="font-display text-2xl leading-8 tracking-tight">{sectorName}</h1>
|
|
<p className="text-sm text-muted-foreground mt-0.5">{sectorDescription}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Extensions grid */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 stagger-enter">
|
|
{sector.extensions.map(ext => (
|
|
<ExtensionCard key={ext.slug} extension={ext} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|