'use client' import { useTranslations } from 'next-intl' import { Brain } from 'lucide-react' import { Card, CardHeader, CardTitle, CardDescription, CardContent, } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Table, TableHeader, TableBody, TableHead, TableRow, TableCell, } from '@/components/ui/table' import { AccountNumber } from '@/components/ui/account-number' import { EmptyState } from '@/components/ui/empty-state' import { formatDateLong } from '@/lib/utils' 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 { LedgerGraph } from './LedgerGraph' import { CompetenceCard, FactsCard } from './AgentCompetenceSections' import { KnowledgeTabs } from './KnowledgeTabs' // Swedish VAT (moms) treatment codes stay Swedish in both locales, like BAS // account names and momsdeklaration labels (.claude/rules/i18n.md). const VAT_LABELS: Record = { standard_25: 'Moms 25%', standard_12: 'Moms 12%', standard_6: 'Moms 6%', reduced_12: 'Moms 12%', reduced_6: 'Moms 6%', reverse_charge: 'Omvänd moms', reverse_charge_eu: 'Omvänd moms (EU)', reverse_charge_services: 'Omvänd moms (tjänster)', eu_reverse_charge_services: 'Omvänd moms (EU-tjänster)', eu_goods: 'EU-varor', export: 'Export', exempt: 'Momsfri', no_vat: 'Ingen moms', } function vatLabel(code: string | null): string | null { if (!code) return null return VAT_LABELS[code] ?? code } export function AgentKnowledgeView({ context, deep, competence, companyName, }: { context: LedgerContext deep: DeepLedgerContext competence: AgentCompetence companyName: string }) { const t = useTranslations('agentKnowledge') const { meta, explicit_rules, vat_profile, conventions } = context const entities = [...deep.counterparty_entities, ...deep.supplier_entities] const isEmpty = meta.coverage.posted_entries_window === 0 && entities.length === 0 && explicit_rules.length === 0 if (isEmpty) { // No bookings yet, but the agent still ships with competence and may // already remember facts: show those rather than a dead end. return ( <>
) } const methodLabel = conventions.accounting_method === 'accrual' ? t('method_accrual') : conventions.accounting_method === 'cash' ? t('method_cash') : t('method_unknown') const periodLabel = vat_profile.moms_period === 'monthly' ? t('period_monthly') : vat_profile.moms_period === 'quarterly' ? t('period_quarterly') : vat_profile.moms_period === 'yearly' ? t('period_yearly') : (vat_profile.moms_period ?? t('unknown')) // "Regler & profil" tab: user-authored rules + observed VAT + conventions. const configContent = ( <> {explicit_rules.length > 0 && ( {t('rules_title')} {t('rules_description')} {t('col_rule')} {t('col_match')} {t('col_account')} {t('col_vat')} {explicit_rules.map((r, i) => (
{r.rule_name} {t('src_rule')}
{r.match} {r.account_number ? : -} {vatLabel(r.vat_treatment) ?? '-'}
))}
)}
{t('vat_title')} {t('vat_description')} {vat_profile.registered ? t('yes') : t('no')} {periodLabel} {vat_profile.treatments_used_12m.length === 0 ? ( {t('vat_no_treatments')} ) : (
{vat_profile.treatments_used_12m.map((code) => ( {vatLabel(code)} ))}
)}
{t('conv_title')} {t('conv_description')} {methodLabel} {conventions.voucher_series_in_use.length === 0 ? ( - ) : (
{conventions.voucher_series_in_use.map((s) => ( {s} ))}
)}
{conventions.salary_run_active ? t('yes') : t('no')} {conventions.typical_booking_lag_days !== null && ( {t('meta_lag_value', { days: conventions.typical_booking_lag_days })} )}
) const tabs = [ { value: 'competence', label: t('tab_competence'), content: }, { value: 'memory', label: t('tab_memory'), content: }, { value: 'config', label: t('tab_config'), content: configContent }, ] return ( <> {/* The cinematic hero: a self-contained dark panel with its own header */} {/* Supporting detail, tabbed so it doesn't stack into a long scroll */}

{t('footer_basis', { entries: meta.coverage.posted_entries_window, date: formatDateLong(meta.computed_at) })}

) } function Row({ label, children }: { label: string; children: React.ReactNode }) { return (
{label}
{children}
) }