'use client' import { useEffect, useState } from 'react' import { Check, Clock } from 'lucide-react' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Skeleton } from '@/components/ui/skeleton' import { formatDateLong } from '@/lib/utils' import { BillingActions } from '@/components/settings/BillingActions' // What the paid tier unlocks (mirrors lib/entitlements PAID_CAPABILITIES). const INCLUDED = [ 'AI-assistent: chatt, kategorisering och dokumenttolkning', 'Bankkoppling och automatisk synk (PSD2)', 'Skatteverket: moms- och AGI-inlämning', 'E-postutskick av fakturor, påminnelser och lönebesked', ] const ALWAYS_FREE = 'All bokföring, fakturering, rapporter, SIE-export, org.nr-uppslag och momsnummerkontroll ingår alltid utan kostnad.' interface BillingView { isPaying: boolean configured: boolean trialEndsAt: string | null daysLeft: number | null } /** * Settings → Abonnemang. Rendered both as the full page (thin wrapper) and * inside the settings modal (via SETTINGS_SECTIONS), so it's a client component * that reads its state from GET /api/billing/status. */ export function BillingSettingsContent() { const [view, setView] = useState(null) useEffect(() => { let active = true fetch('/api/billing/status') .then((r) => r.json()) .then((d: { isPaying: boolean; configured: boolean; trialEndsAt: string | null }) => { if (!active) return // Compute days-left here (effect), not during render, to keep render pure. const daysLeft = d.trialEndsAt ? Math.max(0, Math.ceil((new Date(d.trialEndsAt).getTime() - Date.now()) / 86_400_000)) : null setView({ ...d, daysLeft }) }) .catch(() => { if (active) setView({ isPaying: false, configured: false, trialEndsAt: null, daysLeft: null }) }) return () => { active = false } }, []) if (!view) { return (
) } // Paying company → manage view. if (view.isPaying) { return ( Abonnemang

Ditt abonnemang är aktivt. Du kan hantera eller avsluta det när som helst.

) } // Trialing / expired → sell view. const { trialEndsAt, daysLeft } = view return (
{daysLeft !== null && (
{daysLeft > 0 ? `Din provperiod löper ut om ${daysLeft} ${daysLeft === 1 ? 'dag' : 'dagar'}${ trialEndsAt ? ` (${formatDateLong(trialEndsAt)})` : '' }. Lägg till betalning nu så fortsätter allt utan avbrott.` : 'Din provperiod har löpt ut. Aktivera abonnemanget för att få tillbaka AI, bankkoppling och inlämning.'}
)} Allt du behöver för att sköta bokföringen själv
    {INCLUDED.map((item) => (
  • {item}
  • ))}

{ALWAYS_FREE} Avsluta när du vill. Ingen bindningstid.

) }