feat: implement market page with QueryProvider and dynamic listings
- wrap root layout with QueryProvider for React Query - replace market UnderConstruction placeholder with MarketClient and real data fetching - implement search, pagination, and sort via search params using getActiveListings - add necessary client components and queries - update dependencies (e.g., prisma, pkg-types)
This commit is contained in:
1 parent
55eebde0ba
commit
ab37b477df
106 files changed
+15261
-301
No files matched your search
@@ -0,0 +1,319 @@
|
||||
// Prisma Schema para PostgreSQL (Banco Principal da Aplicação)
|
||||
// URL: DATABASE_URL_APP
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL_APP")
|
||||
}
|
||||
|
||||
model User {
|
||||
user_id Int @id @default(autoincrement())
|
||||
username String @unique @db.VarChar(50)
|
||||
email String @unique @db.VarChar(255)
|
||||
password_hash String @db.VarChar(255)
|
||||
first_name String @db.VarChar(100)
|
||||
last_name String @db.VarChar(100)
|
||||
phone String? @db.VarChar(20)
|
||||
cpf String? @unique @db.VarChar(14)
|
||||
account_level String @default("free") @db.VarChar(20)
|
||||
has_donated Boolean @default(false)
|
||||
whatsapp_notifications Boolean @default(true)
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
last_login DateTime?
|
||||
is_active Boolean @default(true)
|
||||
is_verified Boolean @default(false)
|
||||
|
||||
characters UserCharacter[]
|
||||
listings Listing[]
|
||||
bids Bid[]
|
||||
transactions_as_buyer Transaction[] @relation("Buyer")
|
||||
transactions_as_seller Transaction[] @relation("Seller")
|
||||
notifications Notification[]
|
||||
inventory UserInventory[]
|
||||
favorites UserFavorite[]
|
||||
telemetry_events TelemetryEvent[]
|
||||
purchaseIntentions PurchaseIntention[]
|
||||
|
||||
item Item? @relation("ListingItem", fields: [item_id_unified], references: [item_id], onDelete: SetNull)
|
||||
tradeItem Item? @relation("TradeItem", fields: [trade_item_id_unified], references: [item_id], onDelete: SetNull) @relation("BuyerIntentions")
|
||||
|
||||
@@index([email])
|
||||
@@index([username])
|
||||
@@index([cpf])
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model UserCharacter {
|
||||
character_id Int @id @default(autoincrement())
|
||||
user_id Int
|
||||
character_name String @db.VarChar(100)
|
||||
server_name String @db.VarChar(50)
|
||||
is_main Boolean @default(false)
|
||||
verified Boolean @default(false)
|
||||
created_at DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [user_id], references: [user_id], onDelete: Cascade)
|
||||
|
||||
@@unique([character_name, server_name])
|
||||
@@index([user_id])
|
||||
@@map("user_characters")
|
||||
}
|
||||
|
||||
model Server {
|
||||
server_id Int @id @default(autoincrement())
|
||||
server_name String @unique @db.VarChar(50)
|
||||
server_type String? @db.VarChar(20)
|
||||
location String? @db.VarChar(10)
|
||||
is_active Boolean @default(true)
|
||||
total_listings Int @default(0)
|
||||
total_users Int @default(0)
|
||||
total_subscribers Int @default(0)
|
||||
total_transactions Int @default(0)
|
||||
total_volume Decimal @default(0) @db.Decimal(15, 2)
|
||||
average_listing_price Decimal? @db.Decimal(10, 2)
|
||||
last_activity_at DateTime?
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
@@index([server_name])
|
||||
@@index([is_active])
|
||||
@@index([server_type])
|
||||
@@map("servers")
|
||||
}
|
||||
|
||||
model Item {
|
||||
item_id Int @id @default(autoincrement())
|
||||
source_table_id Int
|
||||
source_table_name String @db.VarChar(50)
|
||||
item_name String @db.VarChar(255)
|
||||
category String @db.VarChar(50)
|
||||
image_local_path String? @db.Text
|
||||
image_url String? @db.Text
|
||||
rarity String? @db.VarChar(20)
|
||||
level Int?
|
||||
weight Decimal? @db.Decimal(10, 2)
|
||||
slots Int?
|
||||
skill String? @db.VarChar(50)
|
||||
metadata Json? @default("{}")
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @default(now()) @updatedAt
|
||||
|
||||
listings Listing[] @relation("ListingItem")
|
||||
tradeListings Listing[] @relation("TradeItem")
|
||||
|
||||
@@unique([source_table_name, source_table_id])
|
||||
@@index([item_name])
|
||||
@@index([category])
|
||||
@@index([rarity])
|
||||
@@map("items")
|
||||
}
|
||||
|
||||
model Listing {
|
||||
listing_id Int @id @default(autoincrement())
|
||||
seller_id Int
|
||||
item_id Int // Legacy - manter para compatibilidade
|
||||
item_id_unified Int? // Nova referência para tabela items
|
||||
item_name String @db.VarChar(255)
|
||||
quantity Int @default(1) Int?
|
||||
min_bid_increment Decimal? @db.Decimal(10, 2)
|
||||
initial_price_pix Decimal? @db.Decimal(10, 2)
|
||||
initial_price_tibia_coins Int?
|
||||
initial_price_gold_coins BigInt?
|
||||
|
||||
seller User @relation(fields: [seller_id], references: [user_id], onDelete: Cascade)
|
||||
bids Bid[]
|
||||
transactions Transaction[]
|
||||
analytics AdAnalytics?
|
||||
telemetry_events TelemetryEvent[]
|
||||
favorites UserFavorite[]
|
||||
purchaseIntentions PurchaseIntention[]
|
||||
|
||||
item Item? @relation("ListingItem", fields: [item_id_unified], references: [item_id], onDelete: SetNull)
|
||||
tradeItem Item? @relation("TradeItem", fields: [trade_item_id_unified], references: [item_id], onDelete: SetNull)
|
||||
|
||||
@@index([listing_status])
|
||||
@@index([item_id])
|
||||
@@index([seller_id])
|
||||
@@index([server_name])
|
||||
@@index([created_at(sort: Desc)])
|
||||
@@index([is_auction, auction_ends_at])
|
||||
@@index([is_featured])
|
||||
@@index([expires_at])
|
||||
@@index([favorites_count(sort: Desc)])
|
||||
@@map("listings")
|
||||
}
|
||||
|
||||
model Bid {
|
||||
bid_id Int @id @default(autoincrement())
|
||||
listing_id Int
|
||||
bidder_id Int
|
||||
bid_amount Decimal @db.Decimal(10, 2)
|
||||
bid_type String? @db.VarChar(20)
|
||||
created_at DateTime @default(now())
|
||||
is_active Boolean @default(true)
|
||||
|
||||
listing Listing @relation(fields: [listing_id], references: [listing_id], onDelete: Cascade)
|
||||
bidder User @relation(fields: [bidder_id], references: [user_id], onDelete: Cascade)
|
||||
|
||||
@@index([listing_id])
|
||||
@@index([bidder_id])
|
||||
@@index([is_active])
|
||||
@@index([listing_id, bid_amount(sort: Desc)])
|
||||
@@map("bids")
|
||||
}
|
||||
|
||||
model Transaction {
|
||||
transaction_id Int @id @default(autoincrement())
|
||||
listing_id Int?
|
||||
buyer_id Int
|
||||
seller_id Int
|
||||
item_name String @db.VarChar(255)
|
||||
quantity Int
|
||||
server_name String @db.VarChar(50)
|
||||
amount Decimal @db.Decimal(10, 2)
|
||||
payment_method String? @db.VarChar(20)
|
||||
escrow_fee Decimal? @db.Decimal(10, 2)
|
||||
transaction_status String @default("pending") @db.VarChar(30)
|
||||
created_at DateTime @default(now())
|
||||
deposited_at DateTime?
|
||||
delivered_at DateTime?
|
||||
completed_at DateTime?
|
||||
buyer_confirmed Boolean @default(false)
|
||||
seller_confirmed Boolean @default(false)
|
||||
buyer_notes String? @db.Text
|
||||
seller_notes String? @db.Text
|
||||
|
||||
listing Listing? @relation(fields: [listing_id], references: [listing_id])
|
||||
buyer User @relation("Buyer", fields: [buyer_id], references: [user_id])
|
||||
seller User @relation("Seller", fields: [seller_id], references: [user_id])
|
||||
|
||||
@@index([buyer_id])
|
||||
@@index([seller_id])
|
||||
@@index([transaction_status])
|
||||
@@index([listing_id])
|
||||
@@index([created_at(sort: Desc)])
|
||||
@@map("transactions")
|
||||
}
|
||||
|
||||
model Notification {
|
||||
notification_id Int @id @default(autoincrement())
|
||||
user_id Int
|
||||
notification_type String @db.VarChar(30)
|
||||
title String @db.VarChar(255)
|
||||
message String @db.Text
|
||||
related_id Int?
|
||||
is_read Boolean @default(false)
|
||||
send_whatsapp Boolean @default(false)
|
||||
whatsapp_sent Boolean @default(false)
|
||||
created_at DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [user_id], references: [user_id], onDelete: Cascade)
|
||||
|
||||
@@index([user_id, is_read])
|
||||
@@index([notification_type])
|
||||
@@index([created_at(sort: Desc)])
|
||||
@@map("notifications")
|
||||
}
|
||||
|
||||
model TelemetryEvent {
|
||||
event_id Int @id @default(autoincrement())
|
||||
event_type String @db.VarChar(50)
|
||||
ad_id Int?
|
||||
user_id Int?
|
||||
session_id String? @db.VarChar(255)
|
||||
metadata Json? @default("{}")
|
||||
timestamp DateTime @default(now())
|
||||
|
||||
listing Listing? @relation(fields: [ad_id], references: [listing_id], onDelete: Cascade)
|
||||
user User? @relation(fields: [user_id], references: [user_id], onDelete: SetNull)
|
||||
|
||||
@@index([ad_id])
|
||||
@@index([user_id])
|
||||
@@index([timestamp(sort: Desc)])
|
||||
@@index([event_type])
|
||||
@@index([session_id])
|
||||
@@index([ad_id, event_type, timestamp(sort: Desc)])
|
||||
@@map("telemetry_events")
|
||||
}
|
||||
|
||||
model AdAnalytics {
|
||||
ad_id Int @id
|
||||
impressions Int @default(0)
|
||||
clicks Int @default(0)
|
||||
ctr Decimal @default(0) @db.Decimal(5, 2)
|
||||
avg_view_duration Decimal @default(0) @db.Decimal(10, 2)
|
||||
bounce_rate Decimal @default(0) @db.Decimal(5, 2)
|
||||
inquiries Int @default(0)
|
||||
favorites Int @default(0)
|
||||
conversion_rate Decimal @default(0) @db.Decimal(5, 2)
|
||||
time_to_sell Int?
|
||||
last_updated DateTime @default(now()) @updatedAt
|
||||
|
||||
listing Listing @relation(fields: [ad_id], references: [listing_id], onDelete: Cascade)
|
||||
|
||||
@@map("ad_analytics")
|
||||
}
|
||||
|
||||
model UserInventory {
|
||||
inventory_id Int @id @default(autoincrement())
|
||||
user_id Int
|
||||
item_id Int
|
||||
item_name String @db.VarChar(255)
|
||||
quantity Int @default(1)
|
||||
acquired_at DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [user_id], references: [user_id], onDelete: Cascade)
|
||||
|
||||
@@unique([user_id, item_id])
|
||||
@@index([user_id])
|
||||
@@index([item_id])
|
||||
@@map("user_inventory")
|
||||
}
|
||||
|
||||
model UserFavorite {
|
||||
user_id Int
|
||||
ad_id Int
|
||||
created_at DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [user_id], references: [user_id], onDelete: Cascade)
|
||||
listing Listing @relation(fields: [ad_id], references: [listing_id], onDelete: Cascade)
|
||||
|
||||
@@id([user_id, ad_id])
|
||||
@@index([user_id])
|
||||
@@index([ad_id])
|
||||
@@map("user_favorites")
|
||||
}
|
||||
|
||||
model PurchaseIntention {
|
||||
intention_id Int @id @default(autoincrement())
|
||||
listing_id Int
|
||||
buyer_id Int
|
||||
payment_method String @db.VarChar(20)
|
||||
status String @default("pending") @db.VarChar(20)
|
||||
buyer_message String? @db.Text
|
||||
seller_response String? @db.Text
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @updatedAt
|
||||
expires_at DateTime?
|
||||
accepted_at DateTime?
|
||||
rejected_at DateTime?
|
||||
|
||||
listing Listing @relation(fields: [listing_id], references: [listing_id], onDelete: Cascade)
|
||||
buyer User @relation("BuyerIntentions", fields: [buyer_id], references: [user_id], onDelete: Cascade)
|
||||
|
||||
@@index([listing_id])
|
||||
@@index([buyer_id])
|
||||
@@index([status])
|
||||
@@index([created_at(sort: Desc)])
|
||||
@@map("purchase_intentions")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user