hardcoded new ui, will now make it funtional

This commit is contained in:
RezHackXYZ 2025-06-02 10:32:09 +05:30
parent 6ac4dad9fa
commit d5d99c6f4f
21 changed files with 225 additions and 507 deletions

View file

@ -1,28 +1,12 @@
<script>
import UseDemoQuestions from "./components/buttons/UseDemoQuestions.svelte";
import NewQuestion from "./components/buttons/NewQuestion.svelte";
import StartGame from "./components/buttons/StartGame.svelte";
import Question from "./components/Questions/question.svelte";
import { questions, Wait } from "./logic/GameCreateData.svelte.js";
import WaitStartGame from "./components/buttons/WaitStartGame.svelte";
import GenerateQuetionsUsingAi from "./components/buttons/GenerateQuetionsUsingAI.svelte";
import HowTheQuestionWillLook from "./HowTheQuestionWillLook.svelte";
import QuestionsList from "./QuestionsList.svelte";
import QuestionOptions from "./QuestionOptions.svelte";
import Buttons from "./Buttons.svelte";
</script>
<div class="bg-grey-900 flex justify-center p-5">
<div
class="flex flex-col items-center justify-center gap-1 rounded-lg bg-gray-900 p-8 shadow-lg"
>
<div class="flex gap-3"><UseDemoQuestions /> <GenerateQuetionsUsingAi /></div>
{#each questions.v as question, index}
<Question {index} />
{/each}
<div class="flex gap-3">
<NewQuestion />
{#if Wait.v == false}
<StartGame />
{:else}
<WaitStartGame />
{/if}
</div>
</div>
<div class="flex h-full justify-between">
<QuestionsList />
<div class="flex h-full w-[54%] flex-col gap-2"><HowTheQuestionWillLook /><Buttons /></div>
<QuestionOptions />
</div>

View file

@ -0,0 +1,11 @@
<div class="flex w-full justify-center gap-2 overflow-y-auto rounded border-2 p-3 pr-5">
<button class="btn flex items-center gap-1">
<i class="nf nf-md-flash"></i> Use Demo Questions
</button>
<button class="btn flex items-center gap-1">
<i class="nf nf-md-cpu_64_bit"></i> Generate Questions Using AI
</button>
<button class="btn flex items-center gap-1">
<i class="nf nf-md-play"></i> Start Game
</button>
</div>

View file

@ -0,0 +1,97 @@
<script>
import { AnswersSymbolAndColorScheme } from "$lib/config.js";
</script>
<div class="flex h-full w-full flex-col gap-2 overflow-y-auto rounded border-2 p-3 pr-5">
<h1 class="text-4xl">How it will look</h1>
<div class="grid h-full place-items-center">
<div class="card w-4/5">
<h1 class="flex flex-col text-3xl">
<span class="text-5xl">1.</span>What is the capital of France?
</h1>
<div class="mt-5 grid grid-cols-2 gap-5 gap-x-3">
<div class="flex">
<input type="radio" id="O{0}" name="question" class="peer sr-only" value={0} />
<label
for="O{1}"
style="
--border-color: {AnswersSymbolAndColorScheme[0].Color};
--bg-color: {AnswersSymbolAndColorScheme[0].Color};
--border-color-checked: {AnswersSymbolAndColorScheme[0].SelectedColor};
--bg-color-checked: {AnswersSymbolAndColorScheme[0].SelectedColor};
--border-color-hover: {AnswersSymbolAndColorScheme[0].HoverBorderColor};
--border-color-checked: {AnswersSymbolAndColorScheme[0].SelectedBorderColor};
--border-color-hover: {AnswersSymbolAndColorScheme[0].HoverBorderColor};
"
class="w-full cursor-pointer rounded-lg border-[5px] border-[var(--border-color)] bg-[var(--bg-color)] pt-1 pr-2 pb-1 pl-2 text-center text-3xl transition-all peer-checked:border-[var(--border-color-checked)] peer-checked:bg-[var(--bg-color-checked)] hover:border-[var(--border-color-hover)]"
>
<i class="nf {AnswersSymbolAndColorScheme[0].Symbol}"></i>
answer 1
</label>
</div>
<div class="flex">
<input type="radio" id="O{1}" name="question" class="peer sr-only" value={1} />
<label
for="O{1}"
style="
--border-color: {AnswersSymbolAndColorScheme[1].Color};
--bg-color: {AnswersSymbolAndColorScheme[1].Color};
--border-color-checked: {AnswersSymbolAndColorScheme[1].SelectedColor};
--bg-color-checked: {AnswersSymbolAndColorScheme[1].SelectedColor};
--border-color-hover: {AnswersSymbolAndColorScheme[1].HoverBorderColor};
--border-color-checked: {AnswersSymbolAndColorScheme[1].SelectedBorderColor};
--border-color-hover: {AnswersSymbolAndColorScheme[1].HoverBorderColor};
"
class="w-full cursor-pointer rounded-lg border-[5px] border-[var(--border-color)] bg-[var(--bg-color)] pt-1 pr-2 pb-1 pl-2 text-center text-3xl transition-all peer-checked:border-[var(--border-color-checked)] peer-checked:bg-[var(--bg-color-checked)] hover:border-[var(--border-color-hover)]"
>
<i class="nf {AnswersSymbolAndColorScheme[1].Symbol}"></i>
answer 2
</label>
</div>
<div class="flex">
<input type="radio" id="O{2}" name="question" class="peer sr-only" value={2} />
<label
for="O{1}"
style="
--border-color: {AnswersSymbolAndColorScheme[2].Color};
--bg-color: {AnswersSymbolAndColorScheme[2].Color};
--border-color-checked: {AnswersSymbolAndColorScheme[2].SelectedColor};
--bg-color-checked: {AnswersSymbolAndColorScheme[2].SelectedColor};
--border-color-hover: {AnswersSymbolAndColorScheme[2].HoverBorderColor};
--border-color-checked: {AnswersSymbolAndColorScheme[2].SelectedBorderColor};
--border-color-hover: {AnswersSymbolAndColorScheme[2].HoverBorderColor};
"
class="w-full cursor-pointer rounded-lg border-[5px] border-[var(--border-color)] bg-[var(--bg-color)] pt-1 pr-2 pb-1 pl-2 text-center text-3xl transition-all peer-checked:border-[var(--border-color-checked)] peer-checked:bg-[var(--bg-color-checked)] hover:border-[var(--border-color-hover)]"
>
<i class="nf {AnswersSymbolAndColorScheme[2].Symbol}"></i>
answer 3
</label>
</div>
<div class="flex">
<input type="radio" id="O{3}" name="question" class="peer sr-only" value={3} />
<label
for="O{1}"
style="
--border-color: {AnswersSymbolAndColorScheme[3].Color};
--bg-color: {AnswersSymbolAndColorScheme[3].Color};
--border-color-checked: {AnswersSymbolAndColorScheme[3].SelectedColor};
--bg-color-checked: {AnswersSymbolAndColorScheme[3].SelectedColor};
--border-color-hover: {AnswersSymbolAndColorScheme[3].HoverBorderColor};
--border-color-checked: {AnswersSymbolAndColorScheme[3].SelectedBorderColor};
--border-color-hover: {AnswersSymbolAndColorScheme[3].HoverBorderColor};
"
class="w-full cursor-pointer rounded-lg border-[5px] border-[var(--border-color)] bg-[var(--bg-color)] pt-1 pr-2 pb-1 pl-2 text-center text-3xl transition-all peer-checked:border-[var(--border-color-checked)] peer-checked:bg-[var(--bg-color-checked)] hover:border-[var(--border-color-hover)]"
>
<i class="nf {AnswersSymbolAndColorScheme[3].Symbol}"></i>
answer 4
</label>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,80 @@
<div
class="flex h-full w-[30%] flex-col justify-between gap-2 overflow-y-auto rounded-l border-2 p-3 pr-5"
>
<div>
<h1 class="text-4xl">Options</h1>
<div class="mt-4">
<label for="QuetionText" class="text-lg leading-0.5 text-gray-500">What the Question?</label>
<input
type="text"
id="QuetionText"
placeholder="Whats the capital of france?"
class="input mt-1"
/>
</div>
<div class="mt-3">
<label for="TimeLimit" class="text-lg leading-0.5 text-gray-500">Time limit?</label>
<select name="TimeLimit" id="TimeLimit" class="input mt-1">
<option value={null}>infinite</option>
<option value={5}>5 sec</option>
<option value={10}>10 sec</option>
<option selected value={15}>15 sec</option>
<option value={30}>30 sec</option>
<option value={60}>1 min</option>
<option value={120}>2 min</option>
<option value={300}>5 min</option>
</select>
</div>
<div class="mt-3">
<label for="QuestionType" class="text-lg leading-0.5 text-gray-500">Question type?</label>
<select name="QuestionType" id="QuestionType" class="input mt-1">
<option selected value="SingleAnswer">Single Answer</option>
</select>
</div>
<div class="mt-3">
{#if "SingleAnswer" === "SingleAnswer"}
<span class="text-lg leading-0.5 text-gray-500">Options</span>
<div class="mt-1 grid grid-cols-1 gap-2">
<div class="flex items-center gap-2">
<input type="radio" name="options" class="ratio" />
<input type="text" placeholder="Option 1" class="input w-1/3" />
<button class="btn slim dull" aria-label="Delete Option">
<i class="nf nf-md-delete"></i>
</button>
</div>
</div>
<div class="mt-1 grid grid-cols-1 gap-2">
<div class="flex items-center gap-2">
<input type="radio" name="options" class="ratio" />
<input type="text" placeholder="Option 2" class="input w-1/3" />
<button class="btn slim dull" aria-label="Delete Option">
<i class="nf nf-md-delete"></i>
</button>
</div>
</div>
<div class="mt-1 grid grid-cols-1 gap-2">
<div class="flex items-center gap-2">
<input type="radio" name="options" class="ratio" />
<input type="text" placeholder="Option 3" class="input w-1/3" />
<button class="btn slim dull" aria-label="Delete Option">
<i class="nf nf-md-delete"></i>
</button>
</div>
</div>
<div class="flex justify-center">
<button class="btn dull mt-2 w-fit">Add Option</button>
</div>
{/if}
</div>
</div>
<div>
<div class="mt-4">
<label for="QuetionText" class="text-lg leading-0.5 text-gray-500">Danger</label>
<button class="btn mt-1 dull w-full" >delete this question</button>
</div>
</div>
</div>

View file

@ -0,0 +1,13 @@
<script>
let questions = ["Question 1", "Question 2", "Question 3"];
</script>
<div class="flex h-full w-[15%] flex-col gap-2 overflow-y-auto rounded-r border-2 p-3 pr-5">
<h1 class="text-4xl">Questions</h1>
{#each questions as questions, questionIndex}
<div class="card flex flex-col">
<span class="text-3xl">{questionIndex + 1}.</span><span>{questions}</span>
</div>
{/each}
<div class="flex justify-center mt-2"><button class="btn"><i class="nf nf-oct-diff_added"></i> New Question</button></div>
</div>

View file

@ -1,23 +0,0 @@
<script>
import { questions } from '../../logic/GameCreateData.svelte.js';
let props = $props();
let questionsIndex = props.questionsIndex;
let index = props.answersIndex;
</script>
<div class="flex items-center gap-2">
<input
type="radio"
value={index}
name={index.toString()}
bind:group={questions.v[questionsIndex].correctAnswer}
class="input"
/>
<input
placeholder="Option {index + 1}"
bind:value={questions.v[questionsIndex].answers[index]}
class="w-[500px] rounded-lg bg-gray-800 p-1 text-center text-white"
/>
</div>

View file

@ -1,79 +0,0 @@
<script>
import DeleteQuestion from "../buttons/DeleteQuestion.svelte";
import GenerateOptionsUsingAI from "../buttons/GenerateOptionsUsingAI.svelte";
import Answers from "./answers.svelte";
import { questions } from "../../logic/GameCreateData.svelte.js";
import { UpLoadFiles } from "../../logic/UpLoadFiles.js";
let props = $props();
let index = props.index;
let files = $state();
</script>
<div class="flex items-center gap-3">
<div class="mb-3 flex flex-col items-center justify-center gap-1 rounded-2xl bg-gray-600 p-2">
<div class="flex h-fit items-center gap-3">
<h1 class="mt-2 mb-3 text-2xl">Q{index + 1}.</h1>
<input
type="text"
bind:value={questions.v[index].name}
placeholder="Question {index + 1}"
class="h-fit w-[500px] rounded-xl bg-gray-800 p-1 text-center text-2xl text-white"
/>
<select
bind:value={questions.v[index].answers.length}
onchange={(e) => {
const newLength = questions.v[index].answers.length;
const currentAnswers = questions.v[index].answers;
if (newLength > currentAnswers.length) {
// Add more answers
while (questions.v[index].answers.length < newLength) {
questions.v[index].answers.push("");
}
} else if (newLength < currentAnswers.length) {
// Remove excess answers
questions.v[index].answers = currentAnswers.slice(0, newLength);
}
}}
class="h-fit rounded-xl bg-gray-800 p-1 text-center text-white"
>
<option disabled selected>Options</option>
{#each Array(7) as _, i}
<option value={i + 2}>{i + 2}</option>
{/each}
</select>
<select
bind:value={questions.v[index].timeLimit}
class="h-fit rounded-xl bg-gray-800 p-1 text-center text-white"
>
<option disabled selected>Time Limit</option>
<option value={null}>infinite</option>
<option value={5}>5 sec</option>
<option value={10}>10 sec</option>
<option value={15}>15 sec</option>
<option value={30}>30 sec</option>
<option value={60}>1 min</option>
<option value={120}>2 min</option>
<option value={300}>5 min</option>
</select>
<DeleteQuestion {index} />
</div>
<div class="flex flex-col gap-2">
{#each questions.v[index].answers as _, answersIndex}
<Answers questionsIndex={index} {answersIndex} />
{/each}
</div>
<GenerateOptionsUsingAI {index} />
<input
type="file"
onchange={async () => {
questions.v[index].media = await UpLoadFiles(files[0]);
}}
bind:files
accept="image/*,video/*"
/>
</div>
</div>

View file

@ -1,20 +0,0 @@
<script>
import { DeleteQuestion } from '../../logic/GameCreateData.svelte.js';
let props = $props();
</script>
<button
onclick={() => DeleteQuestion(props.index)}
class="flex h-fit cursor-pointer items-center justify-center rounded-xl bg-red-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"
/></svg
>Delete question</button
>

View file

@ -1,19 +0,0 @@
<script>
import { GenerateOptionsUsingAI } from "../../logic/GenerateOptionsUsingAI.js";
import { questions } from "../../logic/GameCreateData.svelte.js";
let props = $props();
let index = props.index;
</script>
{#if questions.v[index].answers.every((answer) => answer === "")}
<button
onclick={() => {
GenerateOptionsUsingAI(index);
}}
class="mt-1 mb-1 flex h-fit cursor-pointer items-center justify-center gap-2 rounded-xl bg-blue-700 p-2 transition-all hover:scale-110 hover:-rotate-5"
>
<i class="nf nf-cod-sparkle"></i>
Generate Options using AI
</button>
{/if}

View file

@ -1,14 +0,0 @@
<script>
import { GenerateQuestionsUsingAI } from "../../logic/GenerateQuestionsUsingAI.js";
import { questions } from "../../logic/GameCreateData.svelte.js";
</script>
{#if questions.v.length === 0 || (questions.v.length === 1 && questions.v[0].name === "" && questions.v[0].answers.every((answer) => answer === "") && questions.v[0].correctAnswer === undefined)}
<button
onclick={GenerateQuestionsUsingAI}
class="-mt-5 mb-3 flex h-fit cursor-pointer items-center justify-center gap-2 rounded-xl bg-blue-700 p-2 transition-all hover:scale-110 hover:-rotate-5"
>
<i class="nf nf-cod-sparkle"></i>
Generate questions using AI
</button>
{/if}

View file

@ -1,15 +0,0 @@
<script>
import { AddQuestion } from '../../logic/GameCreateData.svelte.js';
</script>
<button
onclick={() => AddQuestion()}
class="flex h-fit cursor-pointer items-center justify-center rounded-xl bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" /></svg
>New question</button
>

View file

@ -1,18 +0,0 @@
<script>
import { startGame } from '../../logic/StartGame.js';
</script>
<button
onclick={startGame}
class="flex h-fit cursor-pointer items-center justify-center gap-1 rounded-xl bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M560-360q17 0 29.5-12.5T602-402q0-17-12.5-29.5T560-444q-17 0-29.5 12.5T518-402q0 17 12.5 29.5T560-360Zm-30-128h60q0-29 6-42.5t28-35.5q30-30 40-48.5t10-43.5q0-45-31.5-73.5T560-760q-41 0-71.5 23T446-676l54 22q9-25 24.5-37.5T560-704q24 0 39 13.5t15 36.5q0 14-8 26.5T578-596q-33 29-40.5 45.5T530-488ZM320-240q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z"
/></svg
>Start Quiz</button
>

View file

@ -1,15 +0,0 @@
<script>
import { SetQuestionsToDemoQuestions } from '../../logic/GameCreateData.svelte.js';
</script>
<button
onclick={() => SetQuestionsToDemoQuestions()}
class="-mt-5 mb-3 flex h-fit cursor-pointer items-center justify-center rounded-xl bg-green-700 p-2 transition-all hover:scale-110 hover:-rotate-10"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" /></svg
>Use demo questions</button
>

View file

@ -1,18 +0,0 @@
<script>
import { startGame } from "../../logic/StartGame.js";
</script>
<button
onclick={startGame}
class="flex h-fit cursor-pointer items-center justify-center gap-1 rounded-xl bg-gray-700 p-2 transition-all hover:scale-110"
><svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 -960 960 960"
width="24px"
fill="#FFFFFF"
><path
d="M560-360q17 0 29.5-12.5T602-402q0-17-12.5-29.5T560-444q-17 0-29.5 12.5T518-402q0 17 12.5 29.5T560-360Zm-30-128h60q0-29 6-42.5t28-35.5q30-30 40-48.5t10-43.5q0-45-31.5-73.5T560-760q-41 0-71.5 23T446-676l54 22q9-25 24.5-37.5T560-704q24 0 39 13.5t15 36.5q0 14-8 26.5T578-596q-33 29-40.5 45.5T530-488ZM320-240q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z"
/></svg
>Wait for game to be created</button
>

View file

@ -1,38 +0,0 @@
import { DefaultQuestions } from "$lib/config.js";
import toast from "svelte-5-french-toast";
export let Wait = $state({ v: false });
export let questions = $state({
v: [
{
name: "",
answers: ["", "", "", ""],
correctAnswer: undefined,
timeLimit: 30,
},
],
});
export function SetQuestionsToDemoQuestions() {
questions.v = DefaultQuestions;
}
export function AddQuestion() {
questions.v.push({
name: "",
answers: ["", "", "", ""],
correctAnswer: undefined,
timeLimit: 30,
});
}
export function DeleteQuestion(index) {
if (questions.v.length > 1) {
if (confirm("Are you sure you want to delete this question? You cant undo this.")) {
questions.v.splice(index, 1);
}
} else {
toast.error("You need at least one question.");
}
}

View file

@ -1,43 +0,0 @@
import { questions } from "./GameCreateData.svelte.js";
import { AiPrompts } from "$lib/config.js";
import toast from "svelte-5-french-toast";
export function GenerateOptionsUsingAI(index) {
if (!questions.v[index].name) {
toast.error("Please enter a question to generate options.");
return;
}
const fetchOptions = async () => {
const response = await fetch("https://ai.hackclub.com/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
messages: [
{
role: "user",
content: AiPrompts.GenerateOptionsUsingAI.replace(
"[question]",
questions.v[index].name,
),
},
],
}),
});
const data = await response.json();
let question = questions.v[index].name;
questions.v[index] = JSON.parse(data.choices[0].message.content);
questions.v[index].name = question;
};
toast.promise(
fetchOptions(),
{
loading: "Generating options...",
success: "Options generated!",
error: (err) => "Error: " + (err?.message || err),
}
);
}

View file

@ -1,41 +0,0 @@
import { questions } from "./GameCreateData.svelte.js";
import { AiPrompts } from "$lib/config.js";
import toast from "svelte-5-french-toast";
export function GenerateQuestionsUsingAI() {
let topic = window.prompt(
"What is the topic of the questions?\nand the number of questions in the topic?",
);
if (!topic) {
return;
}
const fetchQuestions = async () => {
const response = await fetch("https://ai.hackclub.com/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
messages: [
{
role: "user",
content: AiPrompts.GenerateQuestionsUsingAI.replace("[topic]", topic),
},
],
}),
});
const data = await response.json();
questions.v = JSON.parse(data.choices[0].message.content);
};
toast.promise(
fetchQuestions(),
{
loading: "Generating questions...",
success: "Questions added!",
error: (err) => "Error: " + err.message || err,
}
);
}

View file

@ -1,80 +0,0 @@
import { supabase } from "$lib/supabase";
import toast from "svelte-5-french-toast";
import { Wait } from "./GameCreateData.svelte.js";
export async function createGame(questions, gamePin) {
// Insert game
const insertGamePromise = supabase.from("games").insert({
creator: "anonymous",
creationdate: new Date().toISOString(),
status: "lobby",
gamepin: gamePin,
});
const { data: gameData, error: gameError } = await toast.promise(insertGamePromise, {
loading: "Creating game...",
success: "Game created!",
error: (err) =>
"Failed to create game: " + (err?.message || "Unknown error") + "\n\nPlease try again.",
});
if (gameError) {
Wait.v = false;
return;
}
// Prepare questions and answers for batch insertion
const questionsData = questions.map((q) => ({
gameid: gamePin,
questionstext: q.name,
correctanswer: q.correctAnswer,
timelimit: q.timeLimit,
media: q.media || null,
}));
const insertQuestionsPromise = supabase.from("questions").insert(questionsData).select("id");
const { data: questionsResult, error: questionsError } = await toast.promise(
insertQuestionsPromise,
{
loading: "Inserting questions...",
success: "Questions inserted!",
error: (err) =>
"Failed to insert questions: " +
(err?.message || "Unknown error") +
"\n\nPlease try again.",
},
);
if (questionsError) {
Wait.v = false;
return;
}
const answersData = [];
questionsResult.forEach((question, index) => {
questions[index].answers.forEach((answer) => {
answersData.push({
questionid: question.id,
content: answer,
});
});
});
const insertAnswersPromise = supabase.from("answers").insert(answersData);
const { error: answersError } = await toast.promise(insertAnswersPromise, {
loading: "Inserting answers...",
success: "Answers inserted!",
error: (err) =>
"Failed to insert answers: " + (err?.message || "Unknown error") + "\n\nPlease try again.",
});
if (answersError) {
Wait.v = false
return;
}
window.location.href = `/kahootclone/host?gamepin=${gamePin}`;
}

View file

@ -1,17 +0,0 @@
import { createGame } from "./InsertGameInDB.js";
import { questions,Wait } from "./GameCreateData.svelte.js";
import toast from "svelte-5-french-toast";
export async function startGame() {
if (questions.v.some((q) => q.name === "")) return toast.error("Please fill all questions");
if (questions.v.some((q) => q.answers.some((a) => a === ""))) return toast.error("Fill all options");
if (questions.v.some((q) => q.correctAnswer === undefined))
return toast.error("Select correct answers");
const gamePin = Math.floor(Math.random() * 1000000)
.toString()
.padStart(6, "0");
Wait.v = true;
await createGame(questions.v, gamePin);}

View file

@ -1,31 +0,0 @@
import toast from "svelte-5-french-toast";
import { supabase } from "$lib/supabase.js";
export async function UpLoadFiles(file) {
if (!file) {
toast.error("Please select a file to upload first.");
return;
}
const fileExt = file.name.split(".").pop();
const fileName = `${Date.now()}.${fileExt}`;
const filePath = `${fileName}`;
const uploadPromise = supabase.storage.from("useruploadedcontent").upload(filePath, file);
const result = await toast.promise(uploadPromise, {
loading: "Uploading...",
success: "Upload successful!",
error: (error) => `Upload failed. ${error.message} Please try again.`,
});
if (result.error) {
toast.error("Upload error:"+ result.error.message);
return;
}
// Retrieve public URL
const { data: publicData } = supabase.storage.from("useruploadedcontent").getPublicUrl(filePath);
return publicData.publicUrl;
}

View file

@ -7,28 +7,32 @@
}
.btn {
@apply flex cursor-pointer items-center gap-1 rounded border-2 border-white bg-gray-600 px-4 py-2 font-bold text-white transition-all hover:scale-105 hover:bg-gray-500 hover:shadow-lg;
&.compact {
@apply px-1 py-0.5;
}
&.circular {
@apply rounded-full;
&.compact {
@apply px-0.75 py-0.75;
}
}
@apply flex cursor-pointer items-center gap-1 rounded border-2 border-white bg-gray-700 px-4 py-2 font-bold text-white transition-all hover:scale-105 hover:bg-gray-500 hover:shadow-lg;
&.dull {
@apply border-gray-700 bg-transparent text-gray-700 hover:bg-gray-700 hover:text-white;
}
&.slim {
@apply px-1 py-3;
}
&.green {
@apply bg-green-600 hover:bg-green-500;
}
&.red {
@apply bg-red-600 hover:bg-red-500;
}
}
.card {
@apply cursor-pointer rounded border-2 border-gray-700 bg-gray-800 p-4 shadow-[4px_4px_0px_0px_white] transition-all hover:-translate-0.5 hover:shadow-[6px_6px_0px_0px_white] active:translate-0.5 active:shadow-[2px_2px_0px_0px_white];
}
.input {
@apply w-full rounded border-2 border-gray-700 bg-gray-800 px-4 py-2 text-white transition-all placeholder:text-gray-500 focus:border-white focus:outline-none;
}
.ratio {
@apply h-6 w-6;
}