Files
sapiens-web3/shared/schema.ts
kimjaehyeon0101 8e4d12d99e Add profile image enlargement and refine article display
Implement image enlargement for profile pictures, add relative time display for articles using "X min ago", and ensure articles are sorted by publication date.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 0fb68265-c270-4198-9584-3d9be9bddb41
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/0fb68265-c270-4198-9584-3d9be9bddb41/rOJiPGe
2025-09-30 04:33:42 +00:00

227 lines
8.1 KiB
TypeScript

import { sql } from 'drizzle-orm';
import {
index,
jsonb,
pgTable,
timestamp,
varchar,
text,
integer,
boolean,
decimal,
} from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";
// Session storage table.
// (IMPORTANT) This table is mandatory for Replit Auth, don't drop it.
export const sessions = pgTable(
"sessions",
{
sid: varchar("sid").primaryKey(),
sess: jsonb("sess").notNull(),
expire: timestamp("expire").notNull(),
},
(table) => [index("IDX_session_expire").on(table.expire)],
);
// User storage table.
// (IMPORTANT) This table is mandatory for Replit Auth, don't drop it.
export const users = pgTable("users", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
email: varchar("email").unique(),
firstName: varchar("first_name"),
lastName: varchar("last_name"),
profileImageUrl: varchar("profile_image_url"),
role: varchar("role").default("user"), // user, admin, superadmin
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Media outlets (People, Topics, Companies)
export const mediaOutlets = pgTable("media_outlets", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
name: varchar("name").notNull(),
slug: varchar("slug").notNull().unique(),
category: varchar("category").notNull(), // people, topics, companies
description: text("description"),
imageUrl: varchar("image_url"),
tags: text("tags").array(),
trafficScore: integer("traffic_score").default(0), // For sorting by traffic
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Articles within media outlets
export const articles = pgTable("articles", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
mediaOutletId: varchar("media_outlet_id").notNull(),
title: varchar("title").notNull(),
slug: varchar("slug").notNull(),
excerpt: text("excerpt"),
content: text("content").notNull(),
imageUrl: varchar("image_url"),
authorId: varchar("author_id"),
tags: text("tags").array(),
isPinned: boolean("is_pinned").default(false),
isFeatured: boolean("is_featured").default(false),
publishedMinutesAgo: integer("published_minutes_ago").notNull().default(sql`1 + floor(random() * 59)::int`),
publishedAt: timestamp("published_at").defaultNow(),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Prediction markets
export const predictionMarkets = pgTable("prediction_markets", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
question: varchar("question"),
title: varchar("title").notNull(),
description: text("description"),
articleId: varchar("article_id"),
yesPrice: decimal("yes_price", { precision: 5, scale: 4 }).default("0.5"),
noPrice: decimal("no_price", { precision: 5, scale: 4 }).default("0.5"),
totalVolume: decimal("total_volume", { precision: 12, scale: 2 }).default("0"),
totalBets: integer("total_bets").default(0),
resolutionDate: timestamp("resolution_date"),
volume: decimal("volume", { precision: 12, scale: 2 }),
endDate: timestamp("end_date"),
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Auctions for media outlet management rights
export const auctions = pgTable("auctions", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
mediaOutletId: varchar("media_outlet_id").notNull(),
title: varchar("title").notNull(),
description: text("description"),
currentBid: decimal("current_bid", { precision: 10, scale: 2 }),
qualityScore: integer("quality_score"),
highestBidderId: varchar("highest_bidder_id"),
endDate: timestamp("end_date").notNull(),
duration: integer("duration"), // days
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Bids for auctions
export const bids = pgTable("bids", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
auctionId: varchar("auction_id").notNull(),
bidderId: varchar("bidder_id").notNull(),
amount: decimal("amount", { precision: 10, scale: 2 }).notNull(),
qualityScore: integer("quality_score"),
createdAt: timestamp("created_at").defaultNow(),
});
// Media outlet creation requests
export const mediaOutletRequests = pgTable("media_outlet_requests", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
name: varchar("name").notNull(),
category: varchar("category").notNull(),
description: text("description"),
requesterId: varchar("requester_id").notNull(),
status: varchar("status").default("pending"), // pending, approved, rejected
reviewedBy: varchar("reviewed_by"),
reviewedAt: timestamp("reviewed_at"),
createdAt: timestamp("created_at").defaultNow(),
});
// Comments on articles
export const comments = pgTable("comments", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
articleId: varchar("article_id").notNull(),
authorId: varchar("author_id").notNull(),
content: text("content").notNull(),
isPinned: boolean("is_pinned").default(false),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Prediction market bets
export const predictionBets = pgTable("prediction_bets", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
marketId: varchar("market_id").notNull(),
userId: varchar("user_id").notNull(),
side: varchar("side", { enum: ["yes", "no"] }).notNull(),
amount: decimal("amount", { precision: 12, scale: 2 }).notNull(),
price: decimal("price", { precision: 5, scale: 4 }).notNull(), // Price at time of bet
createdAt: timestamp("created_at").defaultNow(),
});
// Insert schemas
export const insertUserSchema = createInsertSchema(users).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertMediaOutletSchema = createInsertSchema(mediaOutlets).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertArticleSchema = createInsertSchema(articles).omit({
id: true,
publishedMinutesAgo: true,
createdAt: true,
updatedAt: true,
});
export const insertPredictionMarketSchema = createInsertSchema(predictionMarkets).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertAuctionSchema = createInsertSchema(auctions).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertBidSchema = createInsertSchema(bids).omit({
id: true,
createdAt: true,
});
export const insertMediaOutletRequestSchema = createInsertSchema(mediaOutletRequests).omit({
id: true,
createdAt: true,
});
export const insertCommentSchema = createInsertSchema(comments).omit({
id: true,
createdAt: true,
updatedAt: true,
});
export const insertPredictionBetSchema = createInsertSchema(predictionBets).omit({
id: true,
createdAt: true,
});
// Types
export type UpsertUser = typeof users.$inferInsert;
export type User = typeof users.$inferSelect;
export type InsertMediaOutlet = z.infer<typeof insertMediaOutletSchema>;
export type MediaOutlet = typeof mediaOutlets.$inferSelect;
export type InsertArticle = z.infer<typeof insertArticleSchema>;
export type Article = typeof articles.$inferSelect;
export type InsertPredictionMarket = z.infer<typeof insertPredictionMarketSchema>;
export type PredictionMarket = typeof predictionMarkets.$inferSelect;
export type InsertAuction = z.infer<typeof insertAuctionSchema>;
export type Auction = typeof auctions.$inferSelect;
export type InsertBid = z.infer<typeof insertBidSchema>;
export type Bid = typeof bids.$inferSelect;
export type InsertMediaOutletRequest = z.infer<typeof insertMediaOutletRequestSchema>;
export type MediaOutletRequest = typeof mediaOutletRequests.$inferSelect;
export type InsertComment = z.infer<typeof insertCommentSchema>;
export type Comment = typeof comments.$inferSelect;
export type InsertPredictionBet = z.infer<typeof insertPredictionBetSchema>;
export type PredictionBet = typeof predictionBets.$inferSelect;