diff --git a/backend/src/db/migrations/033_shop_phase5.sql b/backend/src/db/migrations/033_shop_phase5.sql new file mode 100644 index 0000000..c5a99fd --- /dev/null +++ b/backend/src/db/migrations/033_shop_phase5.sql @@ -0,0 +1,149 @@ +-- ═══════════════════════════════════════════════════════════════ +-- 033: Phase 5 — shop catalogue expansion +-- +-- Triples the shop's selection (10 → 30 items) so coins finally have +-- something interesting to buy. Adds: +-- • 12 new frames spanning price tiers 200-1200, palette covering +-- warm/cool/multi-color/animated/event ranges +-- • 9 new titles in 150-2000 coin range (some prestige-only) +-- • 1 new theme (warm paper) using the existing theme slug system +-- +-- Effects are intentionally NOT extended here — the front-end +-- _applyEffect() in js/api.js only supports pulse/sparkle/snow today, +-- and adding new effect kinds belongs in a follow-up that updates the +-- renderer. Frame previews and title pills already render properly +-- thanks to the Phase 4 shop UI changes (profile.html). +-- +-- Re-runnable (INSERT OR IGNORE — `name` is informational; the dedup +-- happens because the (name, type) pair would already be in shop_items +-- after the first run, but to be safe we re-check by name+type below). +-- ═══════════════════════════════════════════════════════════════ + +-- Helper pattern: INSERT only if no row with same name+type exists. +-- We can't use INSERT OR IGNORE without a UNIQUE index, so do it via +-- WHERE NOT EXISTS for each row. + +-- ── FRAMES ─────────────────────────────────────────────────────── +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Морская рамка', 'Спокойное синее свечение', 'frame', 'cosmetic', 250, + '{"css":"box-shadow:0 0 0 3px #1E88E5,0 0 14px rgba(30,136,229,0.45);border-color:#1E88E5"}', + 'waves', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Морская рамка' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Лесная рамка', 'Глубокий зелёный ореол', 'frame', 'cosmetic', 250, + '{"css":"box-shadow:0 0 0 3px #2E7D32,0 0 14px rgba(46,125,50,0.45);border-color:#2E7D32"}', + 'tree-pine', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Лесная рамка' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Закат', 'Розово-оранжевый градиент', 'frame', 'cosmetic', 350, + '{"css":"box-shadow:0 0 0 3px #FF6F61,0 0 16px rgba(255,111,97,0.55);border-color:#FF6F61"}', + 'sunset', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Закат' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Минимал', 'Чистая тонкая линия', 'frame', 'cosmetic', 200, + '{"css":"box-shadow:0 0 0 2px #1F2937;border-color:#1F2937"}', + 'square', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Минимал' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Винтаж', 'Тёплая сепия с патиной', 'frame', 'cosmetic', 400, + '{"css":"box-shadow:0 0 0 3px #8B6F47,0 0 12px rgba(139,111,71,0.4);border-color:#8B6F47;filter:sepia(0.2)"}', + 'image', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Винтаж' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Пиксельный', 'Ретро-двухпиксельный шаг', 'frame', 'cosmetic', 350, + '{"css":"box-shadow:0 0 0 2px #fff,0 0 0 4px #9B5DE5,0 0 0 6px #fff,0 0 0 8px #06D6E0;border-color:transparent"}', + 'grid-2x2', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Пиксельный' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Молния', 'Яркий жёлтый разряд', 'frame', 'cosmetic', 500, + '{"css":"box-shadow:0 0 0 3px #FBBF24,0 0 18px rgba(251,191,36,0.6);border-color:#FBBF24"}', + 'zap', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Молния' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Космос', 'Бескрайняя тьма с фиолетовым ядром', 'frame', 'cosmetic', 600, + '{"css":"box-shadow:0 0 0 3px #1E1B4B,0 0 18px rgba(124,58,237,0.6);border-color:#1E1B4B"}', + 'galaxy', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Космос' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Изумруд', 'Глубокий изумрудный градиент', 'frame', 'cosmetic', 700, + '{"css":"box-shadow:0 0 0 3px #10B981,0 0 18px rgba(16,185,129,0.6);border-color:#10B981"}', + 'gem', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Изумруд' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Призрак', 'Полупрозрачный размытый ореол', 'frame', 'cosmetic', 800, + '{"css":"box-shadow:0 0 0 3px rgba(255,255,255,0.3),0 0 20px rgba(255,255,255,0.5);border-color:rgba(255,255,255,0.3)"}', + 'ghost', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Призрак' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Кибер', 'Яркий неоновый ободок', 'frame', 'cosmetic', 900, + '{"css":"box-shadow:0 0 0 2px #06D6E0,0 0 0 4px #FF6B35,0 0 24px rgba(6,214,224,0.8);border-color:transparent"}', + 'cpu', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Кибер' AND type='frame'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Золотой ободок', 'Толстое золото вокруг аватара', 'frame', 'cosmetic', 1200, + '{"css":"box-shadow:0 0 0 4px #FFD700,0 0 22px rgba(255,215,0,0.7);border-color:#FFD700"}', + 'crown', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Золотой ободок' AND type='frame'); + +-- ── TITLES ─────────────────────────────────────────────────────── +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Стажёр', 'Только начинаешь путь', 'title', 'cosmetic', 150, + '{"text":"Стажёр","color":"#6B7280"}', 'user', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Стажёр' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Аналитик', 'Видишь паттерны там, где другие — числа', 'title', 'cosmetic', 300, + '{"text":"Аналитик","color":"#06D6E0"}', 'pie-chart', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Аналитик' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Геометр', 'Любитель углов и треугольников', 'title', 'cosmetic', 350, + '{"text":"Геометр","color":"#10B981"}', 'triangle', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Геометр' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Алгебраист', 'Уравнения — твоя стихия', 'title', 'cosmetic', 350, + '{"text":"Алгебраист","color":"#9B5DE5"}', 'sigma', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Алгебраист' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Физик', 'F = ma наизусть', 'title', 'cosmetic', 400, + '{"text":"Физик","color":"#FF6B35"}', 'atom', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Физик' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Олимпиец', 'Готов к олимпиадам', 'title', 'cosmetic', 600, + '{"text":"Олимпиец","color":"#FBBF24"}', 'medal', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Олимпиец' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Боссфайтер', 'Уничтожает боссов глав одной формулой', 'title', 'cosmetic', 700, + '{"text":"Боссфайтер","color":"#DC2626"}', 'swords', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Боссфайтер' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Магистр', 'Освоил всё, что предлагают', 'title', 'cosmetic', 1200, + '{"text":"Магистр","color":"#7C3AED"}', 'graduation-cap', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Магистр' AND type='title'); + +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Титул: Профессор', 'Топовый престиж', 'title', 'cosmetic', 2000, + '{"text":"Профессор","color":"#FFD700"}', 'graduation-cap', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Титул: Профессор' AND type='title'); + +-- ── THEMES (single addition — renderer already supports active_theme) ── +INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) +SELECT 'Тёплая бумага', 'Молочная палитра вместо синего', 'theme', 'cosmetic', 300, + '{"theme":"warm-paper"}', 'sun', 1 + WHERE NOT EXISTS (SELECT 1 FROM shop_items WHERE name='Тёплая бумага' AND type='theme');