// Copyright (c) 2026 PowerOn AG // All rights reserved. /** * useBilling Hook * * Hook für die Verwaltung von Billing-Daten. * Bietet Zugriff auf Guthaben, Transaktionen, Statistiken und Admin-Funktionen. */ import { useState, useEffect, useCallback } from 'react'; import { useApiRequest } from './useApi'; import { fetchBalances, fetchBalanceForMandate, fetchTransactions, fetchTransactionsPaginated, fetchStatistics, fetchAllowedProviders, fetchSettingsAdmin, updateSettingsAdmin, addCreditAdmin, createCheckoutSession as createCheckoutSessionApi, fetchAccountsAdmin, fetchTransactionsAdmin, fetchUsersForMandateAdmin, type BillingBalance, type BillingTransaction, type BillingSettings, type BillingSettingsUpdate, type UsageReport, type AccountSummary, type CreditAddRequest, type CheckoutCreateRequest, type MandateUserSummary, type StatisticsRangeRequest, type BillingBucketSize, type BillingTransactionsPaginationParams, } from '../api/billingApi'; import type { GroupLayout } from '../api/connectionApi'; // Re-export types export type { BillingBalance, BillingTransaction, BillingSettings, BillingSettingsUpdate, UsageReport, AccountSummary, CreditAddRequest, MandateUserSummary, StatisticsRangeRequest, BillingBucketSize, }; export type { TransactionType, ReferenceType, BillingTransactionsPaginationParams } from '../api/billingApi'; /** * Hook for user billing operations */ export function useBilling() { const [balances, setBalances] = useState([]); const [transactions, setTransactions] = useState([]); const [transactionsPagination, setTransactionsPagination] = useState<{ currentPage: number; pageSize: number; totalItems: number; totalPages: number; } | null>(null); const [transactionsGroupLayout, setTransactionsGroupLayout] = useState(null); const [transactionsAppliedView, setTransactionsAppliedView] = useState<{ viewKey?: string; displayName?: string; } | null>(null); const [statistics, setStatistics] = useState(null); const [allowedProviders, setAllowedProviders] = useState([]); const { request, isLoading: loading, error } = useApiRequest(); // Fetch all balances for the user const loadBalances = useCallback(async () => { try { const data = await fetchBalances(request); setBalances(Array.isArray(data) ? data : []); return data; } catch (err) { console.error('Error loading balances:', err); setBalances([]); return []; } }, [request]); // Fetch balance for a specific mandate const loadBalanceForMandate = useCallback(async (mandateId: string) => { try { return await fetchBalanceForMandate(request, mandateId); } catch (err) { console.error('Error loading balance for mandate:', err); return null; } }, [request]); // Fetch transactions const loadTransactions = useCallback(async (limit: number = 50, offset: number = 0) => { try { const data = await fetchTransactions(request, limit, offset); setTransactions(Array.isArray(data) ? data : []); setTransactionsPagination(null); setTransactionsGroupLayout(null); setTransactionsAppliedView(null); return data; } catch (err) { console.error('Error loading transactions:', err); setTransactions([]); setTransactionsPagination(null); setTransactionsGroupLayout(null); setTransactionsAppliedView(null); return []; } }, [request]); const refetchTransactions = useCallback(async (params?: BillingTransactionsPaginationParams) => { try { const data = await fetchTransactionsPaginated(request, params); setTransactions(Array.isArray(data.items) ? data.items : []); setTransactionsPagination(data.pagination ?? null); setTransactionsGroupLayout(data.groupLayout ?? null); setTransactionsAppliedView(data.appliedView ?? null); return data; } catch (err) { console.error('Error loading transactions:', err); setTransactions([]); setTransactionsPagination(null); setTransactionsGroupLayout(null); setTransactionsAppliedView(null); return null; } }, [request]); const loadStatistics = useCallback(async (range: StatisticsRangeRequest) => { try { const data = await fetchStatistics(request, range); setStatistics(data); return data; } catch (err) { console.error('Error loading statistics:', err); setStatistics(null); return null; } }, [request]); // Fetch allowed providers const loadAllowedProviders = useCallback(async () => { try { const data = await fetchAllowedProviders(request); setAllowedProviders(Array.isArray(data) ? data : []); return data; } catch (err) { console.error('Error loading allowed providers:', err); setAllowedProviders([]); return []; } }, [request]); // Initial load useEffect(() => { loadBalances(); loadAllowedProviders(); }, []); return { balances, transactions, transactionsPagination, transactionsGroupLayout, transactionsAppliedView, statistics, allowedProviders, loading, error, loadBalances, loadBalanceForMandate, loadTransactions, refetchTransactions, loadStatistics, loadAllowedProviders, refetch: loadBalances, }; } /** * Hook for admin billing operations */ export function useBillingAdmin(mandateId?: string) { const [settings, setSettings] = useState(null); const [accounts, setAccounts] = useState([]); const [transactions, setTransactions] = useState([]); const [users, setUsers] = useState([]); const { request, isLoading: loading, error } = useApiRequest(); // Fetch settings for a mandate const loadSettings = useCallback(async (targetMandateId?: string) => { const mId = targetMandateId || mandateId; if (!mId) return null; try { const data = await fetchSettingsAdmin(request, mId); setSettings(data); return data; } catch (err) { console.error('Error loading billing settings:', err); setSettings(null); return null; } }, [request, mandateId]); // Fetch accounts for a mandate const loadAccounts = useCallback(async (targetMandateId?: string) => { const mId = targetMandateId || mandateId; if (!mId) return []; try { const data = await fetchAccountsAdmin(request, mId); setAccounts(Array.isArray(data) ? data : []); return data; } catch (err) { console.error('Error loading accounts:', err); setAccounts([]); return []; } }, [request, mandateId]); // Fetch transactions for a mandate const loadTransactions = useCallback(async (targetMandateId?: string, limit: number = 100) => { const mId = targetMandateId || mandateId; if (!mId) return []; try { const data = await fetchTransactionsAdmin(request, mId, limit); setTransactions(Array.isArray(data) ? data : []); return data; } catch (err) { console.error('Error loading transactions:', err); setTransactions([]); return []; } }, [request, mandateId]); // Fetch users for a mandate const loadUsers = useCallback(async (targetMandateId?: string) => { const mId = targetMandateId || mandateId; if (!mId) return []; try { const data = await fetchUsersForMandateAdmin(request, mId); setUsers(Array.isArray(data) ? data : []); return data; } catch (err) { console.error('Error loading users:', err); setUsers([]); return []; } }, [request, mandateId]); const saveSettings = useCallback( async (settingsUpdate: BillingSettingsUpdate, targetMandateId?: string) => { const mId = targetMandateId || mandateId; if (!mId) return null; try { const data = await updateSettingsAdmin(request, mId, settingsUpdate); setSettings(data); return data; } catch (err) { console.error('Error saving billing settings:', err); throw err; } }, [request, mandateId] ); // Add credit (manual, admin) const addCredit = useCallback( async (creditRequest: CreditAddRequest, targetMandateId?: string) => { const mId = targetMandateId || mandateId; if (!mId) return null; try { const result = await addCreditAdmin(request, mId, creditRequest); await loadAccounts(mId); return result; } catch (err) { console.error('Error adding credit:', err); throw err; } }, [request, mandateId, loadAccounts] ); // Create Stripe Checkout Session (returns redirect URL) const createCheckout = useCallback( async (checkoutRequest: CheckoutCreateRequest, targetMandateId?: string) => { const mId = targetMandateId || mandateId; if (!mId) return null; try { return await createCheckoutSessionApi(request, mId, checkoutRequest); } catch (err) { console.error('Error creating checkout session:', err); throw err; } }, [request, mandateId] ); // Load data when mandateId changes useEffect(() => { if (mandateId) { loadSettings(); loadAccounts(); loadTransactions(); loadUsers(); } }, [mandateId]); return { settings, accounts, transactions, users, loading, error, loadSettings, saveSettings, addCredit, createCheckout, loadAccounts, loadTransactions, loadUsers, refetch: () => { if (mandateId) { loadSettings(); loadAccounts(); loadTransactions(); loadUsers(); } }, }; } export default useBilling;