'use client'; import { useState, useEffect, useCallback } from 'react'; import { AdminNav } from '@/components/AdminNav'; import { Badge, Button, Card, Spinner } from '@/components/ui'; import { api } from '@/lib/api'; import { formatDate, formatTransactionAmount } from '@/lib/utils'; import type { AdminTransaction, AdminTransactionPage, TransactionType } from '@/lib/types'; const PAGE_SIZE = 50; type FilterType = 'all' | TransactionType; const FILTERS: { value: FilterType; label: string }[] = [ { value: 'all', label: 'Все' }, { value: 'earn', label: 'Начисление' }, { value: 'spend', label: 'Списание' }, { value: 'admin_grant', label: 'Вручную' }, { value: 'expire', label: 'Сгорание' }, ]; export default function AdminTransactionsPage() { const [transactions, setTransactions] = useState([]); const [total, setTotal] = useState(0); const [offset, setOffset] = useState(0); const [filter, setFilter] = useState('all'); const [loading, setLoading] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [error, setError] = useState(null); const fetchPage = useCallback(async (currentOffset: number, txFilter: FilterType, append: boolean) => { if (append) setLoadingMore(true); else setLoading(true); setError(null); const typeParam = txFilter !== 'all' ? `&type=${txFilter}` : ''; try { const page = await api.get( `/api/v1/admin/transactions?limit=${PAGE_SIZE}&offset=${currentOffset}${typeParam}`, ); setTransactions((prev) => (append ? [...prev, ...page.transactions] : page.transactions)); setTotal(page.total); } catch (e) { setError(e instanceof Error ? e.message : 'Ошибка загрузки'); } finally { setLoading(false); setLoadingMore(false); } }, []); useEffect(() => { setOffset(0); fetchPage(0, filter, false); }, [filter, fetchPage]); function handleLoadMore() { const next = offset + PAGE_SIZE; setOffset(next); fetchPage(next, filter, true); } const hasMore = transactions.length < total; return (

Все транзакции

{/* Type filter */}
{FILTERS.map((f) => ( ))}
{loading && (
)} {error && (

{error}

)} {!loading && ( {transactions.length === 0 ? (

Транзакций нет

) : ( {transactions.map((tx) => ( ))}
Студент Тип Сумма Описание Дата
{tx.user_email} = 0 ? 'text-green-400' : 'text-red-400' }`} > {formatTransactionAmount(tx.amount)} {tx.description || '—'} {formatDate(tx.created_at)}
)}
)} {!loading && hasMore && (
)} {!loading && !hasMore && transactions.length > 0 && (

Показано {transactions.length} из {total}

)}
); }