diff --git a/api/get_active_perks.php b/api/get_active_perks.php new file mode 100644 index 0000000..4ddaef0 --- /dev/null +++ b/api/get_active_perks.php @@ -0,0 +1,33 @@ +prepare(" + SELECT perk_type, perk_value, user_name, expires_at + FROM shop_perks + WHERE expires_at > ? + ORDER BY created_at DESC + "); + $stmt->execute([$now]); + $all_active = $stmt->fetchAll(); + + $perks = [ + "pinned_message" => null, + "background" => null + ]; + + foreach ($all_active as $p) { + if (!$perks[$p["perk_type"]]) { + $perks[$p["perk_type"]] = $p; + } + } + + echo json_encode(["success" => true, "perks" => $perks]); +} catch (Exception $e) { + echo json_encode(["success" => false, "error" => $e->getMessage()]); +} diff --git a/api/shop.php b/api/shop.php new file mode 100644 index 0000000..793f102 --- /dev/null +++ b/api/shop.php @@ -0,0 +1,55 @@ + false, "error" => "Inicia sesión para comprar"]); + exit; +} + +$perks = [ + "pinned_message" => ["cost" => 500, "duration" => 3600], // 1 hour + "background" => ["cost" => 1000, "duration" => 1800], // 30 mins +]; + +if (!isset($perks[$action])) { + echo json_encode(["success" => false, "error" => "Producto no encontrado"]); + exit; +} + +$perk = $perks[$action]; + +try { + $pdo->beginTransaction(); + + // Check points + $stmt = $pdo->prepare("SELECT points FROM fans WHERE name = ?"); + $stmt->execute([$username]); + $user = $stmt->fetch(); + + if (!$user || $user["points"] < $perk["cost"]) { + echo json_encode(["success" => false, "error" => "No tienes suficientes puntos (" . $perk["cost"] . " requeridos)"]); + $pdo->rollBack(); + exit; + } + + // Deduct points + $stmt = $pdo->prepare("UPDATE fans SET points = points - ? WHERE name = ?"); + $stmt->execute([$perk["cost"], $username]); + + // Activate perk + $expires_at = date("Y-m-d H:i:s", time() + $perk["duration"]); + $stmt = $pdo->prepare("INSERT INTO shop_perks (perk_type, perk_value, user_name, expires_at) VALUES (?, ?, ?, ?)"); + $stmt->execute([$action, $value, $username, $expires_at]); + + $pdo->commit(); + echo json_encode(["success" => true, "message" => "¡Compra exitosa! Perk activado."]); +} catch (Exception $e) { + $pdo->rollBack(); + echo json_encode(["success" => false, "error" => $e->getMessage()]); +} diff --git a/db/migrations/20260217_create_shop_perks.sql b/db/migrations/20260217_create_shop_perks.sql new file mode 100644 index 0000000..76ad155 --- /dev/null +++ b/db/migrations/20260217_create_shop_perks.sql @@ -0,0 +1,9 @@ +-- Migration: Create shop_perks table +CREATE TABLE IF NOT EXISTS shop_perks ( + id INT AUTO_INCREMENT PRIMARY KEY, + perk_type VARCHAR(50) NOT NULL, -- "pinned_message", "background" + perk_value TEXT NOT NULL, -- The message text or the image URL + user_name VARCHAR(255) NOT NULL, + expires_at TIMESTAMP NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/index.php b/index.php index 6e96944..be6ed47 100644 --- a/index.php +++ b/index.php @@ -1291,6 +1291,107 @@ $twitter_link = "https://twitter.com/"; gap: 5px; font-weight: 700; } + + /* Shop Styles */ + .shop-modal { + display: none; + position: fixed; + z-index: 4000; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.8); + backdrop-filter: blur(10px); + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity 0.3s ease; + } + .shop-modal.show { + display: flex; + opacity: 1; + } + .shop-modal-content { + background: rgba(20, 20, 20, 0.9); + border: 1px solid rgba(255, 255, 255, 0.1); + padding: 2.5rem; + border-radius: 32px; + width: 90%; + max-width: 500px; + transform: scale(0.8); + transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); + box-shadow: 0 20px 60px rgba(0,0,0,0.5); + } + .shop-modal.show .shop-modal-content { + transform: scale(1); + } + .shop-item { + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + padding: 1.2rem; + border-radius: 20px; + margin-bottom: 1rem; + display: flex; + align-items: center; + gap: 15px; + transition: all 0.2s; + } + .shop-item:hover { + background: rgba(255, 255, 255, 0.1); + border-color: var(--primary-color); + } + .shop-item-icon { + width: 50px; + height: 50px; + background: rgba(56, 189, 248, 0.1); + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + color: var(--primary-color); + } + .shop-item-info { + flex: 1; + } + .shop-item-name { + font-weight: 800; + font-size: 1rem; + color: white; + } + .shop-item-desc { + font-size: 0.75rem; + opacity: 0.6; + } + .shop-item-price { + font-weight: 800; + color: #facc15; + display: flex; + align-items: center; + gap: 4px; + } + .pinned-message-container { + background: linear-gradient(90deg, rgba(56, 189, 248, 0.2), rgba(0, 200, 83, 0.2)); + border: 1px solid var(--primary-color); + border-radius: 12px; + padding: 0.8rem; + margin-bottom: 1rem; + display: none; + animation: fadeIn 0.5s ease; + position: relative; + } + .pinned-label { + font-size: 0.6rem; + font-weight: 800; + color: var(--primary-color); + text-transform: uppercase; + letter-spacing: 1px; + margin-bottom: 4px; + display: flex; + align-items: center; + gap: 4px; + }
@@ -1318,6 +1419,9 @@ $twitter_link = "https://twitter.com/";