'use client' import { useState, useEffect } from 'react' import Link from 'next/link' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { formatCurrency } from '@/lib/utils' import { calculateEFTax, calculateABTax, getEnhancedTaxWarningStatus } from '@/lib/tax/calculator' import { getSchablonavdragSummary } from '@/lib/tax/schablonavdrag' import FSkattWarningCard from '@/components/dashboard/FSkattWarningCard' import { UpcomingDeadlinesWidget } from '@/components/calendar/UpcomingDeadlinesWidget' import NewUserChecklist from '@/components/onboarding/NewUserChecklist' import { TrendingUp, TrendingDown, Receipt, ArrowLeftRight, ChevronDown, ArrowRight, Camera, HelpCircle, Users, FileText, } from 'lucide-react' import type { CompanySettings, EntityType, MileageEntry, SchablonavdragSettings, Deadline, ReceiptQueueSummary, OnboardingProgress } from '@/types' interface DashboardContentProps { firstName?: string | null settings: CompanySettings | null summary: { ytd: { income: number; expenses: number; net: number } mtd: { income: number; expenses: number; net: number } uncategorizedCount: number uncategorizedIncome: number uncategorizedExpenses: number unpaidInvoicesCount: number unpaidInvoicesTotal: number unpaidVatTotal: number overdueInvoicesCount: number bankBalance: number | null mileageEntries: MileageEntry[] deadlines: Deadline[] receiptQueue: ReceiptQueueSummary | null } onboardingProgress?: OnboardingProgress } export default function DashboardContent({ firstName, settings, summary, onboardingProgress }: DashboardContentProps) { const [showAllAlerts, setShowAllAlerts] = useState(false) const entityType = (settings?.entity_type as EntityType) || 'enskild_firma' const preliminaryTaxMonthly = settings?.preliminary_tax_monthly || 0 const currentMonth = new Date().getMonth() + 1 const preliminaryTaxPaidYTD = preliminaryTaxMonthly * currentMonth const schablonavdragSettings = (settings as CompanySettings & { schablonavdrag_settings?: SchablonavdragSettings })?.schablonavdrag_settings || null const schablonavdragSummary = getSchablonavdragSummary( schablonavdragSettings, summary.mileageEntries, new Date().getFullYear(), currentMonth ) const totalTaxableIncome = summary.ytd.net const taxEstimate = entityType === 'enskild_firma' ? calculateEFTax(totalTaxableIncome, preliminaryTaxPaidYTD, schablonavdragSummary, summary.unpaidVatTotal) : calculateABTax(totalTaxableIncome, 0, preliminaryTaxPaidYTD, summary.unpaidVatTotal) const taxWarning = getEnhancedTaxWarningStatus(taxEstimate, preliminaryTaxMonthly, currentMonth) const formatLargeNumber = (amount: number) => { return new Intl.NumberFormat('sv-SE', { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(amount) } const isNewUser = onboardingProgress && !onboardingProgress.hasInvoices && !onboardingProgress.hasCustomers // Build alert items for "Att hantera" section const alertItems: React.ReactNode[] = [] if (summary.overdueInvoicesCount > 0) { alertItems.push(

Förfallna fakturor

{summary.overdueInvoicesCount} förfallna

Kräver åtgärd
) } if (summary.unpaidInvoicesCount > 0 && summary.overdueInvoicesCount < summary.unpaidInvoicesCount) { alertItems.push(

Obetalda fakturor

{summary.unpaidInvoicesCount - summary.overdueInvoicesCount} obetalda · {formatCurrency(summary.unpaidInvoicesTotal)}

) } if (summary.uncategorizedCount > 0) { alertItems.push(

Transaktioner

{summary.uncategorizedCount} okategoriserade

) } if (summary.receiptQueue && (summary.receiptQueue.pending_review_count > 0 || summary.receiptQueue.unmatched_receipts_count > 0)) { alertItems.push(

Kvitton

{summary.receiptQueue.pending_review_count > 0 ? `${summary.receiptQueue.pending_review_count} att granska` : `${summary.receiptQueue.unmatched_receipts_count} omatchade`}

) } const MAX_VISIBLE_ALERTS = 3 const visibleAlerts = showAllAlerts ? alertItems : alertItems.slice(0, MAX_VISIBLE_ALERTS) const hasMoreAlerts = alertItems.length > MAX_VISIBLE_ALERTS // Quick action items const quickActions = [ { href: '/invoices/new', icon: Receipt, label: 'Ny faktura', desc: 'Skapa och skicka', accent: true }, { href: '/receipts/scan', icon: Camera, label: 'Skanna kvitto', desc: 'Fotografera & spara' }, { href: '/customers', icon: Users, label: 'Ny kund', desc: 'Lägg till kunduppgifter' }, { href: '/transactions', icon: ArrowLeftRight, label: 'Transaktioner', desc: 'Kategorisera' }, ] return (
{/* Hero section - personalized greeting */}

{(() => { const hour = new Date().getHours() if (hour < 12) return 'Godmorgon' if (hour < 18) return 'God eftermiddag' return 'God kväll' })()}{firstName ? ` ${firstName}` : ''}{settings?.company_name ? `, ${settings.company_name}` : ''}

{summary.overdueInvoicesCount > 0 ? `${summary.overdueInvoicesCount} förfallna fakturor kräver åtgärd` : summary.deadlines.filter(d => !d.is_completed && new Date(d.due_date) <= new Date()).length > 0 ? `${summary.deadlines.filter(d => !d.is_completed && new Date(d.due_date) <= new Date()).length} passerade deadlines` : 'Allt är som det ska'}

Hjälp
{/* TODO section - actionable items */} {(() => { const passedDeadlines = summary.deadlines.filter(d => !d.is_completed && new Date(d.due_date) <= new Date()) const todoItems: { label: string; href: string; count: number; variant: 'destructive' | 'warning' | 'default' }[] = [] if (passedDeadlines.length > 0) { todoItems.push({ label: 'passerade deadlines', href: '/calendar', count: passedDeadlines.length, variant: 'destructive' }) } if (summary.overdueInvoicesCount > 0) { todoItems.push({ label: 'förfallna fakturor', href: '/invoices?status=unpaid', count: summary.overdueInvoicesCount, variant: 'destructive' }) } if (summary.uncategorizedCount > 0) { todoItems.push({ label: 'okategoriserade transaktioner', href: '/transactions', count: summary.uncategorizedCount, variant: 'warning' }) } if (summary.receiptQueue && summary.receiptQueue.pending_review_count > 0) { todoItems.push({ label: 'kvitton att granska', href: '/receipts', count: summary.receiptQueue.pending_review_count, variant: 'default' }) } if (todoItems.length === 0) return null return (
{todoItems.map((item) => ( {item.count} {item.label} ))}
) })()} {/* New user checklist */} {onboardingProgress && (
)} {/* Upcoming deadlines - prominent placement */} {summary.deadlines && summary.deadlines.length > 0 && (
)} {/* Quick actions - moved up, as visual cards */}

Snabbåtgärder

{quickActions.map((action) => { const Icon = action.icon return (

{action.label}

{action.desc}

) })}
{/* F-skatt warning */}
{ window.location.href = '/settings' }} />
{/* Alerts section - with urgency indicators and limit */} {alertItems.length > 0 && (

Att hantera

{visibleAlerts}
{hasMoreAlerts && !showAllAlerts && ( )}
)} {/* Uncategorized transactions warning */} {summary.uncategorizedCount > 0 && (summary.uncategorizedIncome > 0 || summary.uncategorizedExpenses > 0) && (

{summary.uncategorizedCount} okategoriserade transaktioner påverkar ditt resultat

{summary.uncategorizedIncome > 0 && ( {formatCurrency(summary.uncategorizedIncome)} i potentiella intäkter )} {summary.uncategorizedIncome > 0 && summary.uncategorizedExpenses > 0 && ' och '} {summary.uncategorizedExpenses > 0 && ( {formatCurrency(summary.uncategorizedExpenses)} i potentiella kostnader )} {' '}visas inte i resultatet. Kategorisera dem för korrekt redovisning.

)} {/* Income/Expenses - Side by side editorial */}

Resultat

Intäkter

Denna månad

{formatLargeNumber(summary.mtd.income)} kr

I år totalt

{formatCurrency(summary.ytd.income)}

Kostnader

Denna månad

{formatLargeNumber(summary.mtd.expenses)} kr

I år totalt

{formatCurrency(summary.ytd.expenses)}

) }