* 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>
55 lines
2.0 KiB
TypeScript
55 lines
2.0 KiB
TypeScript
import { getTranslations } from 'next-intl/server'
|
|
import { SECTORS } from '@/lib/extensions/sectors'
|
|
import { sectorNameKey } from '@/lib/extensions/i18n'
|
|
import { PageHeader } from '@/components/ui/page-header'
|
|
import ExtensionCard from '@/components/extensions/ExtensionCard'
|
|
import SectorCard from '@/components/extensions/SectorCard'
|
|
|
|
export default async function ExtensionsPage() {
|
|
const t = await getTranslations('extensions')
|
|
const generalSector = SECTORS.find(s => s.slug === 'general')
|
|
// Only sectors that actually ship extensions: a shell with zero extensions
|
|
// would render a dead card and an empty grid.
|
|
const industrySectors = SECTORS.filter(s => s.slug !== 'general' && s.extensions.length > 0)
|
|
|
|
const generalSectorName = (() => {
|
|
if (!generalSector) return ''
|
|
const key = sectorNameKey(generalSector.slug)
|
|
return key ? t(key) : generalSector.name
|
|
})()
|
|
|
|
return (
|
|
<div className="space-y-8">
|
|
<PageHeader title={t('page_title')} />
|
|
|
|
{/* General extensions */}
|
|
{generalSector && (
|
|
<section>
|
|
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-4">
|
|
{generalSectorName}
|
|
</h2>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 stagger-enter">
|
|
{generalSector.extensions.map(ext => (
|
|
<ExtensionCard key={ext.slug} extension={ext} />
|
|
))}
|
|
</div>
|
|
</section>
|
|
)}
|
|
|
|
{/* Industry sectors (hidden while no industry sector ships extensions) */}
|
|
{industrySectors.length > 0 && (
|
|
<section>
|
|
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-4">
|
|
{t('industry_tools')}
|
|
</h2>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 stagger-enter">
|
|
{industrySectors.map(sector => (
|
|
<SectorCard key={sector.slug} sector={sector} />
|
|
))}
|
|
</div>
|
|
</section>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|