MVP #6.1 #82

Merged
matthieu42morin merged 34 commits from master into deploy/prod 2023-03-31 17:40:26 +00:00
3 changed files with 56 additions and 29 deletions
Showing only changes of commit 2f84cb65db - Show all commits

View File

@ -1,5 +1,5 @@
import { databases, user as userStore } from '$lib/appwrite' import { databases, user as userStore } from '$lib/appwrite'
import { Account, Permission, Query, Role } from 'appwrite' import { Account, Models, Permission, Query, Role } from 'appwrite'
import database from 'svelte-appwrite-client/src/lib/database' import database from 'svelte-appwrite-client/src/lib/database'
import { getLocationDataFromLatAndLong } from '../locations' import { getLocationDataFromLatAndLong } from '../locations'
import { writable } from 'svelte/store' import { writable } from 'svelte/store'
@ -57,17 +57,17 @@ export const answer = async (experienceId: string, checkPointId: string, answer:
if (CPType === 'CHECKBOX') correct = JSON.stringify(answer) === JSON.stringify(correctAnswer) if (CPType === 'CHECKBOX') correct = JSON.stringify(answer) === JSON.stringify(correctAnswer)
if (CPType === 'RADIO' || CPType === 'NUMBER' || CPType === 'TEXT') correct = answer === correctAnswer[0] if (CPType === 'RADIO' || CPType === 'NUMBER' || CPType === 'TEXT') correct = answer === correctAnswer[0]
//await saveAnswerIntoDatabase(experienceId, checkPointId, correct) await saveAnswerIntoDatabase(experienceId, checkPointId, correct)
return correct return correct
} catch (error) { } catch (error) {
throw new Error(error)
//operation only for sveltekit 401, 500, 403 //operation only for sveltekit 401, 500, 403
} }
} }
const saveAnswerIntoDatabase = async (experienceId: string, checkPointId: string, correct: boolean) => { const saveAnswerIntoDatabase = async (experienceId: string, checkPointId: string, correct: boolean) => {
const previousAttemptDocument = await getUserAnswer(user.$id, checkPointId) const previousAttemptDocument = await getUserAnswer(user.$id, checkPointId)
console.log(previousAttemptDocument)
if (!(previousAttemptDocument?.attemptCount === 2)) { if (!(previousAttemptDocument?.attemptCount === 2)) {
if (previousAttemptDocument) { if (previousAttemptDocument) {
@ -87,6 +87,10 @@ const saveAnswerIntoDatabase = async (experienceId: string, checkPointId: string
[Permission.read(Role.user(user.$id)), Permission.update(Role.user(user.$id))], [Permission.read(Role.user(user.$id)), Permission.update(Role.user(user.$id))],
) )
} }
} else {
const err = new Error('User has already answered.')
err['code'] = '409'
throw err
} }
} }
@ -126,4 +130,16 @@ export const getExperiencesAsStore = () => {
return [store, loading] as const return [store, loading] as const
} }
export const getUserProgress = async (experienceId: string) => {
const { documents } = await databases.listDocuments('63cef30d6da945dd4250', 'users-answers', [Query.equal('userId', user.$id), Query.equal('experience', experienceId)])
return documents
}
export const getUserProgressAsStore = (experienceId: string) => {
const store = writable<Models.Document[]>([])
getUserProgress(experienceId).then((documents) => {
store.set(documents)
})
return [store] as const
}
// !pridat trideni podle kategorie! export const getExperiencesByCategory = async (category: string) => {} // !pridat trideni podle kategorie! export const getExperiencesByCategory = async (category: string) => {}

View File

@ -16,6 +16,7 @@
import { user } from '$lib/appwrite' import { user } from '$lib/appwrite'
import Button from '$lib/components/Buttons/Button.svelte' import Button from '$lib/components/Buttons/Button.svelte'
import LayoutImg from '$lib/components/Layouts/LayoutImg.svelte' import LayoutImg from '$lib/components/Layouts/LayoutImg.svelte'
import { Models } from 'appwrite'
const components = { const components = {
TEXT: TextForm, TEXT: TextForm,
@ -30,10 +31,11 @@
export let control: AnswerState = null export let control: AnswerState = null
let view: 'question' | 'map' | 'end' | 'start' | 'start-map' = 'start-map' let view: 'question' | 'map' | 'end' | 'start' | 'start-map' = 'start-map'
export let gameData: Experience //data export let gameData: Experience //data
export let userProgress: Models.Document[]
let client = { let client = {
//user data about game //user data about game
pos: 0, pos: userProgress.length,
end: gameData.checkPoints.length - 1, //kolik otázek end: gameData.checkPoints.length - 1, //kolik otázek
points: 0, //body points: 0, //body
possiblePointsToSeize: gameData.checkPoints.length * 2, possiblePointsToSeize: gameData.checkPoints.length * 2,
@ -63,19 +65,24 @@
$: checkPoint = gameData.checkPoints[client.pos] $: checkPoint = gameData.checkPoints[client.pos]
let myAnswer: string | string[] let myAnswer: string | string[]
let clear: boolean = false
const checkAnswer = async () => { const checkAnswer = async () => {
const res = await answer(gameData.$id, checkPoint.$id, myAnswer) try {
if (res) { const res = await answer(gameData.$id, checkPoint.$id, myAnswer)
control = 'correct'
client.points += 2 if (res) {
} else if (control === null) { control = 'correct'
control = 'wrong-firstTime' client.points += 2
clear = true } else if (control === null) {
} else control = 'wrong-secondTime' control = 'wrong-firstTime'
setTimeout(() => (clear = false), 400) clear = true
} else control = 'wrong-secondTime'
setTimeout(() => (clear = false), 400)
} catch (error) {
console.log(error)
}
} }
let clear: boolean = false
</script> </script>
<input type="number" bind:value={client.pos} /> <input type="number" bind:value={client.pos} />

View File

@ -12,16 +12,20 @@
import Renderer from './Forms/Renderer.svelte' import Renderer from './Forms/Renderer.svelte'
import Marker from '../../lib/components/Map/Marker.svelte' import Marker from '../../lib/components/Map/Marker.svelte'
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { load } from '$lib/utils/database/experience' import { getUserProgressAsStore, load } from '$lib/utils/database/experience'
import { getLocationDataFromLatAndLong } from '$lib/utils/locations' import { getLocationDataFromLatAndLong } from '$lib/utils/locations'
import { navigate } from '$lib/router' import { navigate } from '$lib/router'
import { Experience } from '$lib/TStypes/experiences'
export let params: { gameurl: string } export let params: { gameurl: string }
let gameData: Experience //
$: [userProgress] = gameData ? getUserProgressAsStore(gameData?.$id) : []
$: console.log($userProgress)
onMount(async () => { onMount(async () => {
try { try {
$data = await load(params.gameurl, 1, (preview) => { gameData = await load(params.gameurl, 2, (preview) => {
$data = preview gameData = preview
view = 'experience-preview' view = 'experience-preview'
}) })
} catch (error) { } catch (error) {
@ -29,7 +33,7 @@
} }
}) })
/*$: assets = $data?.questions /*$: assets = gameData?.questions
?.filter((q) => q.thumbnail !== null) ?.filter((q) => q.thumbnail !== null)
?.slice(0, 8) ?.slice(0, 8)
?.map((q) => q.thumbnail)*/ ?.map((q) => q.thumbnail)*/
@ -38,7 +42,7 @@
//is user already in game //is user already in game
//const userInGame = JSON.parse(localStorage.getItem(location.pathname)) //const userInGame = JSON.parse(localStorage.getItem(location.pathname))
//$: if ($data && userInGame) view = 'game-play' //$: if (gameData && userInGame) view = 'game-play'
</script> </script>
{#if view === 'experience-loading'} {#if view === 'experience-loading'}
@ -47,27 +51,27 @@
<Loading /> <Loading />
</h1> </h1>
{:else if view === 'experience-preview'} {:else if view === 'experience-preview'}
<Overlay shareData={{ url: window.location.href }} img={$data.ExpImage}> <Overlay shareData={{ url: window.location.href }} img={gameData.ExpImage}>
<div> <div>
<span class="text-[36px]">{$data.ExpName}</span> <span class="text-[36px]">{gameData.ExpName}</span>
<div class="bubbles"> <div class="bubbles">
<Bubble background="blue"> <Bubble background="blue">
<span slot="icon"><IconStar /></span> <span slot="icon"><IconStar /></span>
<span> {$data.rating} </span> <span> {'gameData.rating'} </span>
</Bubble> </Bubble>
<Bubble background="white"> <Bubble background="white">
<span slot="icon"><IconPoint /></span> <span slot="icon"><IconPoint /></span>
{#await getLocationDataFromLatAndLong($data.ExpLocation[0], $data.ExpLocation[1]) then { city }} {#await getLocationDataFromLatAndLong(gameData.ExpLocation[0], gameData.ExpLocation[1]) then { city }}
<span>{city}</span> <span>{city}</span>
{/await} {/await}
</Bubble> </Bubble>
</div> </div>
</div> </div>
{#if $data.ExpIntroduction} {#if gameData.ExpIntroduction}
<Section title="Popis"> <Section title="Popis">
<span> <span>
{@html $data.ExpIntroduction} {@html gameData.ExpIntroduction}
</span> </span>
</Section> </Section>
{/if} {/if}
@ -82,20 +86,20 @@
<div class="w-full relative"> <div class="w-full relative">
<div class="px-4 m-auto" style="max-width: var(--max-viewport-width);"> <div class="px-4 m-auto" style="max-width: var(--max-viewport-width);">
<Map radius class="w-full h-44" center={{ lng: $data.ExpLocation[1], lat: $data.ExpLocation[0] }}> <Map radius class="w-full h-44" center={{ lng: gameData.ExpLocation[1], lat: gameData.ExpLocation[0] }}>
{#each $data.checkPoints as { CPLocation: [lat, lng] }} {#each gameData.checkPoints as { CPLocation: [lat, lng] }}
<Marker {lat} {lng} /> <Marker {lat} {lng} />
{/each} {/each}
</Map> </Map>
</div> </div>
</div> </div>
{#if $data.checkPoints.length} {#if gameData.checkPoints.length}
<Button on:click={() => (view = 'experience-play')} primary>Hrát</Button> <Button on:click={() => (view = 'experience-play')} primary>Hrát</Button>
{/if} {/if}
</Overlay> </Overlay>
{:else if view === 'experience-play'} {:else if view === 'experience-play'}
<Renderer gameData={$data} /> <Renderer {gameData} {userProgress} />
{/if} {/if}
<style> <style>