feat: Add 4 major features to BOC Dashboard

1. Balance Sheet Chart — grafisk visning med progress bars
   - Assets (grön), Liabilities (röd), Equity (blå)
   - Balance check längst ner

2. Period-väljare — dropdown för månadsval
   - 2026-02, 2026-03, 2026-04

3. Drill-down — klicka på konto för transaktionshistorik
   - Modal med Date, Description, Debit, Credit, Balance
   - Mock data (ersätt med API-anrop)

4. Export-knappar — SIE4, PDF, CSV
   - Download-funktionalitet
   - Loading-tillstånd

Alla komponenter bygger och integreras i DashboardPage.
This commit is contained in:
Bernt
2026-07-29 20:17:34 +00:00
parent f793fc46a4
commit dd145bc3d9
9 changed files with 791 additions and 467 deletions
+50 -9
View File
@@ -2,6 +2,9 @@ import { useEffect, useState } from 'react'
import { KPICard } from '@/components/KPICard'
import { RevenueChart } from '@/components/RevenueChart'
import { ActivityFeed } from '@/components/ActivityFeed'
import { BalanceSheetChart } from '@/components/BalanceSheetChart'
import { AccountDetailModal } from '@/components/AccountDetailModal'
import { ExportButtons } from '@/components/ExportButtons'
import { Card, CardHeader } from '@/components/ui/Card'
import { Skeleton } from '@/components/ui/Skeleton'
import {
@@ -67,6 +70,9 @@ export function DashboardPage() {
const [ledgerEquity, setLedgerEquity] = useState(0)
const [netIncome, setNetIncome] = useState(0)
const [ledgerAccounts, setLedgerAccounts] = useState<LedgerAccount[]>([])
const [balanceSheetData, setBalanceSheetData] = useState<any>(null)
const [selectedPeriod, setSelectedPeriod] = useState('2026-02')
const [selectedAccount, setSelectedAccount] = useState<{code: string, name: string} | null>(null)
useEffect(() => {
async function fetchData() {
@@ -99,6 +105,7 @@ export function DashboardPage() {
setLedgerAssets(ledgerBs.total_assets || 0)
setLedgerLiabilities(ledgerBs.total_liabilities || 0)
setLedgerEquity(ledgerBs.total_equity || 0)
setBalanceSheetData(ledgerBs)
}
if (ledgerIs) {
setNetIncome(ledgerIs.net_income || 0)
@@ -215,6 +222,20 @@ export function DashboardPage() {
))}
</div>
{/* Period Selector */}
<div className="flex items-center gap-4">
<label className="text-sm font-medium">Period:</label>
<select
value={selectedPeriod}
onChange={(e) => setSelectedPeriod(e.target.value)}
className="border rounded px-3 py-1 text-sm"
>
<option value="2026-02">2026-02</option>
<option value="2026-03">2026-03</option>
<option value="2026-04">2026-04</option>
</select>
</div>
{/* Ledger KPI Cards */}
<div className="mt-8">
<h2 className="text-lg font-semibold mb-4">Ledger (Bokföring)</h2>
@@ -225,6 +246,11 @@ export function DashboardPage() {
</div>
</div>
{/* Balance Sheet Chart */}
{balanceSheetData && (
<BalanceSheetChart data={balanceSheetData} />
)}
{/* Infrastructure Health — Grafana Integration */}
<Card>
<CardHeader
@@ -303,15 +329,18 @@ export function DashboardPage() {
) : (
ledgerAccounts.map((account) => (
<TableRow key={account.code}>
<TableCell className="font-medium">{account.code}</TableCell>
<TableCell>{account.name}</TableCell>
<TableCell>
<Badge>{account.account_type}</Badge>
</TableCell>
<TableCell className="text-right">
<span className={account.balance >= 0 ? 'text-success' : 'text-danger'}>
{formatCurrency(account.balance)}
</span>
<TableCell colSpan={4} className="p-0">
<div
className="flex items-center px-4 py-3 cursor-pointer hover:bg-surface-2"
onClick={() => setSelectedAccount({ code: account.code, name: account.name })}
>
<span className="font-medium w-16">{account.code}</span>
<span className="flex-1">{account.name}</span>
<span className="w-24"><Badge>{account.account_type}</Badge></span>
<span className={`w-32 text-right ${account.balance >= 0 ? 'text-success' : 'text-danger'}`}>
{formatCurrency(account.balance)}
</span>
</div>
</TableCell>
</TableRow>
))
@@ -385,6 +414,18 @@ export function DashboardPage() {
</div>
</Card>
{/* Export Buttons */}
<ExportButtons period={selectedPeriod} />
{/* Account Detail Modal */}
{selectedAccount && (
<AccountDetailModal
accountCode={selectedAccount.code}
accountName={selectedAccount.name}
onClose={() => setSelectedAccount(null)}
/>
)}
{/* Recent Deals */}
<Card>
<CardHeader