diff --git a/src/app/page.tsx b/src/app/page.tsx index 1733b41..b1fa23f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -183,6 +183,12 @@ export default async function HomePage() {

Your top positions + + View all → +

{holdings.biggestGain && ( diff --git a/src/app/profile/[username]/page.tsx b/src/app/profile/[username]/page.tsx index 71bd680..eeca647 100644 --- a/src/app/profile/[username]/page.tsx +++ b/src/app/profile/[username]/page.tsx @@ -187,6 +187,37 @@ export default async function ProfilePage({ params }: Props) {
)} + {/* Funds managed — only shown to the profile owner */} + {isOwn && user.managedFunds.length > 0 && ( +
+

+ + Funds you manage +

+
+
+ {user.managedFunds.map(({ fund }) => ( +
+ + + {fund.name} + + + Trade as this fund → + +
+ ))} +
+
+
+ )} + {/* Positions */} {user.positions.length > 0 && (
@@ -240,37 +271,6 @@ export default async function ProfilePage({ params }: Props) {
)} - {/* Funds managed — only shown to the profile owner */} - {isOwn && user.managedFunds.length > 0 && ( -
-

- - Funds you manage -

-
-
- {user.managedFunds.map(({ fund }) => ( -
- - - {fund.name} - - - Trade as this fund → - -
- ))} -
-
-
- )} - {/* Trade history */} {user.trades.length > 0 && (
diff --git a/src/app/trades/page.tsx b/src/app/trades/page.tsx index d10249e..150fed2 100644 --- a/src/app/trades/page.tsx +++ b/src/app/trades/page.tsx @@ -15,15 +15,23 @@ interface PageProps { export default async function GlobalTradesPage({ searchParams }: PageProps) { const page = Math.max(1, parseInt(searchParams.page ?? '1', 10)) + const tradeWhere = { + OR: [ + { hashtagId: { not: null }, type: { not: 'LOTTERY_WIN' } }, + { type: { in: ['FUND_INVEST', 'FUND_REDEEM'] } }, + ], + } as const + const [total, trades] = await Promise.all([ - prisma.trade.count({ where: { hashtagId: { not: null }, type: { not: 'LOTTERY_WIN' } } }), + prisma.trade.count({ where: tradeWhere }), prisma.trade.findMany({ - where: { hashtagId: { not: null }, type: { not: 'LOTTERY_WIN' } }, + where: tradeWhere, orderBy: { createdAt: 'desc' }, take: PAGE_SIZE, skip: (page - 1) * PAGE_SIZE, include: { hashtag: { select: { tag: true, displayTag: true } }, + fund: { select: { name: true, slug: true } }, user: { select: { username: true, displayUsername: true, isFund: true } }, }, }), @@ -49,19 +57,34 @@ export default async function GlobalTradesPage({ searchParams }: PageProps) { className={`text-xs font-medium px-2 py-0.5 rounded shrink-0 ${ (t.type === 'LIQUIDATE_LONG' || t.type === 'LIQUIDATE_SHORT') ? 'bg-orange-500/15 text-orange-400' - : t.type.startsWith('BUY') - ? 'bg-emerald-500/15 text-emerald-400' - : 'bg-red-500/15 text-red-400' + : (t.type === 'FUND_INVEST' || t.type === 'FUND_REDEEM') + ? 'bg-indigo-500/15 text-indigo-400' + : t.type.startsWith('BUY') + ? 'bg-emerald-500/15 text-emerald-400' + : 'bg-red-500/15 text-red-400' }`} > - {(t.type === 'LIQUIDATE_LONG' || t.type === 'LIQUIDATE_SHORT') ? 'LIQUIDATED' : t.type.replace('_', ' ')} + {(t.type === 'LIQUIDATE_LONG' || t.type === 'LIQUIDATE_SHORT') ? 'LIQUIDATED' : t.type.replace(/_/g, ' ')} - - #{t.hashtag!.displayTag} - + {(t.type === 'FUND_INVEST' || t.type === 'FUND_REDEEM') ? ( + t.fund ? ( + + {t.fund.name} + + ) : ( + Deleted Fund + ) + ) : ( + + #{t.hashtag!.displayTag} + + )} {formatCurrency(t.total)} {/* Secondary row: user · time (left) shares @ price (right) */} @@ -79,8 +102,8 @@ export default async function GlobalTradesPage({ searchParams }: PageProps) { {formatNumber(t.shares)} sh @ {formatCurrency(t.price)} - {/* PnL: sell and liquidation trades */} - {(t.type === 'SELL_LONG' || t.type === 'SELL_SHORT' || t.type === 'LIQUIDATE_LONG' || t.type === 'LIQUIDATE_SHORT') && ( + {/* PnL: sell, liquidation, and fund redeem trades */} + {(t.type === 'SELL_LONG' || t.type === 'SELL_SHORT' || t.type === 'LIQUIDATE_LONG' || t.type === 'LIQUIDATE_SHORT' || t.type === 'FUND_REDEEM') && (
{formatPnl(t.profit)}
)}