Score are dynamically displayed and saved in local storage
This commit is contained in:
72
src/lib/components/LeaderBoard.svelte
Normal file
72
src/lib/components/LeaderBoard.svelte
Normal 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>
|
||||
3
src/lib/components/ListItem.svelte
Normal file
3
src/lib/components/ListItem.svelte
Normal file
@@ -0,0 +1,3 @@
|
||||
<li class="item">
|
||||
<slot></slot>
|
||||
</li>
|
||||
11
src/lib/models/score.ts
Normal file
11
src/lib/models/score.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export class Score {
|
||||
|
||||
readonly playerName : string;
|
||||
readonly value: number;
|
||||
|
||||
constructor({playerName = "", value = 0}) {
|
||||
this.playerName = playerName;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
34
src/lib/stores/scoreStore.ts
Normal file
34
src/lib/stores/scoreStore.ts
Normal 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();
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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>
|
||||
@@ -1 +1 @@
|
||||
<p>It was revealed to me in my dream</p>
|
||||
<p>It was revealed to me in a dream</p>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user