now people can join and leave the game

This commit is contained in:
RezHackXYZ 2025-05-12 10:22:19 +05:30
parent bf582efc46
commit f83f50d9b2
No known key found for this signature in database
12 changed files with 408 additions and 22 deletions

View file

@ -1 +0,0 @@
// place files you want to import through the `$lib` alias in this folder.

6
src/lib/supabase.js Normal file
View file

@ -0,0 +1,6 @@
import { createClient } from '@supabase/supabase-js';
export const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY
);

View file

@ -1,27 +1,37 @@
<script>
let questions = $state([
import { supabase } from '$lib/supabase';
import { goto } from '$app/navigation';
let questions = [
{
name: '',
answers: ['', '', '', ''],
correctAnswer: undefined
}
]);
];
function startGame() {
if (questions.some((question) => question.name === '')) {
alert('Please fill in the question for each question.');
return;
}
if (questions.some((question) => question.answers.some((answer) => answer === ''))) {
alert('Please fill in each of the options for each question.');
return;
}
if (questions.some((question) => question.correctAnswer === undefined)) {
alert('Please select a correct answer for each question.');
async function startGame() {
if (questions.some((q) => q.name === '')) return alert('Please fill all questions');
if (questions.some((q) => q.answers.some((a) => a === ''))) return alert('Fill all options');
if (questions.some((q) => q.correctAnswer === undefined))
return alert('Select correct answers');
const gamePin = Math.floor(Math.random() * 1000000)
.toString()
.padStart(6, '0');
const { error } = await supabase.from('games').insert({
gamePIN: gamePin,
gameStatus: 'lobby',
questions: questions,
players: []
});
if (error) {
alert('Failed to create game: ' + error.message + '\n\nPlease try again.');
return;
}
alert('Game started!');
goto('/host/' + gamePin);
}
</script>

View file

@ -0,0 +1,6 @@
// Example of what your +page.js or +page.server.js might need
export function load({ params }) {
return {
gamePin: params.gamePin
};
}

View file

@ -0,0 +1,78 @@
<script>
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { supabase } from '$lib/supabase';
export let data;
const gamePin = data.gamePin;
const name = $page.state?.name;
let players = [];
// Subscribe to realtime changes in players
function subscribeToPlayers() {
const channel = supabase
.channel(`game-${gamePin}`)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'games',
filter: `gamePIN=eq.${gamePin}`
},
(payload) => {
players = payload.new.players || [];
}
)
.subscribe();
}
onMount(async () => {
const { data: gameData } = await supabase
.from('games')
.select('players')
.eq('gamePIN', Number(gamePin))
.maybeSingle();
if (gameData?.players) {
players = gameData.players;
}
subscribeToPlayers();
});
</script>
<div class="bg-grey-900 flex h-full items-center justify-center">
<div
class="flex max-w-[700px] flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg"
>
<h1 class="m-[0] text-9xl">HOSTING</h1>
<h1 class="m-[0] text-7xl">Game Pin:</h1>
<h1 class="m-[0] rounded-2xl bg-gray-700 pt-1.5 pr-2 pb-0 pl-2 font-mono text-5xl">
{gamePin}
</h1>
<h1 class="m-[0] mt-10 text-6xl">Players Joined:</h1>
<h1 class="m-[0] text-4xl text-gray-400">(Total Players: {players.length})</h1>
<div class="mt-2 flex flex-wrap justify-center gap-2">
{#each players as player}
<span class="m-[0] rounded-xl bg-gray-700 pt-1 pr-2 pb-0 pl-2 font-mono text-3xl"
>{player.name}</span
>
{/each}
</div>
<button
class="mt-5 cursor-pointer rounded-2xl bg-green-700 p-2 text-4xl transition-all hover:scale-110 hover:-rotate-10"
on:click={() => {
if (players.length > 0) {
if (confirm('Are you sure you want to start the game?')) {
// Logic to start the game
alert('Game started!'); // Replace with actual game start logic
}
} else {
alert('You need at least one player to start the game.');
}
}}>Start the game</button
>
</div>
</div>

View file

@ -1,19 +1,72 @@
<script>
import { goto } from '$app/navigation';
import { supabase } from '$lib/supabase';
let pin;
let name;
let Checking = false;
async function validateGamePin() {
const { data, error } = await supabase
.from('games')
.select('gamePIN')
.eq('gamePIN', Number(pin))
.maybeSingle();
// Return true if valid
return data !== null && !error;
}
async function joinGame() {
if (!pin || !name) {
alert('Please fill in the game pin and your name.');
return;
}
Checking = true;
const isValid = await validateGamePin();
if (!isValid) {
alert('Invalid game pin. Please try again.');
Checking = false;
return;
}
goto('/play/' + pin, {
state: {
name
}
});
}
</script>
<div class="bg-grey-900 flex h-full items-center justify-center">
<div class="flex flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg">
<h1 class="m-[0] mb-3 text-5xl">Join a game here</h1>
<input placeholder="Enter game pin" class="rounded-lg bg-gray-800 p-2 text-center text-white" />
<input
placeholder="Enter game pin"
class="rounded-lg bg-gray-800 p-2 text-center text-white"
bind:value={pin}
/>
<input
placeholder="Enter your name"
bind:value={name}
class="rounded-lg bg-gray-800 p-2 text-center text-white"
/>
<button
class="cursor-pointer rounded-full bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
>Join the game</button
>
{#if !Checking}
<button
class="mt-4 cursor-pointer rounded-full bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
on:click={joinGame}
>
Join game
</button>
{:else}<button
class="mt-4 cursor-pointer rounded-full bg-gray-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
>
Checking if pin is valid...
</button>{/if}
</div>
</div>
</div>

View file

@ -0,0 +1,6 @@
// Example of what your +page.js or +page.server.js might need
export function load({ params }) {
return {
gamePin: params.gamePin
};
}

View file

@ -0,0 +1,87 @@
<script>
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { supabase } from '$lib/supabase';
export let data;
const gamePin = data.gamePin;
const name = $page.state?.name;
let players = [];
async function addPlayer() {
const { data: gameData, error } = await supabase
.from('games')
.select('players')
.eq('gamePIN', Number(gamePin))
.maybeSingle();
let updatedPlayers = gameData.players || [];
const alreadyExists = updatedPlayers.some((p) => p.name === name);
if (!alreadyExists) {
updatedPlayers.push({ name: name, score: 0 });
const { error: updateError } = await supabase
.from('games')
.update({ players: updatedPlayers })
.eq('gamePIN', Number(gamePin));
}
}
// Subscribe to realtime changes in players
function subscribeToPlayers() {
const channel = supabase
.channel(`game-${gamePin}`)
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'games',
filter: `gamePIN=eq.${gamePin}`
},
(payload) => {
players = payload.new.players || [];
}
)
.subscribe();
}
onMount(async () => {
await addPlayer();
const { data: gameData } = await supabase
.from('games')
.select('players')
.eq('gamePIN', Number(gamePin))
.maybeSingle();
if (gameData?.players) {
players = gameData.players;
}
subscribeToPlayers();
});
</script>
<div class="bg-grey-900 flex h-full items-center justify-center">
<div
class="flex max-w-[700px] flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg"
>
<h1 class="m-[0] text-9xl">PLAYING</h1>
<h1 class="m-[0] text-7xl">Game Pin:</h1>
<h1 class="m-[0] rounded-2xl bg-gray-700 pt-1.5 pr-2 pb-0 pl-2 font-mono text-5xl">
{gamePin}
</h1>
<h1 class="m-[0] mt-10 text-6xl">Players Joined:</h1>
<h1 class="m-[0] text-4xl text-gray-400">(Total Players: {players.length})</h1>
<div class="mt-2 flex flex-wrap justify-center gap-2">
{#each players as player}
<span class="m-[0] rounded-xl bg-gray-700 pt-1 pr-2 pb-0 pl-2 font-mono text-3xl"
>{player.name}</span
>
{/each}
</div>
</div>
</div>