Score are dynamically displayed and saved in local storage

This commit is contained in:
Laurent
2024-10-14 16:23:07 +02:00
parent cf2234e704
commit c8df868626
8 changed files with 154 additions and 108 deletions

View File

@@ -0,0 +1,72 @@
<script>
export let scores = []
</script>
<ul class="leaderboard">
{#each scores as score, i}
<li class="item">
<div class="name"><img src="" alt=""/> {score.playerName} </div><div class="score"> {score.value} pts.</div>
</li>
{/each}
</ul>
<style>
.leaderboard
{
display: flex;
flex-direction: column;
width: 60vw;
height: 65vh;
padding: 0 2vw 2vw 2vw;
overflow: scroll;
overflow-x: hidden;
}
.leaderboard::-webkit-scrollbar {
display: none;
}
li
{
display: flex;
justify-content: space-around;
padding: 1.25vh;
margin: 1.5vh;
border: 2px solid #A1674A;
border-radius: 10px;
background-color: #f1ecec;
box-shadow: 0 0 10px #343232;
}
li:hover
{
transform: scale(1.075);
background-color: #F5F5F5;
}
.name, .score
{
color: black;
margin-left: 3vh;
}
.name
{
flex-grow: 100;
border-right: 1px solid #A1674A;
}
.score
{
flex-grow: 20;
text-align: center;
}
</style>

View File

@@ -0,0 +1,3 @@
<li class="item">
<slot></slot>
</li>

11
src/lib/models/score.ts Normal file
View File

@@ -0,0 +1,11 @@
export class Score {
readonly playerName : string;
readonly value: number;
constructor({playerName = "", value = 0}) {
this.playerName = playerName;
this.value = value;
}
}

View File

@@ -0,0 +1,34 @@
import {writable} from "svelte/store";
import {Score} from "../models/score";
import {browser} from "$app/environment"
let localStorageKey = "scores"
function isBrowser() {
return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
}
function createStore(){
const storedValue = isBrowser() ? localStorage.getItem(localStorageKey) : null;
const { set, update, subscribe } = writable<Score[]>(!storedValue ? [] : JSON.parse(storedValue));
if (isBrowser()) subscribe(value => localStorage.setItem(localStorageKey, JSON.stringify(value)));
return {
update,
subscribe,
set : (value : Score[]) => set(!value ? [] : value),
reset : () => set([]),
add : (playerName : string, value : number) => {
update(scores => {
let s = [...scores, new Score({playerName : playerName, value : value})];
if(s.length >= 2) s.sort((s1 : Score, s2 : Score) => s1.value - s2.value)
return s;
});
}
};
}
export const scoreStore = createStore();

View File

@@ -3,7 +3,6 @@
import github_mark from '$lib/assets/github-mark-white.svg';
import twitter_mark from '$lib/assets/twitter-mark-white.svg';
import NavLink from "$lib/components/NavLink.svelte";
import {onMount} from "svelte";
onMount(async () => {

View File

@@ -1,101 +1,9 @@
<ul class="leaderboard">
<script>
import {scoreStore} from "$lib/stores/scoreStore.ts"
import LeaderBoard from "$lib/components/LeaderBoard.svelte";
<li class="item">
<div class="name"><img src="" alt=""/> Player 1</div><div class="score">0 pts.</div>
</li>
</script>
<li class="item">
<div class="name"><img src="" alt=""/> Player 2</div><div class="score">1 pts.</div>
</li>
<button on:click={() => {scoreStore.reset()}}>Clear leaderboard</button>
<li class="item">
<div class="name"><img src="" alt=""/> Player 3</div><div class="score">2 pts.</div>
</li>
<li class="item">
<div class="name"><img src="" alt=""/> Player 4</div><div class="score">3 pts.</div>
</li>
<li class="item">
<div class="name"><img src="" alt=""/> Player 5</div><div class="score">4 pts.</div>
</li>
<li class="item">
<div class="name"><img src="" alt=""/> Player 6</div><div class="score">5 pts.</div>
</li>
<li class="item">
<div class="name"><img src="" alt=""/> Player 7</div><div class="score">6 pts.</div>
</li>
<li class="item">
<div class="name"><img src="" alt=""/> Player 8</div><div class="score">7 pts.</div>
</li>
<li class="item">
<div class="name"><img src="" alt=""/> Player 9</div><div class="score">8 pts.</div>
</li>
<li class="item">
<div class="name"><img src="" alt=""/> Player 10</div><div class="score">9 pts.</div>
</li>
</ul>
<style>
.leaderboard
{
display: flex;
flex-direction: column;
width: 60vw;
height: 65vh;
padding: 0 2vw 2vw 2vw;
overflow: scroll;
overflow-x: hidden;
}
.leaderboard::-webkit-scrollbar {
display: none;
}
li
{
display: flex;
justify-content: space-around;
padding: 1.25vh;
margin: 1.5vh;
border: 2px solid #A1674A;
border-radius: 10px;
background-color: #f1ecec;
box-shadow: 0 0 10px #343232;
}
li:hover
{
transform: scale(1.075);
color: #424242;
background-color: #F5F5F5;
}
.name, .score
{
color: black;
margin-left: 3vh;
}
.name
{
flex-grow: 100;
border-right: 1px solid #A1674A;
}
.score
{
flex-grow: 20;
text-align: center;
}
</style>
<LeaderBoard bind:scores={$scoreStore}></LeaderBoard>

View File

@@ -1 +1 @@
<p>It was revealed to me in my dream</p>
<p>It was revealed to me in a dream</p>

View File

@@ -1,7 +1,9 @@
<script>
import {onMount} from "svelte";
import {scoreStore} from "$lib/stores/scoreStore.ts";
let playerName = undefined;
let range = 100;
let result = 0;
@@ -23,6 +25,8 @@
toggleLoading();
window.$(".result").text(`Result : ${result}/${range}`)
scoreStore.add(playerName, result)
}
function toggleLoading(){
@@ -41,6 +45,7 @@
</div>
<div class="player">
<input class="name" placeholder="Your name" bind:value={playerName}/>
<button on:click={roll}>Let's roll !</button>
<div class="result"></div>
</div>
@@ -48,12 +53,7 @@
<style>
.disabled
{
display: none;
}
.container
.container, .player
{
display: flex;
flex-direction: column;
@@ -62,6 +62,25 @@
text-align: center;
}
.disabled
{
display: none;
}
.player
{
gap: 2vh;
}
.name
{
width: 17vw;
height: 6vh;
border: 2px solid #A1674A;
border-radius: 10px;
box-shadow: 0 0 10px #343232;
}
.circular-loader
{
stroke-dasharray: 100, 125;
@@ -79,7 +98,7 @@
{
color: black;
width: 18vw;
height: 18vh;
height: 15vh;
border-radius: 10px;
background-color: #f1ecec;
border: 2px solid #A1674A;
@@ -87,7 +106,7 @@
box-shadow: 0 0 10px #343232;
}
button:hover{
.name:hover, button:hover{
transform: scale(1.1);
}