feat: profile page + 404 page + refactor code

This commit is contained in:
Face 2025-05-25 18:44:06 +03:00
parent 3f137e5c3c
commit d692e86fe0
17 changed files with 1282 additions and 313 deletions

View file

@ -35,8 +35,6 @@ export async function GET({ params, request }) {
userName: user.name,
userUsername: user.username,
userImage: user.image,
userBio: user.bio,
userCreatedAt: user.createdAt,
isLikedByUser: session?.user ?
sql<boolean>`EXISTS(SELECT 1 FROM ${commentLike} WHERE ${commentLike.userId} = ${session.user.id} AND ${commentLike.commentId} = ${comment.id})` :
sql<boolean>`FALSE`
@ -109,8 +107,6 @@ export async function POST({ request, params }) {
userName: user.name,
userUsername: user.username,
userImage: user.image,
userBio: user.bio,
userCreatedAt: user.createdAt,
isLikedByUser: sql<boolean>`FALSE`
})
.from(comment)

View file

@ -0,0 +1,139 @@
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { user, coin, transaction, userPortfolio } from '$lib/server/db/schema';
import { eq, desc, sql, count, and, gte } from 'drizzle-orm';
export async function GET({ params }) {
const { userId } = params;
if (!userId) {
throw error(400, 'User ID or username is required');
}
try {
const isNumeric = /^\d+$/.test(userId);
const userProfile = await db.query.user.findFirst({
where: isNumeric ? eq(user.id, parseInt(userId)) : eq(user.username, userId),
columns: {
id: true,
name: true,
username: true,
bio: true,
image: true,
createdAt: true,
baseCurrencyBalance: true,
isAdmin: true,
}
});
if (!userProfile) {
throw error(404, 'User not found');
}
const actualUserId = userProfile.id;
// get created coins
const createdCoins = await db
.select({
id: coin.id,
name: coin.name,
symbol: coin.symbol,
icon: coin.icon,
currentPrice: coin.currentPrice,
marketCap: coin.marketCap,
volume24h: coin.volume24h,
change24h: coin.change24h,
createdAt: coin.createdAt,
})
.from(coin)
.where(eq(coin.creatorId, actualUserId))
.orderBy(desc(coin.createdAt))
.limit(10);
// get portfolio value and holdings count
const portfolioStats = await db
.select({
holdingsCount: count(),
totalValue: sql<number>`COALESCE(SUM(CAST(${userPortfolio.quantity} AS NUMERIC) * CAST(${coin.currentPrice} AS NUMERIC)), 0)`
})
.from(userPortfolio)
.innerJoin(coin, eq(userPortfolio.coinId, coin.id))
.where(eq(userPortfolio.userId, actualUserId));
// get recent transactions
const recentTransactions = await db
.select({
id: transaction.id,
type: transaction.type,
coinSymbol: coin.symbol,
coinName: coin.name,
coinIcon: coin.icon,
quantity: transaction.quantity,
pricePerCoin: transaction.pricePerCoin,
totalBaseCurrencyAmount: transaction.totalBaseCurrencyAmount,
timestamp: transaction.timestamp,
})
.from(transaction)
.innerJoin(coin, eq(transaction.coinId, coin.id))
.where(eq(transaction.userId, actualUserId))
.orderBy(desc(transaction.timestamp))
.limit(10);
// calc total portfolio value
const baseCurrencyBalance = parseFloat(userProfile.baseCurrencyBalance);
const holdingsValue = portfolioStats[0]?.totalValue || 0;
const totalPortfolioValue = baseCurrencyBalance + holdingsValue;
// get all transaction statistics
const transactionStats = await db
.select({
totalTransactions: count(),
totalBuyVolume: sql<number>`COALESCE(SUM(CASE WHEN ${transaction.type} = 'BUY' THEN CAST(${transaction.totalBaseCurrencyAmount} AS NUMERIC) ELSE 0 END), 0)`,
totalSellVolume: sql<number>`COALESCE(SUM(CASE WHEN ${transaction.type} = 'SELL' THEN CAST(${transaction.totalBaseCurrencyAmount} AS NUMERIC) ELSE 0 END), 0)`
})
.from(transaction)
.where(eq(transaction.userId, actualUserId));
const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
const transactionStats24h = await db
.select({
transactions24h: count(),
buyVolume24h: sql<number>`COALESCE(SUM(CASE WHEN ${transaction.type} = 'BUY' THEN CAST(${transaction.totalBaseCurrencyAmount} AS NUMERIC) ELSE 0 END), 0)`,
sellVolume24h: sql<number>`COALESCE(SUM(CASE WHEN ${transaction.type} = 'SELL' THEN CAST(${transaction.totalBaseCurrencyAmount} AS NUMERIC) ELSE 0 END), 0)`
})
.from(transaction)
.where(
and(
eq(transaction.userId, actualUserId),
gte(transaction.timestamp, twentyFourHoursAgo)
)
);
return json({
profile: {
...userProfile,
baseCurrencyBalance,
totalPortfolioValue,
},
stats: {
totalPortfolioValue,
baseCurrencyBalance,
holdingsValue,
holdingsCount: portfolioStats[0]?.holdingsCount || 0,
coinsCreated: createdCoins.length,
totalTransactions: transactionStats[0]?.totalTransactions || 0,
totalBuyVolume: transactionStats[0]?.totalBuyVolume || 0,
totalSellVolume: transactionStats[0]?.totalSellVolume || 0,
transactions24h: transactionStats24h[0]?.transactions24h || 0,
buyVolume24h: transactionStats24h[0]?.buyVolume24h || 0,
sellVolume24h: transactionStats24h[0]?.sellVolume24h || 0,
},
createdCoins,
recentTransactions
});
} catch (e) {
console.error('Failed to fetch user profile:', e);
throw error(500, 'Failed to fetch user profile');
}
}