// ============================================ // GUILD CREATION WIZARD V2 - Ultimate Premium Experience // With Perks, Events, Achievements & More Gamification // ============================================ const { useState, useEffect, useRef } = React; // ============================================ // CONSTANTS // ============================================ const GUILD_CREATION_COST = 10000; // 100 coins in cents const GUILD_CATEGORIES = [ { id: 'competitive', name: 'Competitive', desc: 'Rankings & guild wars', icon: 'trophy', bonus: '+10% War XP' }, { id: 'social', name: 'Social', desc: 'Fun & friendship focused', icon: 'users', bonus: '+5 Max Members' }, { id: 'trading', name: 'Trading', desc: 'Economy & strategies', icon: 'coins', bonus: '+5% Treasury Bonus' }, { id: 'highroller', name: 'High Roller', desc: 'Big bets, big wins', icon: 'diamond', bonus: 'VIP Perks Unlocked' }, ]; // Extended color palette with text color for contrast const GUILD_COLORS = [ { color: '#5bffb2', name: 'Emerald', textColor: '#000' }, { color: '#8b5cf6', name: 'Royal Purple', textColor: '#fff' }, { color: '#f59e0b', name: 'Gold', textColor: '#000' }, { color: '#ef4444', name: 'Crimson', textColor: '#fff' }, { color: '#3b82f6', name: 'Sapphire', textColor: '#fff' }, { color: '#ec4899', name: 'Hot Pink', textColor: '#fff' }, { color: '#14b8a6', name: 'Teal', textColor: '#000' }, { color: '#f97316', name: 'Orange', textColor: '#000' }, { color: '#6366f1', name: 'Indigo', textColor: '#fff' }, { color: '#84cc16', name: 'Lime', textColor: '#000' }, { color: '#06b6d4', name: 'Cyan', textColor: '#000' }, { color: '#a855f7', name: 'Violet', textColor: '#fff' }, { color: '#f43f5e', name: 'Rose', textColor: '#fff' }, { color: '#22c55e', name: 'Green', textColor: '#000' }, { color: '#eab308', name: 'Yellow', textColor: '#000' }, { color: '#0ea5e9', name: 'Sky Blue', textColor: '#000' }, ]; // Gradient options for emblem backgrounds const GUILD_GRADIENTS = [ { id: 'emerald-purple', colors: ['#5bffb2', '#8b5cf6'], name: 'Emerald Purple', textColor: '#fff' }, { id: 'fire-gold', colors: ['#ef4444', '#f59e0b'], name: 'Fire Gold', textColor: '#fff' }, { id: 'ocean-deep', colors: ['#3b82f6', '#6366f1'], name: 'Ocean Deep', textColor: '#fff' }, { id: 'sunset', colors: ['#f97316', '#ec4899'], name: 'Sunset', textColor: '#fff' }, { id: 'aurora', colors: ['#14b8a6', '#5bffb2'], name: 'Aurora', textColor: '#000' }, { id: 'royal', colors: ['#8b5cf6', '#ec4899'], name: 'Royal', textColor: '#fff' }, { id: 'cyber', colors: ['#06b6d4', '#84cc16'], name: 'Cyber', textColor: '#000' }, { id: 'blood-moon', colors: ['#ef4444', '#a855f7'], name: 'Blood Moon', textColor: '#fff' }, ]; const GUILD_EMBLEMS = [ { id: 'swords', icon: 'swords', name: 'Crossed Swords' }, { id: 'shield', icon: 'shield', name: 'Shield' }, { id: 'crown', icon: 'crown', name: 'Crown' }, { id: 'star', icon: 'star', name: 'Star' }, { id: 'diamond', icon: 'diamond', name: 'Diamond' }, { id: 'fire', icon: 'fire', name: 'Fire' }, { id: 'bolt', icon: 'bolt', name: 'Lightning' }, { id: 'skull', icon: 'skull', name: 'Skull' }, { id: 'trophy', icon: 'trophy', name: 'Trophy' }, { id: 'target', icon: 'target', name: 'Target' }, { id: 'rocket', icon: 'rocket', name: 'Rocket' }, { id: 'sparkles', icon: 'sparkles', name: 'Sparkles' }, ]; const STARTER_PERKS = [ { id: 'treasury_boost', name: 'Treasury Boost', desc: 'Start with 500 coins in treasury', icon: 'coins', selected: true }, { id: 'recruitment_banner', name: 'Recruitment Banner', desc: 'Featured on guild listings for 24h', icon: 'megaphone', selected: false }, { id: 'war_ready', name: 'War Ready', desc: 'Skip cooldown for first guild war', icon: 'swords', selected: false }, { id: 'xp_boost', name: 'XP Boost', desc: '+25% guild XP for 7 days', icon: 'sparkles', selected: false }, ]; const EVENT_TEMPLATES = [ { id: 'war_night', name: 'War Night', desc: 'Coordinate guild wars together', icon: 'swords', time: 'Weekly' }, { id: 'jackpot_party', name: 'Jackpot Party', desc: 'Group jackpot sessions', icon: 'trophy', time: 'Daily' }, { id: 'trading_hour', name: 'Trading Hour', desc: 'Share tips & strategies', icon: 'coins', time: 'Weekly' }, { id: 'custom', name: 'Custom Event', desc: 'Create your own event', icon: 'calendar', time: 'Custom' }, ]; const WIZARD_STEPS = [ { id: 'basics', title: 'Foundation', subtitle: 'Name your guild', icon: 'flag' }, { id: 'identity', title: 'Identity', subtitle: 'Colors & emblem', icon: 'palette' }, { id: 'category', title: 'Category', subtitle: 'Choose your focus', icon: 'target' }, { id: 'story', title: 'Story', subtitle: 'Tell your tale', icon: 'scroll' }, { id: 'rules', title: 'Laws', subtitle: 'Set the rules', icon: 'gavel' }, { id: 'perks', title: 'Perks', subtitle: 'Starter bonuses', icon: 'gift' }, { id: 'event', title: 'First Event', subtitle: 'Plan your launch', icon: 'calendar' }, { id: 'review', title: 'Launch', subtitle: 'Create your guild', icon: 'rocket' }, ]; const ACHIEVEMENTS_PREVIEW = [ { name: 'Guild Founded', desc: 'Create your first guild', unlocked: true }, { name: 'First Blood', desc: 'Win your first guild war', unlocked: false }, { name: 'Full House', desc: 'Reach 10 members', unlocked: false }, { name: 'War Machine', desc: 'Win 10 guild wars', unlocked: false }, { name: 'Treasure Hoard', desc: 'Accumulate 10,000 in treasury', unlocked: false }, { name: 'Legendary', desc: 'Reach guild level 10', unlocked: false }, ]; // ============================================ // SVG ICONS // ============================================ const Icons = { trophy: , users: , coins: , star: , check: , x: , chevronLeft: , chevronRight: , shield: , crown: , diamond: , swords: , fire: , bolt: , skull: , scroll: , target: , sparkles: , calendar: , flag: , palette: , gavel: , gift: , rocket: , megaphone: , lock: , globe: , info: , }; const getIcon = (name) => Icons[name] || Icons.star; // Format coins const formatCoins = (cents) => ((cents || 0) / 100).toLocaleString('en-US', { minimumFractionDigits: 2 }); // ============================================ // MAIN WIZARD COMPONENT // ============================================ function GuildCreateWizard({ user, onClose, onSuccess }) { const [step, setStep] = useState(0); const [creating, setCreating] = useState(false); const [error, setError] = useState(''); const [showConfetti, setShowConfetti] = useState(false); // Form data const [formData, setFormData] = useState({ name: '', tag: '', category: '', primaryColor: '#5bffb2', secondaryColor: '#8b5cf6', useGradient: false, selectedGradient: null, emblem: 'shield', description: '', mission: '', slogan: '', rules: '', welcomeMessage: 'Welcome to the guild! Check out our rules and introduce yourself.', isPublic: true, minLevel: 1, requireApproval: false, selectedPerks: ['treasury_boost'], firstEvent: null, eventName: '', eventDesc: '', }); // Helper to get the current emblem background (color or gradient) const getEmblemBackground = () => { if (formData.useGradient && formData.selectedGradient) { const gradient = GUILD_GRADIENTS.find(g => g.id === formData.selectedGradient); if (gradient) { return `linear-gradient(135deg, ${gradient.colors[0]}, ${gradient.colors[1]})`; } } return formData.primaryColor; }; // Helper to get text color for current selection const getEmblemTextColor = () => { if (formData.useGradient && formData.selectedGradient) { const gradient = GUILD_GRADIENTS.find(g => g.id === formData.selectedGradient); return gradient ? gradient.textColor : '#fff'; } const color = GUILD_COLORS.find(c => c.color === formData.primaryColor); return color ? color.textColor : '#000'; }; const userBalance = user.balance || user.coins || 0; const canCreate = userBalance >= GUILD_CREATION_COST; const updateField = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); setError(''); }; const togglePerk = (perkId) => { setFormData(prev => { const perks = prev.selectedPerks.includes(perkId) ? prev.selectedPerks.filter(p => p !== perkId) : [...prev.selectedPerks, perkId].slice(0, 2); // Max 2 perks return { ...prev, selectedPerks: perks }; }); }; const validateStep = () => { switch (step) { case 0: // Basics if (formData.name.length < 3 || formData.name.length > 32) { setError('Guild name must be 3-32 characters'); return false; } if (formData.tag && (formData.tag.length < 2 || formData.tag.length > 6)) { setError('Guild tag must be 2-6 characters'); return false; } break; case 2: // Category if (!formData.category) { setError('Please select a guild category'); return false; } break; case 3: // Story if (formData.description.length < 20) { setError('Tell us more about your guild (at least 20 characters)'); return false; } if (formData.mission.length < 10) { setError('Add a mission statement (at least 10 characters)'); return false; } break; case 4: // Rules if (formData.rules.length < 10) { setError('Add at least one rule (10+ characters)'); return false; } break; } return true; }; const nextStep = () => { if (validateStep()) { setStep(prev => Math.min(prev + 1, WIZARD_STEPS.length - 1)); setError(''); } }; const prevStep = () => { setStep(prev => Math.max(prev - 1, 0)); setError(''); }; const createGuild = async () => { if (!canCreate) { setError(`Not enough coins! You need 100 coins, you have ${formatCoins(userBalance)}`); return; } setCreating(true); setError(''); try { // Determine the color to send (gradient or solid) let colorToSend = formData.primaryColor; if (formData.useGradient && formData.selectedGradient) { const gradient = GUILD_GRADIENTS.find(g => g.id === formData.selectedGradient); if (gradient) { // Send as special format: gradient:color1,color2 colorToSend = `gradient:${gradient.colors.join(',')}`; } } const res = await fetch('/api/guilds/create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ name: formData.name, tag: formData.tag.toUpperCase() || undefined, description: formData.description, is_public: formData.isPublic, mission: formData.mission, rules: formData.rules, welcome_message: formData.welcomeMessage, primary_color: colorToSend, emblem: formData.emblem, category: formData.category, min_level: formData.minLevel, slogan: formData.slogan, require_approval: formData.requireApproval, starter_perks: formData.selectedPerks, first_event: formData.firstEvent ? { type: formData.firstEvent, name: formData.eventName, description: formData.eventDesc } : null, }) }); // Check if response is JSON const contentType = res.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { if (res.status === 401) { setError('Session expired. Please refresh and log in again.'); } else if (res.status >= 500) { setError('Server error. Please try again later.'); } else { setError(`Error ${res.status}: Failed to create guild.`); } setCreating(false); return; } const data = await res.json(); if (res.ok) { setShowConfetti(true); setTimeout(() => { onSuccess(data.guild); }, 2000); } else { setError(data.detail || data.message || 'Failed to create guild'); } } catch (err) { console.error('Guild creation error:', err); setError('Network error. Please check your connection and try again.'); } setCreating(false); }; // ============================================ // STEP RENDERS // ============================================ const renderBasicsStep = () => (
Pick a name that strikes fear into enemies and inspires allies!
Choose colors and an emblem that represents your guild
This is how your guild will appear
What will your guild focus on? Each category provides unique bonuses!
What makes your guild special? What are you fighting for?
Set clear expectations for your members
Select up to 2 perks to give your guild a head start!
Launch your guild with a bang! Schedule your first community event.
Review your guild and prepare for greatness
"{formData.slogan}"
}{formData.mission}
{EVENT_TEMPLATES.find(e => e.id === formData.firstEvent)?.name || formData.eventName}
Welcome to [{formData.tag || formData.name.substring(0, 4).toUpperCase()}] {formData.name}
Step {step + 1} of {WIZARD_STEPS.length}: {WIZARD_STEPS[step].title}