Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import { ThemeProvider } from '@/components/ThemeProvider'
import { Accounts } from '@/routes/Accounts'
import { Overview } from '@/routes/Overview'

const queryClient = new QueryClient()

export function App() {
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<Overview />} />
</Routes>
</BrowserRouter>
</ThemeProvider>
</QueryClientProvider>
)
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<Overview />} />
<Route path="/accounts" element={<Accounts />} />
</Routes>
</BrowserRouter>
</ThemeProvider>
</QueryClientProvider>
)
}
20 changes: 20 additions & 0 deletions web/src/api/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2026 FinCore Engine Authors

const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? ''
const DEV_BEARER = import.meta.env.VITE_DEV_BEARER_TOKEN

export class ApiError extends Error {
constructor(readonly status: number) {
super(`request failed with status ${status}`)
this.name = 'ApiError'
}
}

export async function apiFetch<T>(path: string): Promise<T> {
const headers: Record<string, string> = { Accept: 'application/json' }
if (DEV_BEARER) headers.Authorization = `Bearer ${DEV_BEARER}`
const response = await fetch(`${BASE_URL}${path}`, { headers })
if (!response.ok) throw new ApiError(response.status)
return (await response.json()) as T
}
31 changes: 31 additions & 0 deletions web/src/api/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2026 FinCore Engine Authors

export type AccountType =
| 'ASSET'
| 'LIABILITY'
| 'EQUITY'
| 'REVENUE'
| 'EXPENSE'
| 'USER_WALLET'
| 'FEE'
| 'RESERVE'
| 'SUSPENSE'

export type AccountStatus = 'ACTIVE' | 'FROZEN' | 'CLOSED'

export interface AccountResponse {
id: string
name: string
type: AccountType
currency: string
status: AccountStatus
}

export interface PageResponse<T> {
items: T[]
page: number
size: number
totalElements: number
totalPages: number
}
84 changes: 45 additions & 39 deletions web/src/components/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,60 @@
// SPDX-FileCopyrightText: 2026 FinCore Engine Authors

import {
Activity,
ArrowDownUp,
BookOpen,
Check,
ChevronDown,
ChevronRight,
Code,
Copy,
Home,
Key,
Play,
Scale,
Search,
Send,
Shield,
Wallet,
type LucideIcon,
Activity,
AlertTriangle,
ArrowDownUp,
BookOpen,
Check,
ChevronDown,
ChevronLeft,
ChevronRight,
Code,
Copy,
Home,
Inbox,
Key,
Play,
Scale,
Search,
Send,
Shield,
Wallet,
type LucideIcon,
} from 'lucide-react'

const ICONS = {
home: Home,
wallet: Wallet,
arrows: ArrowDownUp,
send: Send,
scale: Scale,
shield: Shield,
book: BookOpen,
search: Search,
chevDown: ChevronDown,
chevRight: ChevronRight,
check: Check,
key: Key,
code: Code,
activity: Activity,
copy: Copy,
play: Play,
home: Home,
wallet: Wallet,
arrows: ArrowDownUp,
send: Send,
scale: Scale,
shield: Shield,
book: BookOpen,
search: Search,
chevDown: ChevronDown,
chevLeft: ChevronLeft,
chevRight: ChevronRight,
check: Check,
key: Key,
code: Code,
activity: Activity,
copy: Copy,
play: Play,
alert: AlertTriangle,
inbox: Inbox,
} satisfies Record<string, LucideIcon>

export type IconName = keyof typeof ICONS

interface IconProps {
name: IconName
size?: number
className?: string
style?: React.CSSProperties
name: IconName
size?: number
className?: string
style?: React.CSSProperties
}

export function Icon({ name, size = 14, className, style }: IconProps) {
const Glyph = ICONS[name]
return <Glyph size={size} strokeWidth={1.6} className={className} style={style} aria-hidden />
const Glyph = ICONS[name]
return <Glyph size={size} strokeWidth={1.6} className={className} style={style} aria-hidden />
}
Loading
Loading