Enhance the media auction system with improved bid validation and data handling
Update the MediaOutletAuction component to correctly parse currency values for bid placement and display, and modify the DatabaseStorage to include a new method for fetching active auctions by media outlet ID. 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/jvFIdY3
This commit is contained in:
@ -32,10 +32,7 @@ export default function MediaOutletAuction() {
|
|||||||
|
|
||||||
const placeBidMutation = useMutation({
|
const placeBidMutation = useMutation({
|
||||||
mutationFn: async (bidData: { amount: number; qualityScore?: number }) => {
|
mutationFn: async (bidData: { amount: number; qualityScore?: number }) => {
|
||||||
return apiRequest(`/api/media-outlets/${params?.slug}/auction/bids`, {
|
return apiRequest("POST", `/api/media-outlets/${params?.slug}/auction/bids`, bidData);
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify(bidData),
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast({
|
toast({
|
||||||
@ -75,7 +72,7 @@ export default function MediaOutletAuction() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auction && amount <= auction.currentBid) {
|
if (auction && auction.currentBid && amount <= parseFloat(auction.currentBid)) {
|
||||||
toast({
|
toast({
|
||||||
title: "입찰 금액 부족",
|
title: "입찰 금액 부족",
|
||||||
description: `현재 최고 입찰가(${auction.currentBid}원)보다 높은 금액을 입력해주세요.`,
|
description: `현재 최고 입찰가(${auction.currentBid}원)보다 높은 금액을 입력해주세요.`,
|
||||||
@ -102,7 +99,7 @@ export default function MediaOutletAuction() {
|
|||||||
}).format(amount);
|
}).format(amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatTimeRemaining = (endDate: string) => {
|
const formatTimeRemaining = (endDate: Date | string) => {
|
||||||
const end = new Date(endDate);
|
const end = new Date(endDate);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const diff = end.getTime() - now.getTime();
|
const diff = end.getTime() - now.getTime();
|
||||||
@ -264,7 +261,7 @@ export default function MediaOutletAuction() {
|
|||||||
<span className="font-medium">현재 최고가</span>
|
<span className="font-medium">현재 최고가</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-2xl font-bold text-green-600">
|
<span className="text-2xl font-bold text-green-600">
|
||||||
{formatCurrency(auction.currentBid)}
|
{formatCurrency(parseFloat(auction.currentBid || "0"))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -278,14 +275,14 @@ export default function MediaOutletAuction() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{auction.highestBidder && (
|
{auction.highestBidderId && (
|
||||||
<div className="flex items-center justify-between p-4 bg-muted rounded-lg">
|
<div className="flex items-center justify-between p-4 bg-muted rounded-lg">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<User className="h-4 w-4 text-blue-600" />
|
<User className="h-4 w-4 text-blue-600" />
|
||||||
<span className="font-medium">최고 입찰자</span>
|
<span className="font-medium">최고 입찰자</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-lg font-bold text-blue-600">
|
<span className="text-lg font-bold text-blue-600">
|
||||||
{auction.highestBidder.slice(0, 3)}***
|
{auction.highestBidderId.slice(0, 3)}***
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -328,8 +325,8 @@ export default function MediaOutletAuction() {
|
|||||||
type="number"
|
type="number"
|
||||||
value={bidAmount}
|
value={bidAmount}
|
||||||
onChange={(e) => setBidAmount(e.target.value)}
|
onChange={(e) => setBidAmount(e.target.value)}
|
||||||
placeholder={`${auction.currentBid + 1000} 이상`}
|
placeholder={`${parseFloat(auction.currentBid || "0") + 1000} 이상`}
|
||||||
min={auction.currentBid + 1}
|
min={parseFloat(auction.currentBid || "0") + 1}
|
||||||
data-testid="input-bid-amount"
|
data-testid="input-bid-amount"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -53,6 +53,7 @@ export interface IStorage {
|
|||||||
// Auction operations
|
// Auction operations
|
||||||
getActiveAuctions(): Promise<Auction[]>;
|
getActiveAuctions(): Promise<Auction[]>;
|
||||||
getAuctionById(id: string): Promise<Auction | undefined>;
|
getAuctionById(id: string): Promise<Auction | undefined>;
|
||||||
|
getAuctionByMediaOutlet(mediaOutletId: string): Promise<Auction | undefined>;
|
||||||
createAuction(auction: InsertAuction): Promise<Auction>;
|
createAuction(auction: InsertAuction): Promise<Auction>;
|
||||||
placeBid(bid: InsertBid): Promise<Bid>;
|
placeBid(bid: InsertBid): Promise<Bid>;
|
||||||
|
|
||||||
@ -191,6 +192,13 @@ export class DatabaseStorage implements IStorage {
|
|||||||
return auction;
|
return auction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAuctionByMediaOutlet(mediaOutletId: string): Promise<Auction | undefined> {
|
||||||
|
const [auction] = await db.select().from(auctions).where(
|
||||||
|
and(eq(auctions.mediaOutletId, mediaOutletId), eq(auctions.isActive, true))
|
||||||
|
);
|
||||||
|
return auction;
|
||||||
|
}
|
||||||
|
|
||||||
async createAuction(auction: InsertAuction): Promise<Auction> {
|
async createAuction(auction: InsertAuction): Promise<Auction> {
|
||||||
const [newAuction] = await db.insert(auctions).values(auction).returning();
|
const [newAuction] = await db.insert(auctions).values(auction).returning();
|
||||||
return newAuction;
|
return newAuction;
|
||||||
|
|||||||
Reference in New Issue
Block a user