INIT
This commit is contained in:
parent
d9a1837f3b
commit
ebd2f05ae2
69 changed files with 2335 additions and 451 deletions
13
frontend.old/.eslintignore
Normal file
13
frontend.old/.eslintignore
Normal file
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
15
frontend.old/.eslintrc.cjs
Normal file
15
frontend.old/.eslintrc.cjs
Normal file
|
@ -0,0 +1,15 @@
|
|||
/** @type { import("eslint").Linter.FlatConfig } */
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['eslint:recommended', 'plugin:svelte/recommended', 'prettier'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
extraFileExtensions: ['.svelte']
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2017: true,
|
||||
node: true
|
||||
}
|
||||
};
|
10
frontend.old/.gitignore
vendored
Normal file
10
frontend.old/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
1
frontend.old/.npmrc
Normal file
1
frontend.old/.npmrc
Normal file
|
@ -0,0 +1 @@
|
|||
engine-strict=true
|
13
frontend.old/.prettierignore
Normal file
13
frontend.old/.prettierignore
Normal file
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Ignore files for PNPM, NPM and YARN
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
yarn.lock
|
8
frontend.old/.prettierrc
Normal file
8
frontend.old/.prettierrc
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte"],
|
||||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||
}
|
38
frontend.old/README.md
Normal file
38
frontend.old/README.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
# create-svelte
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
26
frontend.old/package.json
Normal file
26
frontend.old/package.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "frontend",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev --host",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^2.1.1",
|
||||
"@sveltejs/adapter-static": "^2.0.3",
|
||||
"@sveltejs/kit": "^1.30.3",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.35.1",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.1.2",
|
||||
"sass": "^1.69.5",
|
||||
"svelte": "^4.2.8",
|
||||
"vite": "^4.5.1"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
1588
frontend.old/pnpm-lock.yaml
generated
Normal file
1588
frontend.old/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
12
frontend.old/src/app.html
Normal file
12
frontend.old/src/app.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
24
frontend.old/src/lib/icons/login.svelte
Normal file
24
frontend.old/src/lib/icons/login.svelte
Normal file
|
@ -0,0 +1,24 @@
|
|||
<script>
|
||||
// import { Button, Tooltip } from 'flowbite-svelte';
|
||||
|
||||
export let pill = false;
|
||||
export let color = 'blue';
|
||||
export let size = 'sm';
|
||||
export let href = "/login";
|
||||
</script>
|
||||
|
||||
<button size={size} class="!p-2" {pill} color={color} href={href}>
|
||||
<svg
|
||||
class="w-6 h-6 text-gray-100 dark:text-white"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M10 0a10 10 0 1 0 10 10A10.011 10.011 0 0 0 10 0Zm0 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Zm0 13a8.949 8.949 0 0 1-4.951-1.488A3.987 3.987 0 0 1 9 13h2a3.987 3.987 0 0 1 3.951 3.512A8.949 8.949 0 0 1 10 18Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- <Tooltip id="type-auto" arrow={false} type="custom" defaultClass="" class="p-1 text-sm bg-blue-700 text-gray-100" >Login</Tooltip> -->
|
43
frontend.old/src/lib/icons/priority.svelte
Normal file
43
frontend.old/src/lib/icons/priority.svelte
Normal file
|
@ -0,0 +1,43 @@
|
|||
<script>
|
||||
// import { Button, Tooltip } from 'flowbite-svelte';
|
||||
|
||||
|
||||
export let pill = false;
|
||||
export let color = 'blue';
|
||||
export let size = 'sm';
|
||||
</script>
|
||||
|
||||
<button {size} class="!p-2" {pill} {color}>
|
||||
<svg class="w-6 h-6" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="m62.578 41.956 -28.444 21.333a3.556 3.556 0 0 1 -4.267 0l-28.444 -21.333a3.637 3.637 0 0 1 -1.244 -3.982A3.605 3.605 0 0 1 3.556 35.556h7.111V32a3.566 3.566 0 0 1 3.556 -3.556h35.556a3.566 3.566 0 0 1 3.556 3.556v3.556h7.111a3.552 3.552 0 0 1 2.133 6.4Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
x="3"
|
||||
y="4"
|
||||
width="12"
|
||||
height="2"
|
||||
rx="1"
|
||||
ry="1"
|
||||
d="M14.222 14.222H49.778A3.556 3.556 0 0 1 53.333 17.778V17.778A3.556 3.556 0 0 1 49.778 21.333H14.222A3.556 3.556 0 0 1 10.667 17.778V17.778A3.556 3.556 0 0 1 14.222 14.222z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
x="3"
|
||||
width="12"
|
||||
height="2"
|
||||
rx="1"
|
||||
ry="1"
|
||||
d="M14.222 0H49.778A3.556 3.556 0 0 1 53.333 3.556V3.556A3.556 3.556 0 0 1 49.778 7.111H14.222A3.556 3.556 0 0 1 10.667 3.556V3.556A3.556 3.556 0 0 1 14.222 0z"
|
||||
/></svg
|
||||
>
|
||||
</button>
|
||||
<!-- <Tooltip
|
||||
id="type-auto"
|
||||
arrow={false}
|
||||
type="custom"
|
||||
defaultClass=""
|
||||
class="p-1 text-sm bg-blue-700 text-gray-100">Priority</Tooltip
|
||||
> -->
|
32
frontend.old/src/lib/icons/score.svelte
Normal file
32
frontend.old/src/lib/icons/score.svelte
Normal file
|
@ -0,0 +1,32 @@
|
|||
<script>
|
||||
// import { Button, Tooltip } from 'flowbite-svelte';
|
||||
|
||||
|
||||
export let pill = false;
|
||||
export let color = 'blue';
|
||||
export let size = 'sm';
|
||||
</script>
|
||||
|
||||
<button size={size} class="!p-2" {pill} color={color}>
|
||||
<svg
|
||||
class="w-6 h-6"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 455 455"
|
||||
style="enable-background:new 0 0 455 455;"
|
||||
xml:space="preserve"
|
||||
fill="currentColor"
|
||||
>
|
||||
<g>
|
||||
<rect x="162" y="323" width="293" height="132" />
|
||||
<rect x="162" y="161" width="293" height="132" />
|
||||
<rect width="455" height="131" />
|
||||
<rect y="161" width="132" height="294" />
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- <Tooltip id="type-auto" arrow={false} type="custom" defaultClass="" class="p-1 text-sm bg-blue-700 text-gray-100" >Score</Tooltip> -->
|
BIN
frontend.old/src/lib/img/topscorer_logo_alpha.png
Executable file
BIN
frontend.old/src/lib/img/topscorer_logo_alpha.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
BIN
frontend.old/src/lib/img/topscorer_logo_icon.png
Normal file
BIN
frontend.old/src/lib/img/topscorer_logo_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
frontend.old/src/lib/img/topscorer_logo_web.png
Executable file
BIN
frontend.old/src/lib/img/topscorer_logo_web.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
1
frontend.old/src/lib/index.js
Normal file
1
frontend.old/src/lib/index.js
Normal file
|
@ -0,0 +1 @@
|
|||
// place files you want to import through the `$lib` alias in this folder.
|
14
frontend.old/src/lib/store/surfer.js
Normal file
14
frontend.old/src/lib/store/surfer.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { writable } from 'svelte/store'
|
||||
|
||||
export default function () {
|
||||
const surfers = writable([]);
|
||||
|
||||
async function get() {
|
||||
const response = await fetch(`/api/surfers`)
|
||||
surfers.set(await response.json())
|
||||
}
|
||||
|
||||
get();
|
||||
|
||||
return surfers;
|
||||
}
|
14
frontend.old/src/lib/store/user.js
Normal file
14
frontend.old/src/lib/store/user.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { writable } from 'svelte/store'
|
||||
|
||||
export default function () {
|
||||
const users = writable([]);
|
||||
|
||||
async function get() {
|
||||
const response = await fetch(`/api/users`)
|
||||
users.set(await response.json())
|
||||
}
|
||||
|
||||
get();
|
||||
|
||||
return users;
|
||||
}
|
3
frontend.old/src/routes/+layout.js
Normal file
3
frontend.old/src/routes/+layout.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export const prerender = true;
|
||||
export const ssr = false;
|
||||
export const trailingSlash = 'always';
|
10
frontend.old/src/routes/+page.svelte
Normal file
10
frontend.old/src/routes/+page.svelte
Normal file
|
@ -0,0 +1,10 @@
|
|||
<script>
|
||||
import TopScorer from "$lib/img/topscorer_logo_web.png";
|
||||
</script>
|
||||
|
||||
<div style="background-color: black;">
|
||||
<img src={TopScorer} alt="TopScorer">
|
||||
</div>
|
||||
|
||||
|
||||
|
240
frontend.old/src/routes/displayh/+page.svelte
Normal file
240
frontend.old/src/routes/displayh/+page.svelte
Normal file
|
@ -0,0 +1,240 @@
|
|||
<script>
|
||||
// import { page } from '$app/stores';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
if (dev) {
|
||||
console.log('Dev mode');
|
||||
} else {
|
||||
console.log('Not dev mode');
|
||||
}
|
||||
|
||||
let surfers = [
|
||||
{ name: 'Kanoa Igarashi', color: 'red', score: '4.50', priority: '3' },
|
||||
{ name: 'Griffin Colapinto', color: 'white', score: '5.60', priority: 'P' },
|
||||
{ name: 'Jack Robinson', color: 'blue', score: '6.10', priority: '5' },
|
||||
{ name: 'Gabriel Medina', color: 'green', score: '4.30', priority: '2' },
|
||||
{ name: 'Italo Ferreira', color: 'black', score: '6.50', priority: '4' }
|
||||
];
|
||||
|
||||
let width;
|
||||
// $: activeUrl = $page.url.pathname;
|
||||
|
||||
let event = 'Semifinal';
|
||||
let category = 'U16 man';
|
||||
let heat = 'Heat 1';
|
||||
|
||||
const pad2 = (number) => `00${number}`.slice(-2);
|
||||
|
||||
$: min = 10;
|
||||
$: sec = 25;
|
||||
|
||||
let end = false;
|
||||
|
||||
function updateRemainingTime() {
|
||||
if ((min === 0) & (sec === 0)) {
|
||||
clearInterval(timer);
|
||||
end = true;
|
||||
} else if (sec === 0) {
|
||||
min -= 1;
|
||||
sec = 59;
|
||||
} else {
|
||||
sec -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
updateRemainingTime();
|
||||
|
||||
const timer = setInterval(updateRemainingTime, 1000);
|
||||
|
||||
function Subscribe() {
|
||||
const sse = new EventSource(`/api/sse`);
|
||||
console.log('subscribe');
|
||||
sse.onmessage = (e) => {
|
||||
let Msg = JSON.parse(e.data);
|
||||
console.log(`received: ${JSON.stringify(Msg)}`);
|
||||
if (Msg.mode === 'priority') {
|
||||
console.log(`priority: ${Msg.priority}`);
|
||||
for (let i in surfers) {
|
||||
surfers[i].priority = Msg.priority[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
return () => {
|
||||
sse.close();
|
||||
console.log(`sse closing ${Date.now()}`);
|
||||
};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const unsub = Subscribe();
|
||||
return unsub;
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(timer); // Pulisci il timer quando il componente viene distrutto
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth={width} />
|
||||
|
||||
<div class="header">
|
||||
{#if !end}
|
||||
<div class="timer">{pad2(min)}:{pad2(sec)}</div>
|
||||
{:else}
|
||||
<div class="timer" style="color: red">{pad2(min)}:{pad2(sec)}</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
{#each surfers as surfer, id}
|
||||
<div class="box">
|
||||
<div class="square" style="background-color: {surfer.color};">
|
||||
{#if surfer.priority != ''}
|
||||
{#if surfer.priority === 'P'}
|
||||
{#if surfer.color === 'white'}
|
||||
<span class="priority_white">{surfer.priority}</span>
|
||||
{:else}
|
||||
<span class="priority">{surfer.priority}</span>
|
||||
{/if}
|
||||
{:else}
|
||||
<span class="priority_small">{surfer.priority}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="score">{surfer.score}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--backColor: #334;
|
||||
--textColor: white;
|
||||
--maxWidth: (100% - 15px);
|
||||
}
|
||||
|
||||
.header {
|
||||
/* padding: 15px; */
|
||||
height: 10vh;
|
||||
background-color: var(--backColor);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header .timer {
|
||||
font-size: 13vh;
|
||||
padding-left: 10px;
|
||||
padding-right: 20px;
|
||||
font-weight: bold;
|
||||
flex: 2 2 auto;
|
||||
align-self: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 85vh;
|
||||
background-color: var(--backColor);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 4px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.priority {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
animation: blink 2s 3;
|
||||
margin-right: auto;
|
||||
background-color: white;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.priority_white {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
animation: blink_white 2s 3;
|
||||
margin-right: auto;
|
||||
background-color: black;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.priority_small {
|
||||
width: 10%;
|
||||
height: 80%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
/* animation: blink 2s infinite; */
|
||||
margin-right: auto;
|
||||
margin-left: 30px;
|
||||
background-color: #bbb;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.square {
|
||||
width: 100%;
|
||||
height: 16vh;
|
||||
border-radius: 5px;
|
||||
margin-right: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.score {
|
||||
padding-right: 20px;
|
||||
width: 20%;
|
||||
font-size: 12vh;
|
||||
float: right;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0% {
|
||||
background-color: white;
|
||||
}
|
||||
50% {
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
100% {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
</style>
|
256
frontend.old/src/routes/displayv/+page.svelte
Normal file
256
frontend.old/src/routes/displayv/+page.svelte
Normal file
|
@ -0,0 +1,256 @@
|
|||
<script>
|
||||
// import { page } from '$app/stores';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
if (dev) {
|
||||
console.log('Dev mode');
|
||||
} else {
|
||||
console.log('Not dev mode');
|
||||
}
|
||||
|
||||
|
||||
|
||||
let surfers = [
|
||||
// { name: 'Kanoa Igarashi', color: 'red', score: '4.50', priority: '3' },
|
||||
// { name: 'Griffin Colapinto', color: 'white', score: '5.60', priority: 'P' },
|
||||
// { name: 'Jack Robinson', color: 'blue', score: '6.10', priority: '5' },
|
||||
// { name: 'Gabriel Medina', color: 'green', score: '4.30', priority: '2' },
|
||||
// { name: 'Italo Ferreira', color: 'black', score: '6.50', priority: '4' }
|
||||
];
|
||||
|
||||
let width;
|
||||
// $: activeUrl = $page.url.pathname;
|
||||
|
||||
let heat = {};
|
||||
|
||||
const pad2 = (number) => `00${number}`.slice(-2);
|
||||
|
||||
$: min = 0;
|
||||
$: sec = 0;
|
||||
|
||||
let end = false;
|
||||
|
||||
loadRunning();
|
||||
|
||||
async function loadRunning() {
|
||||
const res = await fetch(`/api/runningheat`);
|
||||
const data = await res.json();
|
||||
heat = data;
|
||||
console.log(`retval: ${JSON.stringify(heat)}`);
|
||||
|
||||
if (heat != null) {
|
||||
console.log(`heat: ${JSON.stringify(heat)}`);
|
||||
min = heat.timer;
|
||||
surfers = heat.surfers;
|
||||
}
|
||||
}
|
||||
|
||||
// function updateRemainingTime() {
|
||||
// if ((min === 0) & (sec === 0)) {
|
||||
// clearInterval(timer);
|
||||
// end = true;
|
||||
// } else if (sec === 0) {
|
||||
// min -= 1;
|
||||
// sec = 59;
|
||||
// } else {
|
||||
// sec -= 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// updateRemainingTime();
|
||||
|
||||
// const timer = setInterval(updateRemainingTime, 1000);
|
||||
|
||||
function Subscribe() {
|
||||
const sse = new EventSource(`/api/sse`);
|
||||
console.log('subscribe');
|
||||
sse.onmessage = (e) => {
|
||||
let Msg = JSON.parse(e.data);
|
||||
console.log(`received: ${JSON.stringify(Msg)}`);
|
||||
if (Msg.mode === 'priority') {
|
||||
console.log(`priority: ${Msg.priority}`);
|
||||
for (let i in surfers) {
|
||||
surfers[i].priority = Msg.priority[i];
|
||||
}
|
||||
} else if (Msg.mode === 'time') {
|
||||
// console.log(`duration: ${Msg.duration}`);
|
||||
let min_sec = Msg.duration.split(":");
|
||||
min = min_sec[0];
|
||||
sec = min_sec[1];
|
||||
// console.log(`min & sec = ${min} & ${sec}`);
|
||||
if (!start) {
|
||||
start = true;
|
||||
}
|
||||
} else if (Msg.mode === 'stop') {
|
||||
console.log(`stop duration: ${Msg.duration}`);
|
||||
end = true;
|
||||
start = false;
|
||||
}
|
||||
};
|
||||
return () => {
|
||||
sse.close();
|
||||
console.log(`sse closing ${Date.now()}`);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
onMount(() => {
|
||||
if (!dev) {
|
||||
const unsub = Subscribe();
|
||||
return unsub;
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(timer); // Pulisci il timer quando il componente viene distrutto
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth={width} />
|
||||
|
||||
<div class="header">
|
||||
{#if !end}
|
||||
<div class="timer">{pad2(min)}:{pad2(sec)}</div>
|
||||
{:else}
|
||||
<div class="timer" style="color: red">{pad2(min)}:{pad2(sec)}</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
{#each surfers as surfer, id}
|
||||
<div class="box">
|
||||
<div class="square" style="background-color: {surfer.color};">
|
||||
{#if surfer.priority != ''}
|
||||
{#if surfer.priority === 'P'}
|
||||
{#if surfer.color === 'white'}
|
||||
<span class="priority_white">{surfer.priority}</span>
|
||||
{:else}
|
||||
<span class="priority">{surfer.priority}</span>
|
||||
{/if}
|
||||
{:else}
|
||||
<span class="priority_small">{surfer.priority}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="score">{surfer.score}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--backColor: #334;
|
||||
--textColor: white;
|
||||
--maxWidth: (100% - 15px);
|
||||
}
|
||||
|
||||
.header {
|
||||
/* padding: 15px; */
|
||||
height: 10vh;
|
||||
background-color: var(--backColor);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header .timer {
|
||||
font-size: 13vh;
|
||||
padding-left: 10px;
|
||||
padding-right: 20px;
|
||||
font-weight: bold;
|
||||
flex: 2 2 auto;
|
||||
align-self: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 85vh;
|
||||
background-color: var(--backColor);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 4px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
}
|
||||
|
||||
.priority {
|
||||
width: 90%;
|
||||
height: 20%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
animation: blink 2s 3;
|
||||
margin-top: 50%;
|
||||
background-color: white;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.priority_white {
|
||||
width: 90%;
|
||||
height: 20%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
animation: blink_white 2s 3;
|
||||
margin-top: 50%;
|
||||
background-color: black;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.priority_small {
|
||||
width: 80%;
|
||||
height: 15%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
/* animation: blink 2s infinite; */
|
||||
margin-top: 60%;
|
||||
margin-left: 20px;
|
||||
background-color: #bbb;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.score {
|
||||
padding-right: 20px;
|
||||
width: 20%;
|
||||
font-size: 12vh;
|
||||
float: right;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.box {
|
||||
height: 100%;
|
||||
width: 19%;
|
||||
float: left;
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.square {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
float: left;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
96
frontend.old/src/routes/draws/+page.svelte
Normal file
96
frontend.old/src/routes/draws/+page.svelte
Normal file
|
@ -0,0 +1,96 @@
|
|||
<script>
|
||||
import Logo from "$lib/img/topscorer_logo_web.png"
|
||||
|
||||
$: heats = [];
|
||||
|
||||
loadHeats();
|
||||
|
||||
async function loadHeats() {
|
||||
const res = await fetch(`/api/loadheats`);
|
||||
const data = await res.json();
|
||||
for (let i in data) {
|
||||
heats = [...heats, data[i]];
|
||||
console.log(`${i} retval: ${JSON.stringify(data[i])}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="header">
|
||||
<img class="img" src={Logo} alt="logo">
|
||||
<span class="title" style="color: aliceblue;">Heat Draws</span>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{#each heats as heat}
|
||||
<table>
|
||||
<tr>
|
||||
{#if heat.status === 'running'}
|
||||
<th colspan="2" class="running">
|
||||
{heat.name} ({heat.number}) {heat.category}
|
||||
</th>
|
||||
{:else if heat.status === 'ended'}
|
||||
<th colspan="2" class="ended">
|
||||
{heat.name} ({heat.number}) {heat.category}
|
||||
</th>
|
||||
{:else}
|
||||
<th colspan="2">
|
||||
{heat.name} ({heat.number}) {heat.category}
|
||||
</th>
|
||||
{/if}
|
||||
</tr>
|
||||
{#each heat.surfers as surfer }
|
||||
<tr>
|
||||
<td>
|
||||
{surfer.name}
|
||||
</td>
|
||||
<td style="background-color: {surfer.color};">
|
||||
{surfer.color}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
<hr>
|
||||
{/each}
|
||||
|
||||
<style>
|
||||
.header {
|
||||
background-color: black;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header .img {
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
.header .title {
|
||||
font-size: 3rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th.running {
|
||||
background-color: green;
|
||||
animation: blinker 2s linear infinite;
|
||||
}
|
||||
|
||||
th.ended {
|
||||
background-color: lightcoral;
|
||||
text-decoration: line-through 1px lightyellow;
|
||||
}
|
||||
|
||||
@keyframes blinker {
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
353
frontend.old/src/routes/mobile/+page.svelte
Normal file
353
frontend.old/src/routes/mobile/+page.svelte
Normal file
|
@ -0,0 +1,353 @@
|
|||
<script>
|
||||
// import { page } from '$app/stores';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
if (dev) {
|
||||
console.log('Dev mode');
|
||||
} else {
|
||||
console.log('Not dev mode');
|
||||
}
|
||||
|
||||
let surfers = [
|
||||
{ name: 'Kanoa Igarashi', color: 'red', score: '4.50', priority: '3' },
|
||||
{ name: 'Griffin Colapinto', color: 'white', score: '5.60', priority: 'P' },
|
||||
{ name: 'Jack Robinson', color: 'blue', score: '6.10', priority: '5' },
|
||||
{ name: 'Gabriel Medina', color: 'green', score: '4.30', priority: '2' },
|
||||
{ name: 'Italo Ferreira', color: 'black', score: '6.50', priority: '4' }
|
||||
];
|
||||
|
||||
let width;
|
||||
// $: activeUrl = $page.url.pathname;
|
||||
|
||||
let event = 'Semifinal';
|
||||
let category = 'U16 man';
|
||||
let heat = 'Heat 1';
|
||||
|
||||
const pad2 = (number) => `00${number}`.slice(-2);
|
||||
|
||||
$: min = 10;
|
||||
$: sec = 25;
|
||||
|
||||
let end = false;
|
||||
|
||||
function updateRemainingTime() {
|
||||
if ((min === 0) & (sec === 0)) {
|
||||
clearInterval(timer);
|
||||
end = true;
|
||||
} else if (sec === 0) {
|
||||
min -= 1;
|
||||
sec = 59;
|
||||
} else {
|
||||
sec -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
updateRemainingTime();
|
||||
|
||||
const timer = setInterval(updateRemainingTime, 1000);
|
||||
|
||||
function Subscribe() {
|
||||
const sse = new EventSource(`/api/sse`);
|
||||
console.log('subscribe');
|
||||
sse.onmessage = (e) => {
|
||||
let Msg = JSON.parse(e.data);
|
||||
console.log(`received: ${JSON.stringify(Msg)}`);
|
||||
if (Msg.mode === 'priority') {
|
||||
console.log(`priority: ${Msg.priority}`);
|
||||
for (let i in surfers) {
|
||||
surfers[i].priority = Msg.priority[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
return () => {
|
||||
sse.close();
|
||||
console.log(`sse closing ${Date.now()}`);
|
||||
};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const unsub = Subscribe();
|
||||
return unsub;
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(timer); // Pulisci il timer quando il componente viene distrutto
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth={width} />
|
||||
|
||||
<div class="header">
|
||||
<span class="title">{event}</span>
|
||||
<span class="title">{category}</span>
|
||||
{#if !end}
|
||||
<span class="timer">{pad2(min)}:{pad2(sec)}</span>
|
||||
{:else}
|
||||
<span class="timer" style="color: red">{pad2(min)}:{pad2(sec)}</span>
|
||||
{/if}
|
||||
<span class="heat">{heat}</span>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
{#each surfers as surfer, id}
|
||||
<div class="box">
|
||||
<div class="square" style="background-color: {surfer.color};">
|
||||
{#if surfer.priority != ''}
|
||||
<span class="priority">{surfer.priority}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text">{surfer.name}</div>
|
||||
<div class="score">{surfer.score}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if width < 768}
|
||||
<div class="footer">
|
||||
<div>waiting for scores</div>
|
||||
<!-- <div class="score">6.00</div>
|
||||
<div class="score">6.00</div>
|
||||
<div class="score">6.00</div>
|
||||
<div class="score">6.00</div>
|
||||
<div class="score">6.00</div> -->
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--backColor: #334;
|
||||
--textColor: white;
|
||||
--maxWidth: (100% - 15px);
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: var(--backColor);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header .title {
|
||||
font-size: 2vh;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
font-weight: bold;
|
||||
flex: 1 1 0;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.header .heat {
|
||||
font-size: 2vh;
|
||||
padding-left: 0px;
|
||||
padding-right: 10px;
|
||||
font-weight: bold;
|
||||
flex: 1 1 auto;
|
||||
align-self: center;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.header .timer {
|
||||
font-size: 5vh;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
font-weight: bold;
|
||||
flex: 2 2 auto;
|
||||
align-self: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
background-color: var(--backColor);
|
||||
padding: 10px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.priority {
|
||||
width: 60%;
|
||||
height: 60%;
|
||||
background-color: white;
|
||||
color: black;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.8rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.square {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 5px;
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative; /* Per il posizionamento del testo */
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 1;
|
||||
font-size: 1.5rem;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.score {
|
||||
float: right;
|
||||
padding-right: 10px;
|
||||
text-align: center;
|
||||
width: 20%;
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: var(--backColor);
|
||||
padding: 10px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
display: flex;
|
||||
font-size: larger;
|
||||
font-weight: bold;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
align-content: center;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* .footer .score {
|
||||
float: right;
|
||||
padding-right: 10px;
|
||||
text-align: center;
|
||||
width: 20%;
|
||||
font-size: 1.5rem;
|
||||
font-weight: lighter;
|
||||
} */
|
||||
|
||||
/* @media screen and (min-width: 768px) {
|
||||
.container {
|
||||
height: 85vh;
|
||||
}
|
||||
|
||||
.priority {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
animation: blink 2s infinite;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0% {
|
||||
background-color: white;
|
||||
}
|
||||
50% {
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
100% {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.square {
|
||||
width: 100%;
|
||||
height: 15vh;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.score {
|
||||
padding-right: 40px;
|
||||
width: 20%;
|
||||
font-size: 14vh;
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 0;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 15px;
|
||||
margin-bottom: 2px;
|
||||
height: 10vh;
|
||||
width: calc(100% - 15px);
|
||||
}
|
||||
|
||||
.header .timer {
|
||||
font-size: 6rem;
|
||||
padding-left: 10px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
} */
|
||||
|
||||
/* @media screen and (min-width: 1280px) {
|
||||
.priority {
|
||||
width: 120px;
|
||||
height: 90%;
|
||||
font-size: 6rem;
|
||||
}
|
||||
|
||||
.square {
|
||||
width: 100%;
|
||||
height: 125px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.score {
|
||||
float: right;
|
||||
padding-right: 40px;
|
||||
width: 20%;
|
||||
font-size: 6rem;
|
||||
}
|
||||
|
||||
.header .timer {
|
||||
font-size: 6rem;
|
||||
padding-left: 10px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1920px) {
|
||||
.priority {
|
||||
width: 200px;
|
||||
font-size: 10rem;
|
||||
}
|
||||
|
||||
.square {
|
||||
width: 100%;
|
||||
height: 205px;
|
||||
border-radius: 5px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.score {
|
||||
padding-right: 40px;
|
||||
width: 20%;
|
||||
font-size: 11rem;
|
||||
}
|
||||
|
||||
.header .timer {
|
||||
font-size: 8rem;
|
||||
padding-left: 10px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
} */
|
||||
</style>
|
399
frontend.old/src/routes/priority/+page.svelte
Normal file
399
frontend.old/src/routes/priority/+page.svelte
Normal file
|
@ -0,0 +1,399 @@
|
|||
<script>
|
||||
// import { page } from '$app/stores';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
if (dev) {
|
||||
console.log('Dev mode');
|
||||
} else {
|
||||
console.log('Not dev mode');
|
||||
}
|
||||
|
||||
let heat_number;
|
||||
let heats = [];
|
||||
$: surfers = [];
|
||||
// { name: 'Kanoa Igarashi', color: 'red', score: '4.50', priority: '3' },
|
||||
// { name: 'Griffin Colapinto', color: 'white', score: '5.60', priority: 'P' },
|
||||
// { name: 'Jack Robinson', color: 'blue', score: '6.10', priority: '5' },
|
||||
// { name: 'Gabriel Medina', color: 'green', score: '4.30', priority: '2' },
|
||||
// { name: 'Italo Ferreira', color: 'black', score: '6.50', priority: '4' }
|
||||
// ];
|
||||
|
||||
let width;
|
||||
// $: activeUrl = $page.url.pathname;
|
||||
|
||||
const pad2 = (number) => `00${number}`.slice(-2);
|
||||
|
||||
$: min = 0;
|
||||
$: sec = 0;
|
||||
|
||||
let end = false;
|
||||
let start = false;
|
||||
|
||||
loadHeats();
|
||||
|
||||
function Subscribe() {
|
||||
const sse = new EventSource(`/api/sse`);
|
||||
console.log('subscribe');
|
||||
sse.onmessage = (e) => {
|
||||
let Msg = JSON.parse(e.data);
|
||||
console.log(`received: ${JSON.stringify(Msg)}`);
|
||||
if (Msg.mode === 'priority') {
|
||||
console.log(`priority: ${Msg.priority}`);
|
||||
for (let i in surfers) {
|
||||
surfers[i].priority = Msg.priority[i];
|
||||
}
|
||||
} else if (Msg.mode === 'time') {
|
||||
// console.log(`duration: ${Msg.duration}`);
|
||||
let min_sec = Msg.duration.split(":");
|
||||
min = min_sec[0];
|
||||
sec = min_sec[1];
|
||||
// console.log(`min & sec = ${min} & ${sec}`);
|
||||
if (!start) {
|
||||
start = true;
|
||||
}
|
||||
} else if (Msg.mode === 'stop') {
|
||||
console.log(`stop duration: ${Msg.duration}`);
|
||||
end = true;
|
||||
start = false;
|
||||
}
|
||||
};
|
||||
return () => {
|
||||
sse.close();
|
||||
console.log(`sse closing ${Date.now()}`);
|
||||
};
|
||||
}
|
||||
|
||||
async function dblclick(id) {
|
||||
console.log(`dblclick = ${surfers[id]}`);
|
||||
if (surfers[id] === 'P') {
|
||||
console.log('pressed P');
|
||||
} else {
|
||||
console.log(`pressed: [${id}] ${surfers[id].priority}`);
|
||||
}
|
||||
const res = await fetch(`/api/stopheat`);
|
||||
const data = await res.json();
|
||||
console.log(`stop: ${JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
async function startHeat() {
|
||||
const res = await fetch(`/api/startheat`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
duration: min+"m",
|
||||
mode: 'time'
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
console.log(`retval: ${JSON.stringify(res)}`);
|
||||
start = true;
|
||||
end = false;
|
||||
}
|
||||
|
||||
async function loadHeats() {
|
||||
const res = await fetch(`/api/loadheats`);
|
||||
const data = await res.json();
|
||||
for (let i in data) {
|
||||
heats[i] = data[i];
|
||||
console.log(`${i} retval: ${JSON.stringify(data[i])}`);
|
||||
}
|
||||
}
|
||||
|
||||
function setHeat(id) {
|
||||
console.log(`setHeat: ${id}`);
|
||||
if (id === "99") {
|
||||
min = 0;
|
||||
surfers = []
|
||||
return;
|
||||
}
|
||||
min = heats[id].timer;
|
||||
surfers = heats[id].surfers;
|
||||
}
|
||||
|
||||
async function click(id) {
|
||||
let max = surfers.length;
|
||||
console.log(surfers[id]);
|
||||
if (surfers[id].priority === 'P') {
|
||||
for (let i in surfers) {
|
||||
if (i != id) {
|
||||
let pos = parseInt(surfers[i].priority) - 1;
|
||||
if (pos === 1) {
|
||||
surfers[i].priority = 'P';
|
||||
} else {
|
||||
surfers[i].priority = pos.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
surfers[id].priority = max.toString();
|
||||
} else if (surfers[id].priority === '') {
|
||||
console.log(`priority empty; pressed: [${id}] ${surfers[id].priority}`);
|
||||
for (let i in surfers) {
|
||||
console.log(`looping(${id}): ${i} - ${surfers[i].priority}`);
|
||||
if (i != id) {
|
||||
if (surfers[i].priority === '') {
|
||||
console.log(`empty: [${i}] ${surfers[i].priority}`);
|
||||
continue;
|
||||
} else {
|
||||
console.log(`not empty: [${i}] ${surfers[i].priority}`);
|
||||
let pos = parseInt(surfers[i].priority) - 1;
|
||||
if (pos === 1) {
|
||||
surfers[i].priority = 'P';
|
||||
} else {
|
||||
surfers[i].priority = pos.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
surfers[id].priority = max.toString();
|
||||
} else {
|
||||
console.log(`pressed: [${id}] ${surfers[id].priority}`);
|
||||
let oldpos = parseInt(surfers[id].priority);
|
||||
for (let i in surfers) {
|
||||
if (i != id) {
|
||||
console.log(`pos: [${i}] ${surfers[i].priority} ${surfers[i].priority > oldpos}`);
|
||||
if (surfers[i].priority != 'P' && surfers[i].priority > oldpos) {
|
||||
let pos = parseInt(surfers[i].priority);
|
||||
if (pos > oldpos) {
|
||||
surfers[i].priority = (pos - 1).toString();
|
||||
console.log(`newpos: ${surfers[i].priority}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
surfers[i].priority = max.toString();
|
||||
console.log(`last: [${i}] ${surfers[i].priority}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
const res = await fetch(`/api/priority`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
priority: surfers.map((obj) => obj.priority),
|
||||
mode: 'priority'
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
console.log(
|
||||
JSON.stringify({
|
||||
priority: surfers.map((obj) => obj.priority),
|
||||
mode: 'priority'
|
||||
})
|
||||
);
|
||||
console.log(`retval: ${JSON.stringify(res)}`);
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const unsub = Subscribe();
|
||||
return unsub;
|
||||
});
|
||||
|
||||
// onDestroy(() => {
|
||||
// clearInterval(timer); // Pulisci il timer quando il componente viene distrutto
|
||||
// });
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth={width} />
|
||||
|
||||
<div class="header">
|
||||
<!-- <button class="button" on:click={() => loadHeats()} disabled={start}>Load</button> -->
|
||||
<select name="heats" id="heats" bind:value={heat_number} on:change={() => setHeat(heat_number)}>
|
||||
<option value="99">Select Heat</option>
|
||||
{#each heats as heat, id}
|
||||
<option value={id}>{heat.name} {heat.number} {heat.category}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{#if !end}
|
||||
<div class="timer">{pad2(min)}:{pad2(sec)}</div>
|
||||
{:else}
|
||||
<div class="timer" style="color: red">{pad2(min)}:{pad2(sec)}</div>
|
||||
{/if}
|
||||
<button class="button" on:click={() => startHeat()} disabled={start}>Start</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
{#each surfers as surfer, id}
|
||||
<div class="box">
|
||||
<div
|
||||
class="square"
|
||||
{id}
|
||||
style="background-color: {surfer.color};"
|
||||
on:click={() => click(id)}
|
||||
on:contextmenu={(e) => {
|
||||
e.preventDefault();
|
||||
dblclick(id);
|
||||
}}
|
||||
on:keypress={console.log('keypress')}
|
||||
role="button"
|
||||
tabindex={id}
|
||||
>
|
||||
{#if surfer.priority != ''}
|
||||
{#if surfer.priority === 'P'}
|
||||
{#if surfer.color === 'white'}
|
||||
<span class="priority_white">{surfer.priority}</span>
|
||||
{:else}
|
||||
<span class="priority">{surfer.priority}</span>
|
||||
{/if}
|
||||
{:else}
|
||||
<span class="priority_small">{surfer.priority}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="score">{surfer.score}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--backColor: #334;
|
||||
--textColor: white;
|
||||
--maxWidth: (100% - 15px);
|
||||
}
|
||||
|
||||
.header {
|
||||
/* padding: 15px; */
|
||||
height: 10vh;
|
||||
background-color: var(--backColor);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header .timer {
|
||||
font-size: 13vh;
|
||||
padding-left: 10px;
|
||||
padding-right: 20px;
|
||||
font-weight: bold;
|
||||
flex: 2 2 auto;
|
||||
align-self: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header .button {
|
||||
height: 60%;
|
||||
align-items: center;
|
||||
background-color: yellow;
|
||||
border-radius: 10%;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 85vh;
|
||||
background-color: var(--backColor);
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 4px;
|
||||
width: calc(var(--maxWidth));
|
||||
color: var(--textColor);
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.priority {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
/* animation: blink 2s 2; */
|
||||
margin-right: auto;
|
||||
background-color: white;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.priority_white {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
/* animation: blink_white 2s 3; */
|
||||
margin-right: auto;
|
||||
background-color: black;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.priority_small {
|
||||
width: 13%;
|
||||
height: 85%;
|
||||
border-radius: 20%;
|
||||
font-size: 8vh;
|
||||
/* animation: blink 2s 3; */
|
||||
margin-right: auto;
|
||||
margin-left: 30px;
|
||||
background-color: #ccc;
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.square {
|
||||
width: 100%;
|
||||
height: 16vh;
|
||||
border-radius: 5px;
|
||||
margin-right: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-bottom: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.score {
|
||||
padding-right: 20px;
|
||||
width: 20%;
|
||||
font-size: 12vh;
|
||||
float: right;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0% {
|
||||
background-color: white;
|
||||
}
|
||||
50% {
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
100% {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blink_white {
|
||||
0% {
|
||||
background-color: black;
|
||||
}
|
||||
50% {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
100% {
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
</style>
|
376
frontend.old/src/routes/setup/+page.svelte
Normal file
376
frontend.old/src/routes/setup/+page.svelte
Normal file
|
@ -0,0 +1,376 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import Logo from "$lib/img/topscorer_logo_web.png"
|
||||
|
||||
let colors = [
|
||||
"black",
|
||||
"blue",
|
||||
"red",
|
||||
"green",
|
||||
"yellow",
|
||||
"pink",
|
||||
"white",
|
||||
];
|
||||
|
||||
let rounds = [
|
||||
"Qualifying",
|
||||
"Opening",
|
||||
"Elimination",
|
||||
"Round of 48",
|
||||
"Round of 32",
|
||||
"Round of 16",
|
||||
"Quarterfinal",
|
||||
"Semifinal",
|
||||
"Final",
|
||||
];
|
||||
|
||||
let categories = [
|
||||
"Under 12 Women",
|
||||
"Under 12 Men",
|
||||
"Under 14 Women",
|
||||
"Under 14 Men",
|
||||
"Under 16 Women",
|
||||
"Under 16 Men",
|
||||
"Under 18 Women",
|
||||
"Under 18 Men",
|
||||
];
|
||||
|
||||
$: surfers = 2;
|
||||
|
||||
$: heats = [];
|
||||
let surfer_list = [];
|
||||
$: heat = {};
|
||||
|
||||
resetHeat();
|
||||
loadHeats();
|
||||
|
||||
function resetHeat() {
|
||||
surfers = 2;
|
||||
surfer_list = new Array();
|
||||
surfer_list.push({
|
||||
name: '',
|
||||
color: '',
|
||||
score: '',
|
||||
priority: ''
|
||||
});
|
||||
surfer_list.push({
|
||||
name: '',
|
||||
color: '',
|
||||
score: '',
|
||||
priority: ''
|
||||
});
|
||||
|
||||
heat = {
|
||||
number: 1,
|
||||
name: '',
|
||||
category: '',
|
||||
timer: 20,
|
||||
surfers: surfer_list
|
||||
}
|
||||
}
|
||||
|
||||
async function loadHeats() {
|
||||
const res = await fetch(`/api/loadheats`);
|
||||
const data = await res.json();
|
||||
for (let i in data) {
|
||||
heats[i] = data[i];
|
||||
console.log(`${i} retval: ${JSON.stringify(data[i])}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteHeat(id) {
|
||||
const res = await fetch(`/api/deleteheat`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(heats[id]),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
console.log(`retval: ${JSON.stringify(res)}`);
|
||||
|
||||
console.log(JSON.stringify(heats[id]));
|
||||
resetHeat();
|
||||
loadHeats();
|
||||
}
|
||||
|
||||
function setHeat(id) {
|
||||
resetHeat();
|
||||
console.log(`setHeat: ${id}`);
|
||||
console.log(heats[id]);
|
||||
heat.number = heats[id].number;
|
||||
heat.name = heats[id].name;
|
||||
heat.category = heats[id].category;
|
||||
heat.timer = heats[id].timer;
|
||||
surfer_list = heats[id].surfers;
|
||||
surfers = surfer_list.length;
|
||||
}
|
||||
|
||||
function addSurfers() {
|
||||
surfers++;
|
||||
surfer_list.push({
|
||||
name: '',
|
||||
color: '',
|
||||
score: '',
|
||||
priority: ''
|
||||
});
|
||||
}
|
||||
|
||||
function removeSurfers() {
|
||||
surfers--;
|
||||
if (surfers < 2) surfers = 2;
|
||||
surfer_list.pop();
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if(hasDuplicateColors(surfer_list)) {
|
||||
alert('Colors must be unique');
|
||||
return;
|
||||
}
|
||||
|
||||
if(surfer_list.length < 2) {
|
||||
alert('Must have at least 2 surfers');
|
||||
return;
|
||||
}
|
||||
|
||||
if(heat.name === '') {
|
||||
alert('Must have a name');
|
||||
return;
|
||||
}
|
||||
|
||||
if(heat.category === '') {
|
||||
alert('Must have a category');
|
||||
return;
|
||||
}
|
||||
|
||||
if(heat.number === '') {
|
||||
alert('Must have a number');
|
||||
return;
|
||||
}
|
||||
|
||||
if(heat.timer === '') {
|
||||
alert('Must have a timer');
|
||||
return;
|
||||
}
|
||||
|
||||
heat.surfers = surfer_list;
|
||||
|
||||
const res = await fetch(`/api/saveheat`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(heat),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
console.log(`retval: ${JSON.stringify(res)}`);
|
||||
|
||||
console.log(JSON.stringify(heat));
|
||||
|
||||
resetHeat();
|
||||
loadHeats();
|
||||
}
|
||||
|
||||
function hasDuplicateColors(arr) {
|
||||
const colors = [];
|
||||
|
||||
console.log(JSON.stringify(arr));
|
||||
|
||||
for(let i = 0; i < arr.length; i++) {
|
||||
const color = arr[i].color;
|
||||
|
||||
if(colors.includes(color)) {
|
||||
console.log(`duplicate color: ${color}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
colors.push(color);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function capitalize(element, elementName) {
|
||||
element[elementName] = element[elementName].charAt(0).toUpperCase() + element[elementName].slice(1);
|
||||
console.log(`element: ${element[elementName]}`);
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
resetHeat();
|
||||
loadHeats();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="header">
|
||||
<img class="img" src={Logo} alt="logo">
|
||||
<span class="title" style="color: aliceblue;">Heat setup</span>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="heat">
|
||||
<label class="label" for="heat">Heat</label>
|
||||
<select name="heat" id="heat" bind:value={heat.name}>
|
||||
{#each rounds as round}
|
||||
<option value={round}>{round}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<!-- <input bind:value={heat.name} on:change={capitalize(heat, "name")} id="name" type="text"> -->
|
||||
<label class="label" for="number">Number</label>
|
||||
<input bind:value={heat.number} id="number" type="number" min="1" max="20">
|
||||
<label class="label" for="category">Category</label>
|
||||
<select name="category" id="category" bind:value={heat.category}>
|
||||
{#each categories as category}
|
||||
<option value={category}>{category}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<!-- <input bind:value={heat.category} on:change={capitalize(heat, "category")} id="category" type="text"> -->
|
||||
<label class="label" for="timer">Duration</label>
|
||||
<input bind:value={heat.timer} id="timer" type="number" min="5" max="60" step="5"> <!-- on:keydown={(event) => {event.preventDefault()}} -->
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<button class="plus" on:click={() => {addSurfers();}}>+</button>
|
||||
<span class="surfers">{surfers}</span>
|
||||
<button class="plus" on:click={() => {removeSurfers();}}>-</button>
|
||||
|
||||
|
||||
{#each Array(surfers) as _, surfer}
|
||||
<div class="surfer">
|
||||
<label class="label" for="name{surfer}">Name</label>
|
||||
<input bind:value={surfer_list[surfer].name} on:change={capitalize(surfer_list[surfer], "name")} id="name{surfer}" type="text">
|
||||
<label class="label" for="color{surfer}">Color</label>
|
||||
<select name="color" id="color{surfer}" bind:value={surfer_list[surfer].color} style="background-color: {surfer_list[surfer].color};">
|
||||
{#each colors as color}
|
||||
<option value={color} style="background-color: {color};">{color}</option>
|
||||
{/each}
|
||||
<!-- <option value="red" style="background-color: red;">Select color</option> -->
|
||||
<!-- <option value="red" style="background-color: red;">Red</option>
|
||||
<option value="blue" style="background-color: blue;">Blue</option>
|
||||
<option value="green" style="background-color: green;">Green</option>
|
||||
<option value="yellow" style="background-color: yellow;">Yellow</option>
|
||||
<option value="orange" style="background-color: orange;">Orange</option>
|
||||
<option value="violet" style="background-color: violet;">Violet</option> -->
|
||||
</select>
|
||||
<!-- <input bind:value={surfer_list[surfer].color} type="color" id="color{surfer}"> -->
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
</div>
|
||||
|
||||
<button class="plus" on:click={() => {save();}}>SAVE</button>
|
||||
<button class="plus" on:click={() => {resetHeat();}}>RESET</button>
|
||||
<hr>
|
||||
{#each heats as h, id}
|
||||
<div class="surfer">
|
||||
<button on:click={() => {setHeat(id);}}>{h.name} {h.number} {h.category}</button>
|
||||
<button class="plus" on:click={() => {deleteHeat(id);}}>X</button>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
<!-- <hr> -->
|
||||
|
||||
<!-- <h2>{JSON.stringify(surfer_list)}</h2> -->
|
||||
|
||||
<style>
|
||||
|
||||
.container {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: black;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header .img {
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
.header .title {
|
||||
font-size: 3rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.label {
|
||||
border: 2px solid #555;
|
||||
background-color: gray;
|
||||
border-radius: 8px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.heat {
|
||||
font-size: 1.3rem;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 2px;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
/* color: lightcyan; */
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.heat input {
|
||||
font-size: 1.2rem;
|
||||
border-radius: 6px;
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.1rem;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.heat select {
|
||||
font-size: 1.2rem;
|
||||
border-radius: 6px;
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.1rem;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
|
||||
.surfer {
|
||||
font-size: 1.3rem;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
/* color: lightcyan; */
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.surfer input {
|
||||
font-size: 1.2rem;
|
||||
border-radius: 6px;
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.1rem;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
|
||||
}
|
||||
|
||||
.surfer select {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.plus {
|
||||
border-radius: 8px;
|
||||
margin-left: 0.2rem;
|
||||
margin-right: 0.2rem;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.surfers {
|
||||
border: 1px solid #111;
|
||||
background-color: yellow;
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
</style>
|
BIN
frontend.old/static/favicon.png
Normal file
BIN
frontend.old/static/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
22
frontend.old/svelte.config.js
Normal file
22
frontend.old/svelte.config.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||
// import adapter from '@sveltejs/adapter-auto';
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||
adapter: adapter({
|
||||
pages: '../backend/static',
|
||||
assets: '../backend/static',
|
||||
fallback: 'index.html',
|
||||
precompress: true,
|
||||
strict: true
|
||||
})
|
||||
},
|
||||
preprocess: [vitePreprocess({})]
|
||||
};
|
||||
|
||||
export default config;
|
14
frontend.old/vite.config.js
Normal file
14
frontend.old/vite.config.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
sass: {
|
||||
additionalData: '@use "src/variables.sass" as *'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue