feat: transactions page

This commit is contained in:
Face 2025-05-31 13:38:17 +03:00
parent 2c98047ec0
commit c1bab8ac4a
2 changed files with 543 additions and 25 deletions

View file

@ -2,18 +2,63 @@ import { auth } from '$lib/auth';
import { error, json } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { transaction, coin } from '$lib/server/db/schema';
import { eq, desc } from 'drizzle-orm';
import { eq, desc, asc, and, or, ilike, sql } from 'drizzle-orm';
export async function GET({ request }) {
const session = await auth.api.getSession({
export async function GET({ request, url }) {
const authSession = await auth.api.getSession({
headers: request.headers
});
if (!session?.user) {
if (!authSession?.user) {
throw error(401, 'Not authenticated');
}
const userId = Number(session.user.id);
const userId = Number(authSession.user.id);
const searchQuery = url.searchParams.get('search') || '';
const typeFilter = url.searchParams.get('type') || 'all';
const sortBy = url.searchParams.get('sortBy') || 'timestamp';
const sortOrder = url.searchParams.get('sortOrder') || 'desc';
const page = parseInt(url.searchParams.get('page') || '1');
const limit = Math.min(parseInt(url.searchParams.get('limit') || '20'), 50);
let whereConditions = and(eq(transaction.userId, userId));
if (searchQuery) {
whereConditions = and(
whereConditions,
or(
ilike(coin.name, `%${searchQuery}%`),
ilike(coin.symbol, `%${searchQuery}%`)
)
);
}
if (typeFilter !== 'all') {
whereConditions = and(whereConditions, eq(transaction.type, typeFilter as 'BUY' | 'SELL'));
}
let sortColumn;
switch (sortBy) {
case 'totalBaseCurrencyAmount':
sortColumn = transaction.totalBaseCurrencyAmount;
break;
case 'quantity':
sortColumn = transaction.quantity;
break;
case 'pricePerCoin':
sortColumn = transaction.pricePerCoin;
break;
default:
sortColumn = transaction.timestamp;
}
const orderBy = sortOrder === 'asc' ? asc(sortColumn) : desc(sortColumn);
const [{ count }] = await db
.select({ count: sql<number>`count(*)` })
.from(transaction)
.leftJoin(coin, eq(transaction.coinId, coin.id))
.where(whereConditions);
const transactions = await db
.select({
@ -23,29 +68,31 @@ export async function GET({ request }) {
pricePerCoin: transaction.pricePerCoin,
totalBaseCurrencyAmount: transaction.totalBaseCurrencyAmount,
timestamp: transaction.timestamp,
coinSymbol: coin.symbol,
coinName: coin.name,
coinIcon: coin.icon
coin: {
id: coin.id,
name: coin.name,
symbol: coin.symbol,
icon: coin.icon
}
})
.from(transaction)
.innerJoin(coin, eq(transaction.coinId, coin.id))
.where(eq(transaction.userId, userId))
.orderBy(desc(transaction.timestamp))
.limit(100);
.leftJoin(coin, eq(transaction.coinId, coin.id))
.where(whereConditions)
.orderBy(orderBy)
.limit(limit)
.offset((page - 1) * limit);
const formattedTransactions = transactions.map(tx => ({
...tx,
quantity: Number(tx.quantity),
pricePerCoin: Number(tx.pricePerCoin),
totalBaseCurrencyAmount: Number(tx.totalBaseCurrencyAmount)
}));
return json({
transactions: transactions.map(t => ({
id: t.id,
type: t.type,
quantity: Number(t.quantity),
pricePerCoin: Number(t.pricePerCoin),
totalBaseCurrencyAmount: Number(t.totalBaseCurrencyAmount),
timestamp: t.timestamp,
coin: {
symbol: t.coinSymbol,
name: t.coinName,
icon: t.coinIcon
}
}))
transactions: formattedTransactions,
total: count,
page,
limit
});
}