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,189 @@
|
||||
-- Migration 012: Telemetria e Expansão de Anúncios
|
||||
-- Criado em: 2025-01-27
|
||||
|
||||
-- ============================================
|
||||
-- 1. Tabela de Eventos de Telemetria
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS telemetry_events (
|
||||
event_id SERIAL PRIMARY KEY,
|
||||
event_type VARCHAR(50) NOT NULL,
|
||||
ad_id INTEGER REFERENCES listings(listing_id) ON DELETE CASCADE,
|
||||
user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
|
||||
session_id VARCHAR(255),
|
||||
metadata JSONB DEFAULT '{}'::jsonb,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Índices para performance
|
||||
CREATE INDEX IF NOT EXISTS idx_telemetry_ad_id ON telemetry_events(ad_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_telemetry_user_id ON telemetry_events(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_telemetry_timestamp ON telemetry_events(timestamp DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_telemetry_event_type ON telemetry_events(event_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_telemetry_session_id ON telemetry_events(session_id);
|
||||
|
||||
-- Índice composto para queries de analytics
|
||||
CREATE INDEX IF NOT EXISTS idx_telemetry_ad_type_time ON telemetry_events(ad_id, event_type, timestamp DESC);
|
||||
|
||||
-- ============================================
|
||||
-- 2. Expansão da Tabela listings
|
||||
-- ============================================
|
||||
ALTER TABLE listings
|
||||
ADD COLUMN IF NOT EXISTS is_featured BOOLEAN DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS favorites_count INTEGER DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS inquiries_count INTEGER DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS price_history JSONB DEFAULT '[]'::jsonb,
|
||||
ADD COLUMN IF NOT EXISTS expires_at TIMESTAMP;
|
||||
|
||||
-- Índices para novos campos
|
||||
CREATE INDEX IF NOT EXISTS idx_listings_is_featured ON listings(is_featured) WHERE is_featured = TRUE;
|
||||
CREATE INDEX IF NOT EXISTS idx_listings_expires_at ON listings(expires_at) WHERE expires_at IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_listings_favorites_count ON listings(favorites_count DESC);
|
||||
|
||||
-- ============================================
|
||||
-- 3. Tabela de Analytics Agregados
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS ad_analytics (
|
||||
ad_id INTEGER PRIMARY KEY REFERENCES listings(listing_id) ON DELETE CASCADE,
|
||||
impressions INTEGER DEFAULT 0,
|
||||
clicks INTEGER DEFAULT 0,
|
||||
ctr DECIMAL(5, 2) DEFAULT 0.00, -- Click-through rate em porcentagem
|
||||
avg_view_duration DECIMAL(10, 2) DEFAULT 0.00, -- em segundos
|
||||
bounce_rate DECIMAL(5, 2) DEFAULT 0.00, -- em porcentagem
|
||||
inquiries INTEGER DEFAULT 0,
|
||||
favorites INTEGER DEFAULT 0,
|
||||
conversion_rate DECIMAL(5, 2) DEFAULT 0.00, -- em porcentagem
|
||||
time_to_sell INTEGER DEFAULT NULL, -- em horas
|
||||
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Trigger para atualizar last_updated automaticamente
|
||||
CREATE OR REPLACE FUNCTION update_ad_analytics_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.last_updated = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trigger_update_ad_analytics_updated_at
|
||||
BEFORE UPDATE ON ad_analytics
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_ad_analytics_updated_at();
|
||||
|
||||
-- ============================================
|
||||
-- 4. Tabela de Inventário do Usuário
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS user_inventory (
|
||||
inventory_id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
|
||||
item_id INTEGER NOT NULL,
|
||||
item_name VARCHAR(255) NOT NULL,
|
||||
quantity INTEGER DEFAULT 1 CHECK (quantity > 0),
|
||||
acquired_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(user_id, item_id)
|
||||
);
|
||||
|
||||
-- Índices
|
||||
CREATE INDEX IF NOT EXISTS idx_user_inventory_user_id ON user_inventory(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_inventory_item_id ON user_inventory(item_id);
|
||||
|
||||
-- ============================================
|
||||
-- 5. Tabela de Favoritos
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS user_favorites (
|
||||
user_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
|
||||
ad_id INTEGER NOT NULL REFERENCES listings(listing_id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (user_id, ad_id)
|
||||
);
|
||||
|
||||
-- Índices
|
||||
CREATE INDEX IF NOT EXISTS idx_user_favorites_user_id ON user_favorites(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_favorites_ad_id ON user_favorites(ad_id);
|
||||
|
||||
-- ============================================
|
||||
-- 6. Trigger para Atualizar favorites_count
|
||||
-- ============================================
|
||||
CREATE OR REPLACE FUNCTION update_listing_favorites_count()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF TG_OP = 'INSERT' THEN
|
||||
UPDATE listings
|
||||
SET favorites_count = favorites_count + 1
|
||||
WHERE listing_id = NEW.ad_id;
|
||||
RETURN NEW;
|
||||
ELSIF TG_OP = 'DELETE' THEN
|
||||
UPDATE listings
|
||||
SET favorites_count = GREATEST(0, favorites_count - 1)
|
||||
WHERE listing_id = OLD.ad_id;
|
||||
RETURN OLD;
|
||||
END IF;
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trigger_update_listing_favorites_count
|
||||
AFTER INSERT OR DELETE ON user_favorites
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_listing_favorites_count();
|
||||
|
||||
-- ============================================
|
||||
-- 7. Função para Inicializar Analytics ao Criar Anúncio
|
||||
-- ============================================
|
||||
CREATE OR REPLACE FUNCTION initialize_ad_analytics()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
INSERT INTO ad_analytics (ad_id)
|
||||
VALUES (NEW.listing_id)
|
||||
ON CONFLICT (ad_id) DO NOTHING;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trigger_initialize_ad_analytics
|
||||
AFTER INSERT ON listings
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION initialize_ad_analytics();
|
||||
|
||||
-- ============================================
|
||||
-- 8. Função para Atualizar Price History
|
||||
-- ============================================
|
||||
CREATE OR REPLACE FUNCTION update_price_history()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
new_price_entry JSONB;
|
||||
current_history JSONB;
|
||||
BEGIN
|
||||
-- Verifica se algum preço mudou
|
||||
IF (OLD.price_pix IS DISTINCT FROM NEW.price_pix) OR
|
||||
(OLD.price_tibia_coins IS DISTINCT FROM NEW.price_tibia_coins) OR
|
||||
(OLD.price_gold_coins IS DISTINCT FROM NEW.price_gold_coins) THEN
|
||||
|
||||
-- Cria entrada de histórico
|
||||
new_price_entry := jsonb_build_object(
|
||||
'timestamp', CURRENT_TIMESTAMP,
|
||||
'price_pix', NEW.price_pix,
|
||||
'price_tibia_coins', NEW.price_tibia_coins,
|
||||
'price_gold_coins', NEW.price_gold_coins
|
||||
);
|
||||
|
||||
-- Obtém histórico atual
|
||||
current_history := COALESCE(NEW.price_history, '[]'::jsonb);
|
||||
|
||||
-- Adiciona nova entrada no início do array
|
||||
NEW.price_history := jsonb_insert(
|
||||
current_history,
|
||||
'{0}',
|
||||
new_price_entry
|
||||
);
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trigger_update_price_history
|
||||
BEFORE UPDATE ON listings
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_price_history();
|
||||
|
||||
Reference in new issue
Block a user