made the loby working using the newer rDB and makeing everything to bbe better manageable by using folders and more components!
This commit is contained in:
parent
2b9b5c3b39
commit
d3e0f3406e
37 changed files with 417 additions and 159 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"useTabs": true,
|
"useTabs": true,
|
||||||
"singleQuote": false,
|
"singleQuote": true,
|
||||||
"trailingComma": "all",
|
"trailingComma": "none",
|
||||||
"printWidth": 100,
|
"printWidth": 100,
|
||||||
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
|
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
|
||||||
"overrides": [
|
"overrides": [
|
||||||
|
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -11,6 +11,8 @@
|
||||||
"gamepin",
|
"gamepin",
|
||||||
"hostgame",
|
"hostgame",
|
||||||
"kahoot",
|
"kahoot",
|
||||||
|
"kahootclone",
|
||||||
|
"Newplayers",
|
||||||
"playername",
|
"playername",
|
||||||
"questionid",
|
"questionid",
|
||||||
"questionstext",
|
"questionstext",
|
||||||
|
|
58
README.md
58
README.md
|
@ -16,30 +16,38 @@
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
erDiagram
|
erDiagram
|
||||||
GAMES {
|
GAMES {
|
||||||
int ID PK
|
int ID PK
|
||||||
string creator
|
string creator
|
||||||
date creationDate
|
date creationDate
|
||||||
string status
|
string status
|
||||||
}
|
}
|
||||||
QUESTIONS {
|
QUESTIONS {
|
||||||
int ID PK
|
int ID PK
|
||||||
int GameID FK
|
int GameID FK
|
||||||
string QuestionsText
|
string QuestionsText
|
||||||
string CorrectAnswer
|
string CorrectAnswer
|
||||||
}
|
}
|
||||||
ANSWERS {
|
ANSWERS {
|
||||||
int ID PK
|
int ID PK
|
||||||
int QuestionID FK
|
int QuestionID FK
|
||||||
string content
|
string content
|
||||||
}
|
}
|
||||||
PLAYERS {
|
ANSWEREDBY {
|
||||||
int ID PK
|
int ID PK
|
||||||
int GameID FK
|
int QuestionID FK
|
||||||
int Score
|
string NameOfAnswerer
|
||||||
}
|
}
|
||||||
|
PLAYERS {
|
||||||
|
int ID PK
|
||||||
|
int GameID FK
|
||||||
|
int Score
|
||||||
|
}
|
||||||
|
|
||||||
|
GAMES ||--o{ QUESTIONS : contains
|
||||||
|
QUESTIONS ||--o{ ANSWERS : has_answers
|
||||||
|
QUESTIONS ||--o{ ANSWEREDBY : has_answeredby
|
||||||
|
GAMES ||--o{ PLAYERS : has_players
|
||||||
|
|
||||||
|
|
||||||
GAMES ||--o{ QUESTIONS : contains
|
|
||||||
QUESTIONS ||--o{ ANSWERS : has
|
|
||||||
GAMES ||--o{ PLAYERS : participated_by
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"moduleResolution": "bundler"
|
"moduleResolution": "bundler","target": "es2015",
|
||||||
|
"module": "es2015",
|
||||||
|
"types": ["svelte"]
|
||||||
},
|
},
|
||||||
"exclude": [
|
"include": ["src/**/*"],
|
||||||
"node_modules"
|
"exclude": ["node_modules/*"],
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,7 @@
|
||||||
"@sveltejs/adapter-auto": "^4.0.0",
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
"@sveltejs/kit": "^2.16.0",
|
"@sveltejs/kit": "^2.16.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
"@tailwindcss/postcss": "^4.1.6",
|
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
"autoprefixer": "^10.4.21",
|
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"prettier-plugin-svelte": "^3.3.3",
|
"prettier-plugin-svelte": "^3.3.3",
|
||||||
|
@ -25,8 +23,5 @@
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"tailwindcss": "^4.0.0",
|
"tailwindcss": "^4.0.0",
|
||||||
"vite": "^6.0.0"
|
"vite": "^6.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@supabase/supabase-js": "^2.49.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
src/app.css
Normal file
1
src/app.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import 'tailwindcss';
|
|
@ -1,12 +1,12 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en" style="height: 100%; margin: 0">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover" style="height: 100%; margin: 0">
|
<body data-sveltekit-preload-data="hover">
|
||||||
<div style="display: contents; height: 100%">%sveltekit.body%</div>
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
|
import '../app.css';
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="h-full text-white">{@render children()}</div>
|
{@render children()}
|
||||||
|
|
||||||
<style>
|
|
||||||
@import 'tailwindcss';
|
|
||||||
|
|
||||||
:root {
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,18 +1,2 @@
|
||||||
<div class="bg-grey-900 flex h-full items-center justify-center">
|
<h1>Welcome to SvelteKit</h1>
|
||||||
<div class="flex flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg">
|
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
|
||||||
<h1 class="m-[0] text-6xl">DaKahootClone</h1>
|
|
||||||
<p class="m-[0] mb-2 text-lg text-gray-400">The best ever kahoot clone.</p>
|
|
||||||
<a href="./join">
|
|
||||||
<button
|
|
||||||
class="cursor-pointer rounded-full bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
|
|
||||||
>Join a game</button
|
|
||||||
></a
|
|
||||||
>
|
|
||||||
<a href="./create">
|
|
||||||
<button
|
|
||||||
class="cursor-pointer rounded-full bg-blue-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
|
|
||||||
>Create and Host a game</button
|
|
||||||
>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,46 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import PlayingDisplay from "./components/DuringGame/display.svelte";
|
||||||
import { page } from '$app/stores';
|
|
||||||
import { supabase } from '$lib/supabase';
|
import LobbyDisplay from "./components/lobby/display.svelte";
|
||||||
import { goto } from '$app/navigation';
|
import { Status } from "./logic/HostsData.svelte.js";
|
||||||
|
import { AutoUpdatePlayersList } from "./logic/UpdatePlayersList.js";
|
||||||
|
import { GetCurrentPlayers } from "./logic/GetCurrentPlayers.js";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
const gamePin = data.gamePin;
|
const gamePin = data.gamePin;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
let players = [];
|
GetCurrentPlayers(gamePin);
|
||||||
|
AutoUpdatePlayersList(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 () => {
|
|
||||||
const { data: gameData } = await supabase
|
|
||||||
.from('games')
|
|
||||||
.select('players')
|
|
||||||
.eq('gamePIN', Number(gamePin))
|
|
||||||
.maybeSingle();
|
|
||||||
|
|
||||||
if (gameData?.players) {
|
|
||||||
players = gameData.players;
|
|
||||||
}
|
|
||||||
|
|
||||||
subscribeToPlayers();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -48,35 +20,10 @@
|
||||||
<div
|
<div
|
||||||
class="flex max-w-[700px] flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg"
|
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>
|
{#if Status.v == "lobby"}
|
||||||
<h1 class="m-[0] text-7xl">Game Pin:</h1>
|
<LobbyDisplay {gamePin} />
|
||||||
<h1 class="m-[0] rounded-2xl bg-gray-700 pt-1.5 pr-2 pb-0 pl-2 font-mono text-5xl">
|
{:else if Status.v == "started"}
|
||||||
{gamePin}
|
<PlayingDisplay />
|
||||||
</h1>
|
{/if}
|
||||||
<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={async () => {
|
|
||||||
if (players.length > 0) {
|
|
||||||
if (confirm('Are you sure you want to start the game?')) {
|
|
||||||
await supabase
|
|
||||||
.from('games')
|
|
||||||
.update({ gameStatus: 'started' })
|
|
||||||
.eq('gamePIN', Number(data.gamePin));
|
|
||||||
goto(`/hostgame/${gamePin}`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert('You need at least one player to start the game.');
|
|
||||||
}
|
|
||||||
}}>Start the game</button
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import { PeopleAwnseredQ, Totalplayers } from "./../../logic/HostsData.svelte.js";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mt-1 mb-3 flex w-full flex-col rounded-2xl border-2 border-green-400 p-2">
|
||||||
|
<h3>{PeopleAwnseredQ.v} out of {Totalplayers.v} have awnsered the quetion</h3>
|
||||||
|
<div class="flex-1 rounded-full border-2 border-gray-600">
|
||||||
|
<div
|
||||||
|
class="h-4 rounded-full bg-green-600 transition-all duration-500"
|
||||||
|
style="width: {(PeopleAwnseredQ.v / Totalplayers.v) * 100}%;"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import { currentQuestion, totalQuetions } from "./../../logic/HostsData.svelte.js";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mt-1 mb-3 flex w-full flex-col rounded-2xl border-2 border-green-400 p-2">
|
||||||
|
<h3>Question {currentQuestion.v + 1} of {totalQuetions.v} is beeing awnsered</h3>
|
||||||
|
<div class="flex-1 rounded-full border-2 border-gray-600">
|
||||||
|
<div
|
||||||
|
class="h-4 rounded-full bg-green-600 transition-all duration-500"
|
||||||
|
style="width: {(currentQuestion.v + 1 / totalQuetions.v) * 100}%;"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import PeopleAwnsered from "./PeopleAwnsered.svelte";
|
||||||
|
import QuetionsAwnsred from "./QuetionsAwnsred.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1 class="m-[0] text-7xl">HOSTING</h1>
|
||||||
|
<QuetionsAwnsred />
|
||||||
|
<PeopleAwnsered />
|
|
@ -0,0 +1,6 @@
|
||||||
|
<script>
|
||||||
|
let props = $props();
|
||||||
|
let playerName = props.playerName;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span class="m-[0] rounded-xl bg-gray-700 pt-1 pr-2 pb-0 pl-2 font-mono text-3xl">{playerName}</span>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<script>
|
||||||
|
import { players } from "../../../logic/HostsData.svelte.js";
|
||||||
|
import PlayerBadge from "./playerBadge.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1 class="m-[0] mt-10 text-6xl">Players Joined:</h1>
|
||||||
|
<h1 class="m-[0] text-4xl text-gray-400">(Total Players: {players.v.length})</h1>
|
||||||
|
<div class="mt-2 flex flex-wrap justify-center gap-2">
|
||||||
|
{#each players.v as playerName}
|
||||||
|
<PlayerBadge {playerName} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<script>
|
||||||
|
import { startGame } from "../../../logic/startGame.js";
|
||||||
|
|
||||||
|
let props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="mt-5 cursor-pointer rounded-2xl bg-green-700 p-2 text-4xl transition-all hover:scale-110 hover:-rotate-10"
|
||||||
|
onclick={() => {
|
||||||
|
startGame(props.gamePin);
|
||||||
|
}}>Start the game</button
|
||||||
|
>
|
15
src/routes/host/[gamePin]/components/lobby/display.svelte
Normal file
15
src/routes/host/[gamePin]/components/lobby/display.svelte
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<script>
|
||||||
|
import StartGame from "./buttons/startGame.svelte";
|
||||||
|
import Players from "./PlayersGUI/players.svelte";
|
||||||
|
|
||||||
|
let props = $props();
|
||||||
|
let gamePin = props.gamePin;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<Players />
|
||||||
|
<StartGame {gamePin} />
|
18
src/routes/host/[gamePin]/logic/GetCurrentPlayers.js
Normal file
18
src/routes/host/[gamePin]/logic/GetCurrentPlayers.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { supabase } from "$lib/supabase.js";
|
||||||
|
import { players } from "./HostsData.svelte.js";
|
||||||
|
|
||||||
|
export async function GetCurrentPlayers(gamePin) {
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from("players")
|
||||||
|
.select("playername")
|
||||||
|
.eq("gameid", Number(gamePin));
|
||||||
|
|
||||||
|
console.log("Current players data:", JSON.stringify(data));
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Error fetching players:", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
players.v = data ? data.map(player => player.playername) : [];
|
||||||
|
}
|
9
src/routes/host/[gamePin]/logic/HostsData.svelte.js
Normal file
9
src/routes/host/[gamePin]/logic/HostsData.svelte.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
export let players = $state({ v: [] });
|
||||||
|
export let Status = $state({ v: "lobby" });
|
||||||
|
export let questions = $state({ v: [] });
|
||||||
|
export let CurrentQuestion = $state({ v: -1 });
|
||||||
|
|
||||||
|
export let currentQuestion = $state({ v: 0 });
|
||||||
|
export let totalQuetions = $state({ v: 3 });
|
||||||
|
export let PeopleAwnseredQ = $state({ v: 0 });
|
||||||
|
export let Totalplayers = $state({ v: 3 });
|
26
src/routes/host/[gamePin]/logic/UpdatePlayersList.js
Normal file
26
src/routes/host/[gamePin]/logic/UpdatePlayersList.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { supabase } from "$lib/supabase.js";
|
||||||
|
import { players } from "./HostsData.svelte.js";
|
||||||
|
|
||||||
|
export let LobbyConnection;
|
||||||
|
|
||||||
|
function onNewPlayer(Newplayers) {
|
||||||
|
players.v.push(Newplayers.playername);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AutoUpdatePlayersList(gamePin) {
|
||||||
|
LobbyConnection = supabase
|
||||||
|
.channel("players-realtime")
|
||||||
|
.on(
|
||||||
|
"postgres_changes",
|
||||||
|
{
|
||||||
|
event: "INSERT",
|
||||||
|
schema: "public",
|
||||||
|
table: "players",
|
||||||
|
filter: `gameid=eq.${gamePin}`,
|
||||||
|
},
|
||||||
|
(payload) => {
|
||||||
|
onNewPlayer(payload.new);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
}
|
25
src/routes/host/[gamePin]/logic/startGame.js
Normal file
25
src/routes/host/[gamePin]/logic/startGame.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { supabase } from "$lib/supabase.js";
|
||||||
|
import { LobbyConnection } from "./UpdatePlayersList.js";
|
||||||
|
import { questions, Status, CurrentQuestion, currentQuestion } from "./HostsData.svelte.js";
|
||||||
|
|
||||||
|
export async function startGame(gamePin) {
|
||||||
|
await supabase.removeChannel(LobbyConnection);
|
||||||
|
|
||||||
|
Status.v = "started";
|
||||||
|
|
||||||
|
const { data } = await supabase
|
||||||
|
.from("questions")
|
||||||
|
.select("*")
|
||||||
|
.eq("gameid", Number(gamePin))
|
||||||
|
.order("id", { ascending: true });
|
||||||
|
questions.v = data;
|
||||||
|
|
||||||
|
CurrentQuestion.v = 0;
|
||||||
|
|
||||||
|
await supabase
|
||||||
|
.from("games")
|
||||||
|
.update({ status: `question-${currentQuestion.v}` })
|
||||||
|
.eq("gamepin", gamePin);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,15 @@
|
||||||
<script>
|
<script>
|
||||||
import { joinGame } from './logic/joinGame.js';
|
import { joinGame } from "./logic/joinGame.js";
|
||||||
import { Checking } from './logic/JoinGameData.svelte.js';
|
import { Checking } from "./logic/JoinGameData.svelte.js";
|
||||||
|
|
||||||
let pin;
|
let pin;
|
||||||
let name;
|
let name;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="bg-grey-900 flex h-full items-center justify-center">
|
<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-7 shadow-lg">
|
<div
|
||||||
|
class="flex flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-7 shadow-lg"
|
||||||
|
>
|
||||||
<h1 class="m-[0] mb-3 text-5xl">Join a game here</h1>
|
<h1 class="m-[0] mb-3 text-5xl">Join a game here</h1>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
@ -29,13 +31,13 @@
|
||||||
Checking if pin is valid...
|
Checking if pin is valid...
|
||||||
</button>
|
</button>
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
<button
|
||||||
class="mt-2 cursor-pointer rounded-full bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
|
class="mt-2 cursor-pointer rounded-full bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (!pin || !name) {
|
if (!pin || !name) {
|
||||||
alert('Please fill in the game pin and your name.');
|
alert("Please fill in the game pin and your name.");
|
||||||
} else {
|
} else {
|
||||||
joinGame();
|
joinGame(pin, name);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from "$app/navigation";
|
||||||
import { addPlayer } from './InsertPlayerInDB.js';
|
import { addPlayer } from "./InsertPlayerInDB.js";
|
||||||
import { validateGamePin } from './validateGamePin.js';
|
import { validateGamePin } from "./validateGamePin.js";
|
||||||
import { Checking} from "./JoinGameData.svelte.js"
|
import { Checking } from "./JoinGameData.svelte.js";
|
||||||
|
|
||||||
export async function joinGame(pin, name) {
|
export async function joinGame(pin, name) {
|
||||||
Checking.v = true;
|
Checking.v = true;
|
||||||
|
|
||||||
if (!(await validateGamePin())) {
|
if (!(await validateGamePin(pin))) {
|
||||||
alert('Invalid game pin. Please try again.');
|
alert("Invalid game pin. Please try again.");
|
||||||
Checking.v = false;
|
Checking.v = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
addPlayer(name, pin);
|
addPlayer(name, pin);
|
||||||
|
|
||||||
|
Checking.v = false;
|
||||||
|
|
||||||
goto('/play/' + pin, {
|
goto("/play/" + pin, {
|
||||||
state: { name }
|
state: { name },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,4 @@ export function load({ params }) {
|
||||||
return {
|
return {
|
||||||
gamePin: params.gamePin
|
gamePin: params.gamePin
|
||||||
};
|
};
|
||||||
}
|
}
|
29
src/routes/play/[gamePin]/+page.svelte
Normal file
29
src/routes/play/[gamePin]/+page.svelte
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<script>
|
||||||
|
import PlayingDisplay from "./components/DuringGame/display.svelte";
|
||||||
|
|
||||||
|
import LobbyDisplay from "./components/lobby/display.svelte";
|
||||||
|
import { Status } from "./logic/HostsData.svelte.js";
|
||||||
|
import { AutoUpdatePlayersList } from "./logic/UpdatePlayersList.js";
|
||||||
|
import { GetCurrentPlayers } from "./logic/GetCurrentPlayers.js";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
const gamePin = data.gamePin;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
GetCurrentPlayers(gamePin);
|
||||||
|
AutoUpdatePlayersList(gamePin);
|
||||||
|
});
|
||||||
|
</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"
|
||||||
|
>
|
||||||
|
{#if Status.v == "lobby"}
|
||||||
|
<LobbyDisplay {gamePin} />
|
||||||
|
{:else if Status.v == "started"}
|
||||||
|
<PlayingDisplay />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import { PeopleAwnseredQ, Totalplayers } from "./../../logic/HostsData.svelte.js";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mt-1 mb-3 flex w-full flex-col rounded-2xl border-2 border-green-400 p-2">
|
||||||
|
<h3>{PeopleAwnseredQ.v} out of {Totalplayers.v} have awnsered the quetion</h3>
|
||||||
|
<div class="flex-1 rounded-full border-2 border-gray-600">
|
||||||
|
<div
|
||||||
|
class="h-4 rounded-full bg-green-600 transition-all duration-500"
|
||||||
|
style="width: {(PeopleAwnseredQ.v / Totalplayers.v) * 100}%;"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import { currentQuestion, totalQuetions } from "./../../logic/HostsData.svelte.js";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mt-1 mb-3 flex w-full flex-col rounded-2xl border-2 border-green-400 p-2">
|
||||||
|
<h3>Question {currentQuestion.v + 1} of {totalQuetions.v} is beeing awnsered</h3>
|
||||||
|
<div class="flex-1 rounded-full border-2 border-gray-600">
|
||||||
|
<div
|
||||||
|
class="h-4 rounded-full bg-green-600 transition-all duration-500"
|
||||||
|
style="width: {(currentQuestion.v + 1 / totalQuetions.v) * 100}%;"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import PeopleAwnsered from "./PeopleAwnsered.svelte";
|
||||||
|
import QuetionsAwnsred from "./QuetionsAwnsred.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1 class="m-[0] text-7xl">HOSTING</h1>
|
||||||
|
<QuetionsAwnsred />
|
||||||
|
<PeopleAwnsered />
|
|
@ -0,0 +1,6 @@
|
||||||
|
<script>
|
||||||
|
let props = $props();
|
||||||
|
let playerName = props.playerName;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span class="m-[0] rounded-xl bg-gray-700 pt-1 pr-2 pb-0 pl-2 font-mono text-3xl">{playerName}</span>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<script>
|
||||||
|
import { players } from "../../../logic/HostsData.svelte.js";
|
||||||
|
import PlayerBadge from "./playerBadge.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1 class="m-[0] mt-10 text-6xl">Players Joined:</h1>
|
||||||
|
<h1 class="m-[0] text-4xl text-gray-400">(Total Players: {players.v.length})</h1>
|
||||||
|
<div class="mt-2 flex flex-wrap justify-center gap-2">
|
||||||
|
{#each players.v as playerName}
|
||||||
|
<PlayerBadge {playerName} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
13
src/routes/play/[gamePin]/components/lobby/display.svelte
Normal file
13
src/routes/play/[gamePin]/components/lobby/display.svelte
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import Players from "./PlayersGUI/players.svelte";
|
||||||
|
|
||||||
|
let props = $props();
|
||||||
|
let gamePin = props.gamePin;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<Players />
|
18
src/routes/play/[gamePin]/logic/GetCurrentPlayers.js
Normal file
18
src/routes/play/[gamePin]/logic/GetCurrentPlayers.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { supabase } from "$lib/supabase.js";
|
||||||
|
import { players } from "./HostsData.svelte.js";
|
||||||
|
|
||||||
|
export async function GetCurrentPlayers(gamePin) {
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from("players")
|
||||||
|
.select("playername")
|
||||||
|
.eq("gameid", Number(gamePin));
|
||||||
|
|
||||||
|
console.log("Current players data:", JSON.stringify(data));
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Error fetching players:", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
players.v = data ? data.map(player => player.playername) : [];
|
||||||
|
}
|
9
src/routes/play/[gamePin]/logic/HostsData.svelte.js
Normal file
9
src/routes/play/[gamePin]/logic/HostsData.svelte.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
export let players = $state({ v: [] });
|
||||||
|
export let Status = $state({ v: "lobby" });
|
||||||
|
export let questions = $state({ v: [] });
|
||||||
|
export let CurrentQuestion = $state({ v: -1 });
|
||||||
|
|
||||||
|
export let currentQuestion = $state({ v: 0 });
|
||||||
|
export let totalQuetions = $state({ v: 3 });
|
||||||
|
export let PeopleAwnseredQ = $state({ v: 0 });
|
||||||
|
export let Totalplayers = $state({ v: 3 });
|
26
src/routes/play/[gamePin]/logic/UpdatePlayersList.js
Normal file
26
src/routes/play/[gamePin]/logic/UpdatePlayersList.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { supabase } from "$lib/supabase.js";
|
||||||
|
import { players } from "./HostsData.svelte.js";
|
||||||
|
|
||||||
|
export let LobbyConnection;
|
||||||
|
|
||||||
|
function onNewPlayer(Newplayers) {
|
||||||
|
players.v.push(Newplayers.playername);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AutoUpdatePlayersList(gamePin) {
|
||||||
|
LobbyConnection = supabase
|
||||||
|
.channel("players-realtime")
|
||||||
|
.on(
|
||||||
|
"postgres_changes",
|
||||||
|
{
|
||||||
|
event: "INSERT",
|
||||||
|
schema: "public",
|
||||||
|
table: "players",
|
||||||
|
filter: `gameid=eq.${gamePin}`,
|
||||||
|
},
|
||||||
|
(payload) => {
|
||||||
|
onNewPlayer(payload.new);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
}
|
25
src/routes/play/[gamePin]/logic/startGame.js
Normal file
25
src/routes/play/[gamePin]/logic/startGame.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { supabase } from "$lib/supabase.js";
|
||||||
|
import { LobbyConnection } from "./UpdatePlayersList.js";
|
||||||
|
import { questions, Status, CurrentQuestion, currentQuestion } from "./HostsData.svelte.js";
|
||||||
|
|
||||||
|
export async function startGame(gamePin) {
|
||||||
|
await supabase.removeChannel(LobbyConnection);
|
||||||
|
|
||||||
|
Status.v = "started";
|
||||||
|
|
||||||
|
const { data } = await supabase
|
||||||
|
.from("questions")
|
||||||
|
.select("*")
|
||||||
|
.eq("gameid", Number(gamePin))
|
||||||
|
.order("id", { ascending: true });
|
||||||
|
questions.v = data;
|
||||||
|
|
||||||
|
CurrentQuestion.v = 0;
|
||||||
|
|
||||||
|
await supabase
|
||||||
|
.from("games")
|
||||||
|
.update({ status: `question-${currentQuestion.v}` })
|
||||||
|
.eq("gamepin", gamePin);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -7,15 +7,7 @@ const config = {
|
||||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||||
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
||||||
adapter: adapter()
|
adapter: adapter()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue