From 10d2fd70263bc2128a3850dc909d89db55050e0d Mon Sep 17 00:00:00 2001 From: kimjaehyeon0101 <47347352-kimjaehyeon0101@users.noreply.replit.com> Date: Mon, 29 Sep 2025 19:23:17 +0000 Subject: [PATCH] Display bid history for media outlet auctions and fetch bid data Add a new API endpoint and integrate bid history display into the media outlet auction page. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 069d4324-6c40-4355-955e-c714a50de1ea Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/069d4324-6c40-4355-955e-c714a50de1ea/6XTzcDL --- client/src/pages/MediaOutletAuction.tsx | 88 +++++++++++++++++++++++++ server/routes.ts | 10 +++ server/storage.ts | 9 +++ 3 files changed, 107 insertions(+) diff --git a/client/src/pages/MediaOutletAuction.tsx b/client/src/pages/MediaOutletAuction.tsx index f9249b4..405a45f 100644 --- a/client/src/pages/MediaOutletAuction.tsx +++ b/client/src/pages/MediaOutletAuction.tsx @@ -30,6 +30,11 @@ export default function MediaOutletAuction() { enabled: !!params?.slug }); + const { data: bids = [], isLoading: bidsLoading } = useQuery({ + queryKey: ["/api/auctions", auction?.id, "bids"], + enabled: !!auction?.id + }); + const placeBidMutation = useMutation({ mutationFn: async (bidData: { amount: number; qualityScore?: number }) => { return apiRequest("POST", `/api/media-outlets/${params?.slug}/auction/bids`, bidData); @@ -42,6 +47,7 @@ export default function MediaOutletAuction() { setBidAmount(""); setQualityScore(""); queryClient.invalidateQueries({ queryKey: ["/api/media-outlets", params?.slug, "auction"] }); + queryClient.invalidateQueries({ queryKey: ["/api/auctions", auction?.id, "bids"] }); }, onError: (error: any) => { toast({ @@ -363,6 +369,88 @@ export default function MediaOutletAuction() { + {/* Bid History */} + + + + + 입찰 내역 + {bids.length}건 + + + + {bidsLoading ? ( +
+ {Array.from({ length: 5 }).map((_, i) => ( +
+
+
+
+ ))} +
+ ) : bids.length > 0 ? ( +
+ {(() => { + // Sort bids by time (newest first) + const sortedBids = [...bids].sort((a, b) => + new Date(b.createdAt!).getTime() - new Date(a.createdAt!).getTime() + ); + + // Find highest bid by amount + const highestBid = bids.reduce((highest, current) => + parseFloat(current.amount) > parseFloat(highest.amount) ? current : highest + , bids[0]); + + return sortedBids.map((bid, index) => ( +
+
+
+
+ + {formatCurrency(parseFloat(bid.amount))} + + {bid.id === highestBid.id && ( + 최고가 + )} +
+
+ 입찰자: {bid.bidderId.slice(0, 8)}*** + {bid.qualityScore !== undefined && bid.qualityScore !== null && ( + 품질점수: {bid.qualityScore} + )} +
+
+
+
+ + {new Date(bid.createdAt!).toLocaleDateString('ko-KR', { + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + })} + +
+
+ )); + })()} +
+ ) : ( +
+ +

아직 입찰 내역이 없습니다

+

첫 번째 입찰자가 되어보세요!

+
+ )} +
+
+ {/* Auction Description */} diff --git a/server/routes.ts b/server/routes.ts index c81e1aa..3368aa8 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -168,6 +168,16 @@ export async function registerRoutes(app: Express): Promise { } }); + app.get('/api/auctions/:id/bids', async (req, res) => { + try { + const bids = await storage.getBidsByAuctionId(req.params.id); + res.json(bids); + } catch (error) { + console.error("Error fetching bids:", error); + res.status(500).json({ message: "Failed to fetch bids" }); + } + }); + app.post('/api/auctions/:id/bid', isAuthenticated, async (req: any, res) => { try { const userId = req.user.claims.sub; diff --git a/server/storage.ts b/server/storage.ts index 5fe6834..d81e4a3 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -59,6 +59,7 @@ export interface IStorage { getAuctionByMediaOutlet(mediaOutletId: string): Promise; createAuction(auction: InsertAuction): Promise; placeBid(bid: InsertBid): Promise; + getBidsByAuctionId(auctionId: string): Promise; // Media outlet request operations getMediaOutletRequests(status?: string): Promise; @@ -251,6 +252,14 @@ export class DatabaseStorage implements IStorage { return newBid; } + + async getBidsByAuctionId(auctionId: string): Promise { + return await db + .select() + .from(bids) + .where(eq(bids.auctionId, auctionId)) + .orderBy(desc(bids.createdAt)); + } // Media outlet request operations async getMediaOutletRequests(status?: string): Promise {