import { Badge } from '@/components/ui/badge' import { formatDate } from '@/lib/utils' import { SettingsRow, SettingsRowNote } from '@/components/settings/SettingsRows' // Read-only "Bolagsuppgifter" view of the cached TIC company profile // (companies.tic_snapshot), rendered as flat settings rows inside the // section's SettingsGroup. Lives in core: reads the snapshot as plain // JSON rather than importing the TIC extension's types, so the // core-build CI boundary (no core → @/extensions/) stays intact. // // The snapshot is written by the TIC /profile endpoint; shape mirrors // TICCompanyProfile. We type only the fields we render and treat // everything as optional/defensive since older snapshots predate some // sections. interface SnapshotShape { companyName?: string | null orgNumber?: string | null legalEntityType?: string | null address?: { street?: string | null; postalCode?: string | null; city?: string | null } | null registration?: { fTax?: boolean; vat?: boolean; payroll?: boolean } | null sniCodes?: { code: string; name: string }[] | null bankAccounts?: { type: string; accountNumber: string; bic?: string | null }[] | null purpose?: string | null employeeRange?: string | null financials?: { periodStart?: number periodEnd?: number netSalesK?: number | null operatingProfitK?: number | null } | null statuses?: { code?: string | null description?: string | null color?: 'red' | 'yellow' | 'green' | 'neutral' | string | null statusDate?: string | null isCeased?: boolean | null }[] | null fiscalYear?: { startMonthDay?: string | null; endMonthDay?: string | null } | null signatory?: { description: string }[] | null board?: { numberOfBoardMembers?: number | null numberOfDeputyBoardMembers?: number | null } | null representatives?: { name?: string | null positionType?: string | null positionStart?: string | null }[] | null } // Clean Bolagsverket signatory text: the source carries ">" list markers // and collapses several rules onto one line. Strip the markers, normalise // whitespace, and split run-on "Firman tecknas …" clauses onto their own // lines so each rule reads as a sentence. function cleanSignatory(raw: string | null | undefined): string[] { // The snapshot is unvalidated registry JSON: `description` is declared // required inside an interface whose every other field is optional, so a // signatory row without one would throw here and blank the settings panel. if (!raw) return [] const normalised = raw .replace(/>/g, ' ') .replace(/\s+/g, ' ') .trim() // Each firmateckningsregel starts with "Firman tecknas". Split on the // boundary before subsequent occurrences so they stack vertically. return normalised .split(/(?=Firman tecknas)/g) .map((s) => s.trim()) .filter((s) => s.length > 0) } export function CompanyProfileView({ snapshot }: { snapshot: SnapshotShape | null }) { if (!snapshot) { // Dynamic status (nothing fetched yet): stays visible as a quiet line. return (
Inga företagsuppgifter hämtade ännu. Uppgifterna hämtas automatiskt från Bolagsverket via organisationsnumret.
) } const entityLabel = snapshot.legalEntityType === 'AB' ? 'Aktiebolag' : snapshot.legalEntityType === 'EF' ? 'Enskild firma' : snapshot.legalEntityType ?? null const reg = snapshot.registration const regBadges = [ reg?.fTax ? 'F-skatt' : null, reg?.vat ? 'Moms' : null, reg?.payroll ? 'Arbetsgivare' : null, ].filter(Boolean) as string[] const fyLabel = snapshot.fiscalYear?.startMonthDay && snapshot.fiscalYear?.endMonthDay ? `${snapshot.fiscalYear.startMonthDay} till ${snapshot.fiscalYear.endMonthDay}` : null // Only show dated status entries: Bolagsverket emits informational // flags like "Har aldrig varit verksam" with no date that read as // noise next to the real ones. Plain text, no colour: per the // design system, semantic colour is data-only and never chrome. const datedStatuses = (snapshot.statuses ?? []).filter((s) => s.statusDate) // Flatten every signatory row, clean ">" markers, split run-on // clauses, and dedupe: the source repeats "Firman tecknas av // styrelsen" across rows. const signatoryRules = Array.from( new Set( (snapshot.signatory ?? []).flatMap((s) => cleanSignatory(s.description)), ), ) return ( <>{snapshot.purpose}
{[ snapshot.board.numberOfBoardMembers != null ? `${snapshot.board.numberOfBoardMembers} styrelseledamot/-ledamöter` : null, snapshot.board.numberOfDeputyBoardMembers != null ? `${snapshot.board.numberOfDeputyBoardMembers} suppleant(er)` : null, ] .filter(Boolean) .join(' · ')}
)}