stream-score/src/routes/+page.svelte
2025-02-25 16:26:52 +01:00

479 lines
14 KiB
Svelte

<script>
import { onMount } from "svelte";
import { colors } from "$lib/stores/colors.js";
import { rounds } from "$lib/stores/rounds.js";
import { categories } from "$lib/stores/categories.js";
// let wWidth = $state(window.innerWidth);
// let wHeight = $state(window.innerHeight);
let timer;
let surfers = $state([]);
let start = $state(false);
let info = $state({
category: "U12 M",
round: "Qualifying",
heat: "1",
time: 0,
});
let mins = $state(0);
let secs = $state(0);
let round_name = $state(false);
onMount(async () => {
LoadFromLocalCache();
console.log(`onMount: ${JSON.stringify(surfers)}`);
});
function LoadFromLocalCache() {
let srf = window.sessionStorage.getItem("surfers");
if (srf) {
console.log(`load cache: ${srf}`);
surfers = JSON.parse(srf);
start = JSON.parse(window.sessionStorage.getItem("start"));
info = JSON.parse(window.sessionStorage.getItem("info"));
console.log(
`loaded cache: ${JSON.stringify(surfers)} - ${start} - ${info}`,
);
} else {
ResetLocalCache();
console.log(`no cache found`);
}
}
function ResetLocalCache() {
console.log("ResetLocalCache");
window.sessionStorage.clear();
surfers = [
{
id: 1,
name: "",
score: 0,
color: "lightgray",
priority: 0,
delete: false,
},
{
id: 2,
name: "",
score: 0,
color: "lightgray",
priority: 0,
delete: false,
},
];
start = false;
info = {
category: "U12 M",
round: "Qualifying",
heat: "1",
time: 0,
};
mins = info.time;
secs = 0;
round_name = false;
console.log(`reset store: ${JSON.stringify(surfers)}`);
}
function SaveToLocalCahe() {
window.sessionStorage.setItem("surfers", JSON.stringify(surfers));
window.sessionStorage.setItem("info", JSON.stringify(info));
console.log(`update cache: ${JSON.stringify(surfers)}`);
}
function StartHeat() {
console.log("StartHeat");
start = true;
mins = info.time;
secs = 0;
SaveToLocalCahe();
timer = setInterval(Timer, 1000);
}
function pad(n) {
return n < 10 ? "0" + n : n;
}
function Timer() {
if (mins == 0 && secs == 0) {
StopHeat();
}
if (secs == 0) {
mins = mins - 1;
secs = 59;
} else {
secs = secs - 1;
}
}
function StopHeat() {
console.log("StopHeat");
start = false;
SaveToLocalCahe;
clearInterval(timer);
}
function CheckRound() {
if (!round_name) {
info.round = "Qualifying";
} else {
info.round = "QR";
}
}
function AddSurfer() {
if (surfers.length < 5) {
let newSurfer = {
id: surfers.length + 1,
name: "",
score: 0,
rank: 0,
color: "lightgray",
delete: true,
};
surfers.push(newSurfer);
SaveToLocalCahe();
}
}
function DelSurfer() {
if (surfers.length > 2) {
surfers.pop();
SaveToLocalCahe();
}
}
async function SendStatus() {
if (dev) {
return;
}
const res = await fetch(`/api/status`, {
method: "POST",
body: JSON.stringify({
surfers: surfers,
info: info,
start: start,
}),
headers: {
"Content-Type": "application/json",
},
});
console.log(`SendPriority: ${JSON.stringify(info)}`);
}
</script>
<!-- <svelte:window bind:innerWidth={wWidth} bind:innerHeight={wHeight} /> -->
<div class="body">
<div id="score-container">
<div class="info-box">
<div class="Time">
{#if mins >= 0}
<span id="time">{pad(mins)}:{pad(secs)}</span>
{/if}
</div>
<div class="Cat">
<small><span id="round">{info.category}</span></small>
</div>
<div class="Round">
<small><span id="round">{info.round}</span></small>
</div>
<div class="Heat">
<small><span id="heat">Heat {info.heat}</span></small>
</div>
</div>
{#each surfers as surfer}
{#if surfer.name != ""}
<div class="score-box">
<div
class="color"
style="background-color: {surfer.color};"
id="color-{surfer.color}">
</div>
<div class="surfer">{surfer.name}</div>
{#if surfer.score != 0}
<div class="score" id="score-1">{surfer.score}</div>
{/if}
</div>
{/if}
{/each}
</div>
<!-- Form -->
<div class="form-box">
<form>
{#if start}
<button
type="submit"
class="btn btn-danger mt-1 mb-3 w-100"
onclick={StopHeat}>Stop</button>
{:else}
<button
type="submit"
class="btn btn-primary mt-1 mb-3 w-100"
onclick={StartHeat}>Start</button>
{/if}
<div class="input-group mb-1">
<span class="input-group-text">time</span>
<input
disabled={start}
type="text"
class="form-control time"
name="time"
required
pattern="^[0-9][0-9]$"
maxlength="2"
size="2"
onchange={() => {
secs = 0;
mins = info.time;
}}
bind:value={info.time} />
<span class="input-group-text">category</span>
<select
class="form-select"
name="category"
aria-label="Category"
bind:value={info.category}>
{#each $categories as cat}
<option value={cat.title}>{cat.title}</option>
{/each}
</select>
</div>
<div class="input-group">
<span class="input-group-text">round</span>
<select
name="round"
class="form-select"
aria-label="Round"
bind:value={info.round}>
{#each $rounds as rnd}
{#if round_name}
<option value={rnd.title}>{rnd.name}</option>
{:else}
<option value={rnd.name}>{rnd.name}</option>
{/if}
{/each}
</select>
<div class="input-group-text">
<input
class="form-check-input mt-0"
type="checkbox"
bind:checked={round_name}
onchange={CheckRound}
aria-label="Checkbox for following text input" />
</div>
<span class="input-group-text">heat</span>
<input
type="text"
class="form-control"
name="heat"
bind:value={info.heat}
pattern="^[0-9][0-9]?$"
maxlength="2"
size="2" />
</div>
<hr />
<div class="surfer">
<ul>
{#each surfers as surfer, id}
<li>
<div
class="d-grid gap-2 d-md-flex justify-content-md-center mb-2">
<!-- <div class="input-group"> -->
<!-- <span class="input-group-text">colore</span> -->
<select
class="form-select w-25"
name="color"
aria-label="Color"
size="1"
bind:value={surfer.color}
style="background-color: {surfer.color};">
{#each $colors as col}
<option
value={col}
class="color"
style="background-color: {col}"
>{col}</option>
{/each}
</select>
<span class="badge bg-secondary">nome</span>
<input
type="text"
class="form-control"
name="nome-{id}"
bind:value={surfer.name} />
<span class="badge bg-secondary">score</span>
<input
type="number"
class="form-control w-25"
name="score-{id}"
bind:value={surfer.score} />
</div>
</li>
{/each}
</ul>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-center mb-2">
<button
type="button"
class="btn btn-primary w-50"
onclick={AddSurfer}>Add</button>
<button
type="button"
class="btn btn-warning w-50"
onclick={DelSurfer}>Del</button>
<!-- <div class="btn-group w-100" role="group" aria-label="save"> -->
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-2">
<button
type="button"
class="btn btn-primary w-50"
onclick={SaveToLocalCahe}>Save</button>
<button
type="button"
class="btn btn-danger w-50"
onclick={ResetLocalCache}>Reset</button>
</div>
<!-- <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-2">
<button class="justify-content-md-center"
>{wWidth} - {wHeight}</button>
</div> -->
</form>
</div>
</div>
<style>
.body {
background-color: lightgreen;
color: black;
font-family: Arial, sans-serif;
min-height: 895px;
min-width: 1024px;
}
.info-box {
display: grid;
top: 6px;
left: 6px;
width: 254px;
padding-left: 6px;
padding-right: 4px;
background: rgba(40, 40, 40, 0.8);
color: white;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
gap: 1px 1px;
grid-template-areas:
"Time Time Time Cat Cat"
"Time Time Time Round Round"
"Time Time Time Heat Heat";
margin: 2px;
}
.score-box {
display: grid;
grid-template-columns: 1fr 4fr 1fr;
grid-template-areas: "color surfer score";
width: 254px;
padding-left: 6px;
padding-right: 6px;
padding-top: 2px;
padding-bottom: 2px;
background: rgba(40, 40, 40, 0.8);
color: white;
margin-left: 2px;
}
.Time {
grid-area: Time;
font-size: 48px;
font-weight: bold;
justify-self: start;
align-self: center;
}
.Cat {
grid-area: Cat;
font-size: 14px;
justify-self: start;
align-self: center;
margin-left: 28px;
#font-weight: bold;
}
.Round {
grid-area: Round;
font-size: 14px;
justify-self: start;
align-self: center;
margin-left: 28px;
#font-weight: bold;
}
.Heat {
grid-area: Heat;
font-size: 14px;
justify-self: start;
align-self: center;
margin-left: 28px;
#font-weight: bold;
}
.surfer {
grid-area: surfer;
display: flex;
align-items: center;
padding: 6px;
width: 100%;
align-content: center;
}
.surfer ul {
list-style-type: none;
margin-left: 0px;
padding-left: 0px;
}
.surfer select {
-moz-appearance: none; /* Firefox */
-webkit-appearance: none; /* Safari and Chrome */
appearance: none;
}
.color {
grid-area: color;
width: 30px;
height: 30px;
border-radius: 2px;
margin-right: 10px;
margin-top: 4px;
margin-left: 4px;
}
.score {
grid-area: score;
font-weight: bold;
text-align: start;
align-content: center;
margin-right: 2px;
}
.form-box {
width: 700px;
background: rgba(50, 50, 50, 0.7);
color: white;
margin-left: 550px;
margin-top: 100px;
padding: 10px;
}
.form-box .time {
font-size: 16px;
font-weight: bold;
justify-self: start;
align-self: center;
}
.form-box .surfer {
font-size: 16px;
font-weight: bold;
justify-self: end;
}
</style>