Add routes for media outlets, articles, and prediction markets
Adds API endpoints for fetching articles by media outlet slug, prediction markets by article slug, and auction data for media outlets. Includes functionality to place bids on media outlet auctions. 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:
@ -55,6 +55,20 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get('/api/media-outlets/:slug/articles', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const outlet = await storage.getMediaOutletBySlug(req.params.slug);
|
||||||
|
if (!outlet) {
|
||||||
|
return res.status(404).json({ message: "Media outlet not found" });
|
||||||
|
}
|
||||||
|
const articles = await storage.getArticlesByOutlet(outlet.id);
|
||||||
|
res.json(articles);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching articles by slug:", error);
|
||||||
|
res.status(500).json({ message: "Failed to fetch articles" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.get('/api/articles/:slug', async (req, res) => {
|
app.get('/api/articles/:slug', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const article = await storage.getArticleBySlug(req.params.slug);
|
const article = await storage.getArticleBySlug(req.params.slug);
|
||||||
@ -68,6 +82,20 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get('/api/articles/:slug/markets', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const article = await storage.getArticleBySlug(req.params.slug);
|
||||||
|
if (!article) {
|
||||||
|
return res.status(404).json({ message: "Article not found" });
|
||||||
|
}
|
||||||
|
const markets = await storage.getPredictionMarkets(article.id);
|
||||||
|
res.json(markets);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching prediction markets for article:", error);
|
||||||
|
res.status(500).json({ message: "Failed to fetch prediction markets" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.get('/api/articles/featured', async (req, res) => {
|
app.get('/api/articles/featured', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const limit = parseInt(req.query.limit as string) || 10;
|
const limit = parseInt(req.query.limit as string) || 10;
|
||||||
@ -123,9 +151,26 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get('/api/media-outlets/:slug/auction', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const outlet = await storage.getMediaOutletBySlug(req.params.slug);
|
||||||
|
if (!outlet) {
|
||||||
|
return res.status(404).json({ message: "Media outlet not found" });
|
||||||
|
}
|
||||||
|
const auction = await storage.getAuctionByMediaOutlet(outlet.id);
|
||||||
|
if (!auction) {
|
||||||
|
return res.status(404).json({ message: "No active auction found for this media outlet" });
|
||||||
|
}
|
||||||
|
res.json(auction);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching auction:", error);
|
||||||
|
res.status(500).json({ message: "Failed to fetch auction" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.post('/api/auctions/:id/bid', isAuthenticated, async (req: any, res) => {
|
app.post('/api/auctions/:id/bid', isAuthenticated, async (req: any, res) => {
|
||||||
try {
|
try {
|
||||||
const userId = req.user.claims.sub;
|
const userId = req.user.id;
|
||||||
const bidData = insertBidSchema.parse({
|
const bidData = insertBidSchema.parse({
|
||||||
...req.body,
|
...req.body,
|
||||||
auctionId: req.params.id,
|
auctionId: req.params.id,
|
||||||
@ -140,6 +185,33 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post('/api/media-outlets/:slug/auction/bids', isAuthenticated, async (req: any, res) => {
|
||||||
|
try {
|
||||||
|
const outlet = await storage.getMediaOutletBySlug(req.params.slug);
|
||||||
|
if (!outlet) {
|
||||||
|
return res.status(404).json({ message: "Media outlet not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const auction = await storage.getAuctionByMediaOutlet(outlet.id);
|
||||||
|
if (!auction) {
|
||||||
|
return res.status(404).json({ message: "No active auction found for this media outlet" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = req.user.id;
|
||||||
|
const bidData = insertBidSchema.parse({
|
||||||
|
...req.body,
|
||||||
|
auctionId: auction.id,
|
||||||
|
bidderId: userId
|
||||||
|
});
|
||||||
|
|
||||||
|
const bid = await storage.placeBid(bidData);
|
||||||
|
res.status(201).json(bid);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error placing bid:", error);
|
||||||
|
res.status(500).json({ message: "Failed to place bid" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Media outlet request routes
|
// Media outlet request routes
|
||||||
app.get('/api/media-outlet-requests', isAuthenticated, async (req: any, res) => {
|
app.get('/api/media-outlet-requests', isAuthenticated, async (req: any, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -205,6 +205,30 @@ export class DatabaseStorage implements IStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async placeBid(bid: InsertBid): Promise<Bid> {
|
async placeBid(bid: InsertBid): Promise<Bid> {
|
||||||
|
// First, get the auction to validate
|
||||||
|
const auction = await this.getAuctionById(bid.auctionId);
|
||||||
|
if (!auction) {
|
||||||
|
throw new Error("Auction not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate auction status
|
||||||
|
if (!auction.isActive) {
|
||||||
|
throw new Error("Auction is not active");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate auction end date
|
||||||
|
if (new Date() > auction.endDate) {
|
||||||
|
throw new Error("Auction has ended");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate bid amount
|
||||||
|
const currentBidAmount = parseFloat(auction.currentBid || "0");
|
||||||
|
const bidAmount = parseFloat(bid.amount.toString());
|
||||||
|
|
||||||
|
if (bidAmount <= currentBidAmount) {
|
||||||
|
throw new Error(`Bid amount must be higher than current bid of ${currentBidAmount}`);
|
||||||
|
}
|
||||||
|
|
||||||
const [newBid] = await db.insert(bids).values(bid).returning();
|
const [newBid] = await db.insert(bids).values(bid).returning();
|
||||||
|
|
||||||
// Update auction with highest bid
|
// Update auction with highest bid
|
||||||
|
|||||||
Reference in New Issue
Block a user