Meteen naar de inhoud

BIP

import React, { useState, useEffect } from ‘react’; import { XCircle, Award, Users, ChevronUp, ChevronDown, Zap, Clock, CheckCircle, XSquare, Mail, QrCode, Share2, Bell, Link, Copy, Smile, Frown, Send, MessageSquare } from ‘lucide-react’; // Main App Component const App = () => { const [screen, setScreen] = useState(‘login’); const [user, setUser] = useState(null); const [leaderboard, setLeaderboard] = useState([]); const [currentQuestion, setCurrentQuestion] = useState(0); const [score, setScore] = useState(0); const [challengeTarget, setChallengeTarget] = useState(null); const [quizQuestions, setQuizQuestions] = useState([]); const [timeLeft, setTimeLeft] = useState(20); const [quizStarted, setQuizStarted] = useState(false); const [quizFinished, setQuizFinished] = useState(false); const [isCorrect, setIsCorrect] = useState(null); const [duelInvites, setDuelInvites] = useState([]); const [activeDuel, setActiveDuel] = useState(null); const [inviteCode, setInviteCode] = useState(”); const [waitingForOpponent, setWaitingForOpponent] = useState(false); const [notifications, setNotifications] = useState([]); const [chatOpen, setChatOpen] = useState(false); const [chatMessages, setChatMessages] = useState([]); const [messageInput, setMessageInput] = useState(”); const [opponentAnswered, setOpponentAnswered] = useState(false); const [opponentScore, setOpponentScore] = useState(0); const [opponentCorrect, setOpponentCorrect] = useState(null); const [duelResults, setDuelResults] = useState(null); const [inviteMethod, setInviteMethod] = useState(‘direct’); // Mock online users const [onlineUsers, setOnlineUsers] = useState([]); // Set up real players for the leaderboard with connection status useEffect(() => { if (leaderboard.length === 0) { const realPlayers = [ { id: 1, name: ‘Jos’, country: ‘Netherlands’, email: ‘j.vonk@fontys.nl’, score: 890, rank: 1, avatar: ‘👨‍🏫’, online: false, status: ‘offline’ }, { id: 2, name: ‘Sander’, country: ‘Netherlands’, email: ‘s.vanheeswijk@fontys.nl’, score: 840, rank: 2, avatar: ‘👨‍💻’, online: false, status: ‘offline’ }, { id: 3, name: ‘Onno’, country: ‘Netherlands’, email: ‘o.deklerk@fontys.nl’, score: 780, rank: 3, avatar: ‘👨‍🔬’, online: false, status: ‘offline’ }, { id: 4, name: ‘Bart’, country: ‘Netherlands’, email: ‘b.vanabeelen@fontys.nl’, score: 730, rank: 4, avatar: ‘👨‍🎓’, online: false, status: ‘offline’ }, ]; // Randomly set 1-3 players as online for demo purposes // In a real app, this would be managed by a backend const numOnline = 1 + Math.floor(Math.random() * 3); const shuffled = […realPlayers].sort(() => 0.5 – Math.random()); for (let i = 0; i < numOnline; i++) { shuffled[i].online = true; shuffled[i].status = 'online'; } setLeaderboard(shuffled.sort((a, b) => a.rank – b.rank)); setOnlineUsers(shuffled.filter(user => user.online)); } }, [leaderboard.length]); // Questions bank organized by difficulty level const questionsByLevel = { beginner: [ { question: “What is Papa John’s tagline in Spain?”, options: [ “Better Ingredients. Better Pizza.”, “This is Pizza, Papa.”, “Esto es Pizza, Papá.”, “The Best Pizza in Spain.” ], correctAnswer: 2 }, { question: “In what year did Papa John’s open its first store in Spain?”, options: [“2010”, “2014”, “2016”, “2018”], correctAnswer: 2 }, { question: “How many stores does Papa John’s have in Spain?”, options: [“Around 50”, “Around 75”, “Around 95”, “Around 120”], correctAnswer: 2 }, { question: “What is unique about Papa John’s dough according to their branding?”, options: [ “It’s imported from Italy”, “It’s always fresh, never frozen”, “It’s made with spring water only”, “It’s fermented for 48 hours” ], correctAnswer: 1 }, { question: “Which city in Spain has the most Papa John’s stores?”, options: [“Barcelona”, “Valencia”, “Madrid”, “Seville”], correctAnswer: 2 } ], intermediate: [ { question: “What is the brand personality of Papa John’s as described in the brief?”, options: [ “Friendly and approachable”, “Sophisticated and premium”, “Challengers: bold, brave, and here to play”, “Traditional and authentic” ], correctAnswer: 2 }, { question: “What special item does Papa John’s add to their pizza boxes that’s mentioned as a ‘surprise element’?”, options: [ “Garlic dipping sauce”, “A pepperoncini”, “Parmesan cheese packets”, “Herb seasoning” ], correctAnswer: 1 }, { question: “In how many European countries does Papa John’s operate?”, options: [“7”, “9”, “10”, “12”], correctAnswer: 2 }, { question: “What type of cheese does Papa John’s emphasize using in their marketing?”, options: [ “Blend of six cheeses”, “Authentic Italian cheese”, “Locally sourced cheese”, “100% mozzarella” ], correctAnswer: 3 }, { question: “What important element of Papa John’s product messaging is emphasized throughout the brief?”, options: [ “Fast delivery times”, “Customizable options”, “Quality of ingredients”, “Competitive pricing” ], correctAnswer: 2 } ], advanced: [ { question: “What strategic position is Papa John’s taking in the Spanish market according to the brief?”, options: [ “Value-focused budget option”, “Premium quality with unique touches”, “Health-conscious alternative”, “Family-oriented tradition” ], correctAnswer: 1 }, { question: “What is the target audience age range for Papa John’s Halloween campaign?”, options: [“12 to 25”, “16 to 35”, “25 to 45”, “All age groups”], correctAnswer: 1 }, { question: “In which year was Papa John’s founded globally?”, options: [“1976”, “1980”, “1984”, “1990”], correctAnswer: 2 }, { question: “What is emphasized about the vegetables used in Papa John’s pizzas?”, options: [ “They’re organic and locally sourced”, “They’re imported from specific regions”, “They’re fresh and chopped daily in-store”, “They’re pre-selected for optimal flavor” ], correctAnswer: 2 }, { question: “Besides Spain, name another European country where Papa John’s operates according to the brief:”, options: [ “France and Italy”, “Germany and Poland”, “Portugal and Netherlands”, “Sweden and Norway” ], correctAnswer: 2 } ], expert: [ { question: “What is the marketing philosophy expressed in the statement ‘If we’re just gonna do what everyone else does’?”, options: [ “We’d rather not do it at all”, “We’d do it better than them”, “We’d need to charge less”, “We’d find a new market” ], correctAnswer: 0 }, { question: “What is the primary objective of the Halloween 2025 campaign according to the brief?”, options: [ “Increase sales by 25%”, “Launch a new limited-time product”, “Drive awareness through a multi-channel approach”, “Compete directly with other pizza chains” ], correctAnswer: 2 }, { question: “Which statement best describes Papa John’s communication positioning according to the brief?”, options: [ “We’re saving the world through better ingredients”, “We’re not saving the world. Pizza is about fun and good times.”, “We’re transforming the pizza industry standards”, “We’re preserving authentic pizza traditions” ], correctAnswer: 1 }, { question: “According to the brief, which of these approaches is most aligned with the brand’s tone?”, options: [ “Detailed explanations of sourcing practices”, “Emotional storytelling around family traditions”, “Say it like it is – This is what we’ve got, this is how it is”, “Aspirational messaging about premium lifestyles” ], correctAnswer: 2 }, { question: “In which specific countries must the Halloween campaign be simultaneously implemented?”, options: [ “Spain, Italy, Portugal, and France”, “Spain, Czech Republic, Romania, and Netherlands”, “Spain, UK, Germany, and Poland”, “All European locations” ], correctAnswer: 1 } ] }; // Generate quiz questions based on user’s rank const generateQuestions = (userRank) => { let questions = []; // Determine difficulty distribution based on rank if (userRank >= 1 && userRank <= 3) { // Top ranks get mostly expert questions questions = questions.concat(getRandomQuestions(questionsByLevel.expert, 5)); questions = questions.concat(getRandomQuestions(questionsByLevel.advanced, 3)); questions = questions.concat(getRandomQuestions(questionsByLevel.intermediate, 2)); } else if (userRank >= 4 && userRank <= 6) { // Middle-high ranks get mostly advanced questions questions = questions.concat(getRandomQuestions(questionsByLevel.expert, 2)); questions = questions.concat(getRandomQuestions(questionsByLevel.advanced, 5)); questions = questions.concat(getRandomQuestions(questionsByLevel.intermediate, 3)); } else if (userRank >= 7 && userRank <= 9) { // Middle ranks get mostly intermediate questions questions = questions.concat(getRandomQuestions(questionsByLevel.advanced, 2)); questions = questions.concat(getRandomQuestions(questionsByLevel.intermediate, 5)); questions = questions.concat(getRandomQuestions(questionsByLevel.beginner, 3)); } else { // Lower ranks get mostly beginner questions questions = questions.concat(getRandomQuestions(questionsByLevel.intermediate, 2)); questions = questions.concat(getRandomQuestions(questionsByLevel.beginner, 8)); } // Shuffle questions return shuffleArray(questions); }; // Helper to get random questions from a category const getRandomQuestions = (questionSet, count) => { const shuffled = […questionSet].sort(() => 0.5 – Math.random()); return shuffled.slice(0, count); }; // Helper to shuffle array const shuffleArray = (array) => { return […array].sort(() => 0.5 – Math.random()); }; // Generate a unique invite code const generateInviteCode = () => { const chars = ‘ABCDEFGHJKLMNPQRSTUVWXYZ23456789’; let result = ”; for (let i = 0; i < 6; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; }; // Handle user login const handleLogin = (username) => { if (!username) return; // Create a new user or find existing one let newUser; const existingUserIndex = leaderboard.findIndex(u => u.name.toLowerCase() === username.toLowerCase()); if (existingUserIndex >= 0) { // Update the status of the existing user to online const updatedLeaderboard = […leaderboard]; updatedLeaderboard[existingUserIndex] = { …updatedLeaderboard[existingUserIndex], online: true, status: ‘online’ }; newUser = updatedLeaderboard[existingUserIndex]; setLeaderboard(updatedLeaderboard); setOnlineUsers(updatedLeaderboard.filter(u => u.online)); } else { // Only allow login as one of the pre-defined users alert(“Please log in as one of the real players: Jos, Sander, Onno, or Bart”); return; } setUser(newUser); // Add welcome notification addNotification(`Welcome to Papa John’s Marketing Challenge, ${username}!`); // Generate personal invite code setInviteCode(generateInviteCode()); // In a real app, this would broadcast the user’s online status to all other users setScreen(‘home’); }; // Add notification const addNotification = (message) => { const newNotification = { id: Date.now(), message, read: false, timestamp: new Date() }; setNotifications(prev => [newNotification, …prev]); }; // Sort leaderboard by score const sortLeaderboard = (board) => { const sorted = […board].sort((a, b) => b.score – a.score); // Update ranks return sorted.map((user, index) => ({ …user, rank: index + 1 })); }; // Send duel invitation with real-time connection const sendDuelInvitation = (targetUser) => { // Don’t allow challenging busy players if (targetUser.status === ‘busy’) { addNotification(`${targetUser.name} is currently in another challenge.`); return; } // Update opponent status to pending const updatedLeaderboard = leaderboard.map(player => { if (player.id === targetUser.id) { return { …player, status: ‘pending’ }; } return player; }); setLeaderboard(updatedLeaderboard); // Update current user status to indicate waiting setUser({ …user, status: ‘waiting’ }); // Create pending challenge setChallengeTarget(targetUser); // Show waiting screen for connection setWaitingForOpponent(true); addNotification(`Waiting for ${targetUser.name} to accept your challenge…`); // In a real app, this would be a WebSocket connection to the target user // For demo purposes, we’ll simulate the other player’s response setTimeout(() => { // Simulate decision (90% acceptance rate for demo) const accepted = Math.random() > 0.1; if (accepted) { // Update opponent status to busy const busyLeaderboard = updatedLeaderboard.map(player => { if (player.id === targetUser.id) { return { …player, status: ‘busy’ }; } if (player.id === user.id) { return { …player, status: ‘busy’ }; } return player; }); setLeaderboard(busyLeaderboard); // Update user status setUser({ …user, status: ‘busy’ }); addNotification(`${targetUser.name} accepted your challenge! Starting duel…`); // Generate questions and prepare duel const questions = generateQuestions(Math.floor((user.rank + targetUser.rank) / 2)); setQuizQuestions(questions); setActiveDuel({ opponent: targetUser, startTime: new Date(), questions, connected: true, bothReady: false }); // Move to connection confirmation screen setWaitingForOpponent(false); setScreen(‘connectionConfirm’); } else { // Reset status const resetLeaderboard = updatedLeaderboard.map(player => { if (player.id === targetUser.id) { return { …player, status: ‘online’ }; } return player; }); setLeaderboard(resetLeaderboard); // Reset user status setUser({ …user, status: ‘online’ }); // Notify user of decline addNotification(`${targetUser.name} declined your challenge.`); setWaitingForOpponent(false); setChallengeTarget(null); } }, 3000 + Math.random() * 2000); // Random wait time for realism }; // Accept a duel invitation const acceptDuelInvitation = (invite) => { const sender = leaderboard.find(u => u.id === invite.sender.id); // Remove the invitation setDuelInvites(prev => prev.filter(i => i.id !== invite.id)); // Start the duel startDuel(sender); }; // Start a duel match with confirmed connection const startDuel = (opponent) => { // Reset stats setCurrentQuestion(0); setScore(0); setOpponentScore(0); setTimeLeft(20); setIsCorrect(null); setOpponentCorrect(null); setOpponentAnswered(false); setQuizStarted(true); setQuizFinished(false); setChatMessages([]); // Set both players as ready and connected setActiveDuel(prev => ({ …prev, bothReady: true, connectionTime: new Date() })); // Start countdown setScreen(‘countdown’); // After countdown, start the actual duel setTimeout(() => { setScreen(‘duel’); }, 3000); }; // Function for player to confirm ready status const confirmConnection = () => { addNotification(`You’re connected with ${activeDuel.opponent.name}!`); addNotification(“Get ready for the challenge to begin!”); // In a real app, this would notify the server that this player is ready // For demo purposes, simulate both players being ready setTimeout(() => { // Start the actual duel startDuel(activeDuel.opponent); }, 1500); }; // Join duel with code const joinDuelWithCode = (code) => { // In a real app, this would validate the code on the server if (code.length < 4) { addNotification("Please enter a valid duel code"); return; } // Simulate looking for match setWaitingForOpponent(true); // For demo, we'll select an opponent that the user can challenge setTimeout(() => { setWaitingForOpponent(false); const challengeableOpponents = leaderboard.filter(u => u.id !== user.id && canChallenge(u)); if (challengeableOpponents.length > 0) { const randomOpponent = challengeableOpponents[Math.floor(Math.random() * challengeableOpponents.length)]; addNotification(`Connected with ${randomOpponent.name} for a duel!`); // Start duel startDuel(randomOpponent); } else { addNotification(“No challengers found. You can only challenge players up to 2 ranks above you.”); setScreen(‘home’); } }, 3000); }; // Send a chat message const sendChatMessage = () => { if (!messageInput.trim()) return; const newMessage = { id: Date.now(), sender: user, text: messageInput, timestamp: new Date() }; setChatMessages(prev => […prev, newMessage]); setMessageInput(”); // Simulate opponent response if (activeDuel && Math.random() > 0.5) { setTimeout(() => { const responseMessages = [ “Good luck!”, “You’re going down!”, “May the best marketer win!”, “Let’s see who knows more about Papa John’s!”, “I’m going to win this one 🍕” ]; const opponentMessage = { id: Date.now() + 1, sender: activeDuel.opponent, text: responseMessages[Math.floor(Math.random() * responseMessages.length)], timestamp: new Date() }; setChatMessages(prev => […prev, opponentMessage]); }, 1500 + Math.random() * 2000); } }; // Check if user can challenge another user (at most 2 ranks above) const canChallenge = (targetUser) => { // Can only challenge players up to 2 positions above in ranking return targetUser.rank < user.rank + 3 && targetUser.rank >= 1 && targetUser.id !== user.id; }; // Handle answer selection const handleAnswerSelect = (answerIndex) => { if (quizFinished) return; const currentQ = quizQuestions[currentQuestion]; const isAnswerCorrect = answerIndex === currentQ.correctAnswer; setIsCorrect(isAnswerCorrect); if (isAnswerCorrect) { // Calculate score based on time left and question difficulty const timeBonus = timeLeft * 5; const difficultyBonus = getDifficultyBonus(currentQuestion); const questionScore = 100 + timeBonus + difficultyBonus; setScore(prevScore => prevScore + questionScore); } // In duel mode, simulate opponent’s answer if (activeDuel) { simulateOpponentAnswer(); } // Move to next question after a short delay setTimeout(() => { setIsCorrect(null); setOpponentCorrect(null); setOpponentAnswered(false); if (currentQuestion < quizQuestions.length - 1) { setCurrentQuestion(prev => prev + 1); setTimeLeft(20); // Reset timer for next question } else { // End quiz finishQuiz(); } }, 2000); }; // Simulate opponent’s answer in duel mode const simulateOpponentAnswer = () => { // Random delay for opponent’s answer const answerDelay = 500 + Math.random() * 3000; setTimeout(() => { setOpponentAnswered(true); // Skill based on rank const opponentSkill = 1 – (activeDuel.opponent.rank / 15); // Higher rank = higher skill // Determine if opponent answers correctly (weighted by skill) const isCorrect = Math.random() < (0.5 + opponentSkill / 2); setOpponentCorrect(isCorrect); if (isCorrect) { // Calculate opponent score const remainingTime = Math.floor(Math.random() * timeLeft); const timeBonus = remainingTime * 5; const difficultyBonus = getDifficultyBonus(currentQuestion); const questionScore = 100 + timeBonus + difficultyBonus; setOpponentScore(prev => prev + questionScore); } }, answerDelay); }; // Get bonus points based on question difficulty const getDifficultyBonus = (questionIndex) => { // Earlier questions are easier, later ones are harder return questionIndex * 10; }; // Finish the quiz and update rankings const finishQuiz = () => { setQuizFinished(true); // Calculate results for duel if (activeDuel) { const playerWon = score > opponentScore; const isDraw = score === opponentScore; setDuelResults({ playerScore: score, opponentScore: opponentScore, playerWon, isDraw }); // Update rankings based on duel results if (playerWon) { // Player moves up addNotification(`You won the duel against ${activeDuel.opponent.name}!`); } else if (!isDraw) { // Opponent moves up addNotification(`You lost the duel against ${activeDuel.opponent.name}.`); } else { // Draw – no change addNotification(`Your duel with ${activeDuel.opponent.name} ended in a draw!`); } } // Update user score and rankings setTimeout(() => { const newLeaderboard = […leaderboard]; // Find current user const userIndex = newLeaderboard.findIndex(u => u.id === user.id); if (userIndex >= 0) { // Update the user’s score newLeaderboard[userIndex] = { …newLeaderboard[userIndex], score: newLeaderboard[userIndex].score + score }; // If this was a duel and the player won, swap ranks with opponent if needed if (activeDuel && score > opponentScore) { const opponentIndex = newLeaderboard.findIndex(u => u.id === activeDuel.opponent.id); if (opponentIndex >= 0 && newLeaderboard[opponentIndex].rank < newLeaderboard[userIndex].rank) { // Boost player score above opponent newLeaderboard[userIndex].score = newLeaderboard[opponentIndex].score + 10; } } // Reset status for both players if (activeDuel) { const opponentIndex = newLeaderboard.findIndex(u => u.id === activeDuel.opponent.id); if (opponentIndex >= 0) { newLeaderboard[opponentIndex] = { …newLeaderboard[opponentIndex], status: ‘online’ }; } newLeaderboard[userIndex] = { …newLeaderboard[userIndex], status: ‘online’ }; } // Sort leaderboard and update ranks const sortedLeaderboard = sortLeaderboard(newLeaderboard); setLeaderboard(sortedLeaderboard); // Update current user const updatedUser = sortedLeaderboard.find(u => u.id === user.id); setUser(updatedUser); } setScreen(activeDuel ? ‘duelResults’ : ‘results’); }, 1000); }; // Timer effect useEffect(() => { let timer; if (quizStarted && !quizFinished && timeLeft > 0) { timer = setTimeout(() => { setTimeLeft(prev => prev – 1); }, 1000); } else if (timeLeft === 0 && !quizFinished) { // Time’s up, move to next question setIsCorrect(false); // In duel mode, simulate opponent’s answer if they haven’t answered yet if (activeDuel && !opponentAnswered) { simulateOpponentAnswer(); } setTimeout(() => { setIsCorrect(null); setOpponentCorrect(null); setOpponentAnswered(false); if (currentQuestion < quizQuestions.length - 1) { setCurrentQuestion(prev => prev + 1); setTimeLeft(20); } else { finishQuiz(); } }, 2000); } return () => clearTimeout(timer); }, [timeLeft, quizStarted, quizFinished, currentQuestion, quizQuestions.length, activeDuel, opponentAnswered]); // Copy invite code to clipboard const copyInviteCode = () => { navigator.clipboard.writeText(inviteCode).then(() => { addNotification(“Invite code copied to clipboard!”); }); }; // Render login screen const renderLogin = () => (

Papa John’s

Marketing Challenge

Enter Your Name

); // Render home screen const renderHome = () => (

Papa John’s Challenge

{user.avatar} {user.name}

Your Stats

Rank #{user.rank}

Score

{user.score}

Duels

12

Win Rate

67%

Challenge a Friend

Direct Challenge

Challenge someone directly from the leaderboard

Invite Code

Share your code or enter someone else’s code

QR Code

Generate a QR code for quick in-person challenges

{inviteMethod === ‘direct’ && ( )} {inviteMethod === ‘code’ && (
{inviteCode}
)} {inviteMethod === ‘qr’ && (
{/* This would be a real QR code in production */}
QR Code for
{inviteCode}

Let your friend scan this code to challenge you

)}

Practice Mode

Test your knowledge about Papa John’s marketing strategy and improve your skills!

Leaderboard

{leaderboard.map((rankUser) => (
{rankUser.rank}
{rankUser.avatar} {rankUser.id !== user.id && ( )}
{rankUser.name}
{rankUser.country} {rankUser.id !== user.id && ( {rankUser.status === ‘offline’ ? ‘Offline’ : rankUser.status === ‘online’ ? ‘Online’ : rankUser.status === ‘busy’ ? ‘In Challenge’ : rankUser.status === ‘pending’ ? ‘Pending’ : ”} )}
{rankUser.score}
{canChallenge(rankUser) && rankUser.status === ‘online’ && ( )} {canChallenge(rankUser) && rankUser.status !== ‘online’ && ( )}
))}

Online Now

{onlineUsers.length} Online
{leaderboard.filter(u => u.id !== user.id && canChallenge(u)).map(challengeableUser => (
{challengeableUser.avatar}
{challengeableUser.name} Rank #{challengeableUser.rank}
))}
); // Render challenge screen const renderChallengeScreen = () => (

Challenge Opponents

Available Opponents

{leaderboard .filter(u => u.id !== user.id && canChallenge(u)) .map(opponent => (
{opponent.avatar}

{opponent.name}

Rank #{opponent.rank} {opponent.status === ‘offline’ ? ‘Offline’ : opponent.status === ‘online’ ? ‘Online’ : opponent.status === ‘busy’ ? ‘In Challenge’ : opponent.status === ‘pending’ ? ‘Pending’ : ”}
{opponent.email}
{opponent.rank < user.rank ? ( Higher rank ) : ( Lower rank )} {opponent.status === ‘online’ ? ( ) : ( )}
))} {leaderboard.filter(u => u.id !== user.id && canChallenge(u)).length === 0 && (

No opponents available to challenge

{user.rank <= 2 ? "You can only challenge players up to 2 ranks above you." : "You're already at or near the top of the leaderboard!"}

)}
); // Render notifications screen const renderNotificationsScreen = () => (

Notifications

Your Notifications

{notifications.length === 0 ? (

No notifications yet

) : (
{notifications.map(notification => (

{notification.message}

{notification.timestamp.toLocaleTimeString([], { hour: ‘2-digit’, minute: ‘2-digit’ })}
))}
)}
); // Render waiting screen for finding opponent const renderWaitingScreen = () => (

Waiting for Opponent

Waiting for response…

{challengeTarget && (
{challengeTarget.avatar}

{challengeTarget.name}

{challengeTarget.email}

Challenge invitation sent. Waiting for {challengeTarget.name} to respond…

)}

Please wait while we establish a connection

); // Render connection confirmation screen const renderConnectionConfirmScreen = () => (

Establish Connection

{user.avatar}

You

Connected

{activeDuel.opponent.avatar}

{activeDuel.opponent.name}

Connected

Connection Established!

You are now connected with {activeDuel.opponent.name} for a marketing challenge duel. Click Ready when you’re prepared to begin!

); // Render countdown screen const renderCountdownScreen = () => (

Duel Starting

{user.avatar}

{user.name}

VS
{activeDuel.opponent.avatar}

{activeDuel.opponent.name}

{/* In a real app, this would be a dynamic countdown */} 3

Get ready for the challenge!

); // Helper component to render Trophy icon const Trophy = ({ size, className }) => ( ); // Render duel screen const renderDuelScreen = () => { if (!activeDuel) return null; const currentQ = quizQuestions[currentQuestion]; const progress = ((currentQuestion + 1) / quizQuestions.length) * 100; return (

Duel: You vs {activeDuel.opponent.name}

{timeLeft}s
{/* Duel scoreboard */}
{user.avatar}

You

{score}

VS

{activeDuel.opponent.name}

{opponentScore}

{activeDuel.opponent.avatar}
{/* Question and answers */}

{currentQ.question}

{currentQ.options.map((option, index) => ( ))}
{/* Player status indicators */}
{user.avatar}
You {isCorrect === true && } {isCorrect === false && }
{activeDuel.opponent.name}
{activeDuel.opponent.avatar}
{opponentAnswered ? ( opponentCorrect === true ? ( ) : ( ) ) : (
)}
{/* Chat slide-in panel */}

Chat with {activeDuel.opponent.name}

{chatMessages.length === 0 ? (

No messages yet

Start the conversation!

) : (
{chatMessages.map(message => (

{message.sender.id === user.id ? ‘You’ : message.sender.name}

{message.text}

{message.timestamp.toLocaleTimeString([], { hour: ‘2-digit’, minute: ‘2-digit’ })}

))}
)}
setMessageInput(e.target.value)} onKeyPress={e => { if (e.key === ‘Enter’) { sendChatMessage(); } }} />
); }; // Render duel results screen const renderDuelResults = () => { if (!duelResults || !activeDuel) return null; const { playerScore, opponentScore, playerWon, isDraw } = duelResults; return (

Duel Results

{isDraw ? “It’s a Draw!” : playerWon ? “Victory!” : “Defeat!”}

{user.avatar}

You

{playerScore}

VS
{activeDuel.opponent.avatar}

{activeDuel.opponent.name}

{opponentScore}

{isDraw ? “You both performed equally well!” : playerWon ? `You beat ${activeDuel.opponent.name}!` : `${activeDuel.opponent.name} won this time.`}

Questions

{quizQuestions.length}

New Rank

#{user.rank}

Duel Summary

{quizQuestions.slice(0, 5).map((q, i) => (

{q.question}

Correct answer: {q.options[q.correctAnswer]}

))} {quizQuestions.length > 5 && (

+ {quizQuestions.length – 5} more questions

)}
); }; // Render quiz screen const renderQuiz = () => { const currentQ = quizQuestions[currentQuestion]; const progress = ((currentQuestion + 1) / quizQuestions.length) * 100; return (

Papa John’s Quiz

{timeLeft}s
Question {currentQuestion + 1} of {quizQuestions.length} Score: {score}

{currentQ.question}

{currentQ.options.map((option, index) => ( ))}
); }; // Render results screen const renderResults = () => { const correctAnswers = quizQuestions.reduce( (count, question, index) => count + (0 === question.correctAnswer ? 1 : 0), 0 ); const accuracy = Math.round((correctAnswers / quizQuestions.length) * 100); return (

Challenge Results

Challenge Complete!

Total Score

{score}

Accuracy

{accuracy}%

New Rank

#{user.rank}

Challenge Summary

{quizQuestions.slice(0, 5).map((q, i) => (

{q.question}

Correct answer: {q.options[q.correctAnswer]}

))} {quizQuestions.length > 5 && (

+ {quizQuestions.length – 5} more questions

)}
); }; // Main render method if (waitingForOpponent) { return renderWaitingScreen(); } switch (screen) { case ‘login’: return renderLogin(); case ‘home’: return renderHome(); case ‘challenge’: return renderChallengeScreen(); case ‘notifications’: return renderNotificationsScreen(); case ‘quiz’: return renderQuiz(); case ‘results’: return renderResults(); case ‘duel’: return renderDuelScreen(); case ‘duelResults’: return renderDuelResults(); case ‘connectionConfirm’: return renderConnectionConfirmScreen(); case ‘countdown’: return renderCountdownScreen(); default: return renderLogin(); } }; export default App;