62 lines
2.4 KiB
TypeScript
62 lines
2.4 KiB
TypeScript
import { serverFetch } from '@/lib/api'
|
|
import type { Account, Budget, TransferRule } from '@/lib/types'
|
|
import { TransactionFilters } from '@/components/transactions/TransactionFilters'
|
|
import { TransactionTable } from '@/components/transactions/TransactionTable'
|
|
import { TransferRulesButton } from '@/components/transactions/TransferRulesButton'
|
|
|
|
const PAGE_LIMIT = 50
|
|
|
|
type SearchParams = Promise<Record<string, string | string[] | undefined>>
|
|
|
|
export default async function TransactionsPage({ searchParams }: { searchParams: SearchParams }) {
|
|
const sp = await searchParams
|
|
const get = (key: string) => (Array.isArray(sp[key]) ? sp[key][0] : sp[key]) ?? ''
|
|
|
|
const page = Math.max(1, Number(get('page')) || 1)
|
|
const accountId = get('accountId')
|
|
const dateFrom = get('dateFrom')
|
|
const dateTo = get('dateTo')
|
|
const type = get('type')
|
|
const search = get('search')
|
|
|
|
const params = new URLSearchParams({ page: String(page), limit: String(PAGE_LIMIT) })
|
|
if (accountId) params.set('accountId', accountId)
|
|
if (dateFrom) params.set('dateFrom', dateFrom)
|
|
if (dateTo) params.set('dateTo', dateTo)
|
|
if (type) params.set('type', type)
|
|
if (search) params.set('search', search)
|
|
|
|
const [txRes, accountsRes, budgetsRes, rulesRes] = await Promise.all([
|
|
serverFetch(`/api/transactions?${params}`),
|
|
serverFetch('/api/accounts'),
|
|
serverFetch('/api/budgets'),
|
|
serverFetch('/api/transfer-rules'),
|
|
])
|
|
|
|
const txData = txRes.ok ? await txRes.json() : { transactions: [], total: 0 }
|
|
const allAccounts: Account[] = accountsRes.ok ? await accountsRes.json() : []
|
|
const allBudgets: Budget[] = budgetsRes.ok ? await budgetsRes.json() : []
|
|
const transferRules: TransferRule[] = rulesRes.ok ? await rulesRes.json() : []
|
|
|
|
const accountOptions = allAccounts.map(({ id, name }) => ({ id, name }))
|
|
const budgetOptions = allBudgets.filter((b) => b.isActive).map(({ id, name, color }) => ({ id, name, color }))
|
|
|
|
return (
|
|
<div className="p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h1 className="text-2xl font-bold">Transactions</h1>
|
|
<TransferRulesButton rules={transferRules} />
|
|
</div>
|
|
<TransactionFilters accounts={accountOptions} />
|
|
<TransactionTable
|
|
transactions={txData.transactions ?? []}
|
|
total={txData.total ?? 0}
|
|
page={page}
|
|
limit={PAGE_LIMIT}
|
|
showAccount
|
|
budgets={budgetOptions}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|