This commit is contained in:
parent
9d0dbc520b
commit
c80eb89db7
34 changed files with 560 additions and 565 deletions
|
@ -1,40 +1,40 @@
|
||||||
{
|
{
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build && ./add-sigint.sh",
|
"build": "vite build && ./add-sigint.sh",
|
||||||
"add-sigint": "./add-sigint.sh",
|
"add-sigint": "./add-sigint.sh",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
||||||
"format": "prettier --plugin-search-dir . --write ."
|
"format": "prettier --plugin-search-dir . --write ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-node": "^4.0.1",
|
"@sveltejs/adapter-node": "^4.0.1",
|
||||||
"@sveltejs/kit": "^2.5.2",
|
"@sveltejs/kit": "^2.5.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
||||||
"@types/leaflet": "^1.9.8",
|
"@types/leaflet": "^1.9.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||||
"@typescript-eslint/parser": "^7.1.1",
|
"@typescript-eslint/parser": "^7.1.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.35.1",
|
"eslint-plugin-svelte": "^2.35.1",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-svelte": "^3.2.2",
|
"prettier-plugin-svelte": "^3.2.2",
|
||||||
"svelte": "^4.2.12",
|
"svelte": "^4.2.12",
|
||||||
"svelte-check": "^3.6.6",
|
"svelte-check": "^3.6.6",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^5.1.5"
|
"vite": "^5.1.5"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/sveltekit": "^7.105.0",
|
"@sentry/sveltekit": "^7.105.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"leaflet-gpx": "^1.7.0",
|
"leaflet-gpx": "^1.7.0",
|
||||||
"svelte-preprocess": "^5.1.3"
|
"svelte-preprocess": "^5.1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
90
frontend/src/app.d.ts
vendored
90
frontend/src/app.d.ts
vendored
|
@ -9,51 +9,50 @@ declare global {
|
||||||
// interface PageData {}
|
// interface PageData {}
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
interface Category {
|
interface Category {
|
||||||
"id": 1,
|
id: 1;
|
||||||
"name_it": "Natura",
|
name_it: 'Natura';
|
||||||
"name_en": "Nature",
|
name_en: 'Nature';
|
||||||
"description_it": "Giri nella natura",
|
description_it: 'Giri nella natura';
|
||||||
"description_en": "Countryside routes",
|
description_en: 'Countryside routes';
|
||||||
"icon": "",
|
icon: '';
|
||||||
"created_at": null,
|
created_at: null;
|
||||||
"updated_at": null,
|
updated_at: null;
|
||||||
"deleted_at": null,
|
deleted_at: null;
|
||||||
"color": string,
|
color: string;
|
||||||
"cover": string,
|
cover: string;
|
||||||
}
|
}
|
||||||
interface Sport {
|
interface Sport {
|
||||||
"id": 1,
|
id: 1;
|
||||||
"name_it": "Trekking",
|
name_it: 'Trekking';
|
||||||
"name_en": "Trekking",
|
name_en: 'Trekking';
|
||||||
"description_it": "Percorso escursionistico",
|
description_it: 'Percorso escursionistico';
|
||||||
"description_en": "Trekking route",
|
description_en: 'Trekking route';
|
||||||
"icon": "",
|
icon: '';
|
||||||
"created_at": "2023-10-31T18:37:30.000000Z",
|
created_at: '2023-10-31T18:37:30.000000Z';
|
||||||
"updated_at": null,
|
updated_at: null;
|
||||||
"deleted_at": null
|
deleted_at: null;
|
||||||
}
|
}
|
||||||
interface SportDetails {
|
interface SportDetails {
|
||||||
id: 1,
|
id: 1;
|
||||||
route_id: 1,
|
route_id: 1;
|
||||||
sport_id: 1,
|
sport_id: 1;
|
||||||
short_description_it: "Percorso escursionistico intermedio. Buon allenamento richiesto. Sentieri facilmente percorribili. Adatto a ogni livello di abilit\u00e0. ",
|
short_description_it: 'Percorso escursionistico intermedio. Buon allenamento richiesto. Sentieri facilmente percorribili. Adatto a ogni livello di abilit\u00e0. ';
|
||||||
short_description_en: "Intermediate hiking route. Good training required. Easily accessible paths. Suitable for all skill levels.",
|
short_description_en: 'Intermediate hiking route. Good training required. Easily accessible paths. Suitable for all skill levels.';
|
||||||
gpx_path: "",
|
gpx_path: '';
|
||||||
distance: 16800,
|
distance: 16800;
|
||||||
duration: 288,
|
duration: 288;
|
||||||
elevation_gain: 439,
|
elevation_gain: 439;
|
||||||
elevation_loss: null,
|
elevation_loss: null;
|
||||||
altitude_max: 620,
|
altitude_max: 620;
|
||||||
altitude_min: 180,
|
altitude_min: 180;
|
||||||
difficulty_it: "Facile",
|
difficulty_it: 'Facile';
|
||||||
difficulty_en: "Easy",
|
difficulty_en: 'Easy';
|
||||||
route_type_it: "Percorso ad anello",
|
route_type_it: 'Percorso ad anello';
|
||||||
route_type_en: "Ring route",
|
route_type_en: 'Ring route';
|
||||||
created_at: "2023-11-02T10:57:41.000000Z",
|
created_at: '2023-11-02T10:57:41.000000Z';
|
||||||
updated_at: null,
|
updated_at: null;
|
||||||
deleted_at: null,
|
deleted_at: null;
|
||||||
sport: Sport
|
sport: Sport;
|
||||||
|
|
||||||
}
|
}
|
||||||
interface Route {
|
interface Route {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -66,7 +65,7 @@ declare global {
|
||||||
description_it: string;
|
description_it: string;
|
||||||
description_en: string;
|
description_en: string;
|
||||||
route_category_id: number;
|
route_category_id: number;
|
||||||
created_at: "2023-11-02T10:50:07.000000Z";
|
created_at: '2023-11-02T10:50:07.000000Z';
|
||||||
updated_at: null;
|
updated_at: null;
|
||||||
deleted_at: null;
|
deleted_at: null;
|
||||||
route_sport_details: Array<SportDetails>;
|
route_sport_details: Array<SportDetails>;
|
||||||
|
@ -74,9 +73,4 @@ declare global {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export {
|
export { Route, Category, Sport, SportDetails };
|
||||||
Route,
|
|
||||||
Category,
|
|
||||||
Sport,
|
|
||||||
SportDetails
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,50 +1,48 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="it">
|
<html lang="it">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<link rel="manifest" href="manifest.json" />
|
||||||
|
|
||||||
<head>
|
%sveltekit.head%
|
||||||
<meta charset="utf-8" />
|
</head>
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<style>
|
||||||
<meta name="viewport" content="width=device-width" />
|
:root {
|
||||||
<link rel="manifest" href="manifest.json" />
|
--footer-height: 108px;
|
||||||
|
--accent-color: #213c8b;
|
||||||
|
--pianello-red: #de0e1b;
|
||||||
|
--pianello-yellow: #f6ae04;
|
||||||
|
--pianello-blue: #213c8b;
|
||||||
|
--card-background-color: #f9f4f1;
|
||||||
|
}
|
||||||
|
|
||||||
%sveltekit.head%
|
* {
|
||||||
</head>
|
box-sizing: border-box;
|
||||||
<style>
|
}
|
||||||
:root {
|
|
||||||
--footer-height: 108px;
|
|
||||||
--accent-color: #213c8b;
|
|
||||||
--pianello-red: #de0e1b;
|
|
||||||
--pianello-yellow: #f6ae04;
|
|
||||||
--pianello-blue: #213c8b;
|
|
||||||
--card-background-color: #f9f4f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
html {
|
||||||
box-sizing: border-box;
|
width: 100%;
|
||||||
}
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
margin: 0px;
|
||||||
|
background-color: #fff;
|
||||||
|
font-family: 'Roboto-Regular';
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
@font-face {
|
||||||
width: 100%;
|
font-family: 'Roboto-Regular';
|
||||||
height: 100%;
|
src: url('/fonts/roboto/Roboto-Regular.ttf') format('TrueType');
|
||||||
margin: 0px;
|
}
|
||||||
background-color: #fff;
|
</style>
|
||||||
font-family: 'Roboto-Regular';
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Roboto-Regular';
|
|
||||||
src: url('/fonts/roboto/Roboto-Regular.ttf') format('TrueType');
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<body data-sveltekit-preload-data="hover">
|
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,42 +1,41 @@
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--footer-height: calc(68px + 20px + 20px);
|
--footer-height: calc(68px + 20px + 20px);
|
||||||
--accent-color: #213c8b;
|
--accent-color: #213c8b;
|
||||||
--pianello-red: #de0e1b;
|
--pianello-red: #de0e1b;
|
||||||
--pianello-yellow: #f6ae04;
|
--pianello-yellow: #f6ae04;
|
||||||
--pianello-blue: #213c8b;
|
--pianello-blue: #213c8b;
|
||||||
--card-background-color: #f9f4f1;
|
--card-background-color: #f9f4f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
font-family: 'Roboto-Regular';
|
font-family: 'Roboto-Regular';
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
header,
|
header,
|
||||||
main,
|
main,
|
||||||
footer {
|
footer {
|
||||||
background: white;
|
background: white;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Roboto-Regular';
|
font-family: 'Roboto-Regular';
|
||||||
src: url('/fonts/roboto/Roboto-Regular.ttf') format('TrueType');
|
src: url('/fonts/roboto/Roboto-Regular.ttf') format('TrueType');
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
.header {
|
.header {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: black;
|
color: black;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
padding-right: 25px;
|
padding-right: 25px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,41 @@
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
<head>
|
body {
|
||||||
<style>
|
background-image: url(/splash.webp);
|
||||||
* {
|
background-size: cover;
|
||||||
box-sizing: border-box;
|
display: grid;
|
||||||
padding: 0;
|
place-content: center;
|
||||||
margin: 0;
|
height: 100%;
|
||||||
}
|
font-size: 24px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
#status {
|
||||||
background-image: url(/splash.webp);
|
border-right: 1px solid black;
|
||||||
background-size: cover;
|
}
|
||||||
display: grid;
|
p {
|
||||||
place-content: center;
|
padding: 20px;
|
||||||
height: 100%;
|
}
|
||||||
font-size: 24px;
|
</style>
|
||||||
font-family: monospace;
|
</head>
|
||||||
}
|
|
||||||
.wrapper {
|
|
||||||
display: flex;
|
|
||||||
backdrop-filter: blur(5px);
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
#status {
|
|
||||||
border-right: 1px solid black;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="wrapper">
|
|
||||||
<p id="status">Code %sveltekit.status%</p>
|
|
||||||
<p id="message">%sveltekit.error.message%</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<p id="status">Code %sveltekit.status%</p>
|
||||||
|
<p id="message">%sveltekit.error.message%</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,6 +1,6 @@
|
||||||
export async function handleError({ error, event, status, message }) {
|
export async function handleError({ error, event, status, message }) {
|
||||||
const errorId = crypto.randomUUID();
|
const errorId = crypto.randomUUID();
|
||||||
console.error(error)
|
console.error(error);
|
||||||
// console.error(event)
|
// console.error(event)
|
||||||
// console.error(status)
|
// console.error(status)
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -9,7 +9,7 @@ export async function handleFetch({ request, fetch }) {
|
||||||
|
|
||||||
export async function handleError({ error, event, status, message }) {
|
export async function handleError({ error, event, status, message }) {
|
||||||
const errorId = crypto.randomUUID();
|
const errorId = crypto.randomUUID();
|
||||||
console.error(error)
|
console.error(error);
|
||||||
// console.error(event)
|
// console.error(event)
|
||||||
// console.error(status)
|
// console.error(status)
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
box-shadow: 0 0 50px #ccc;
|
box-shadow: 0 0 50px #ccc;
|
||||||
background-color: var(--card-background-color);
|
background-color: var(--card-background-color);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#container > a {
|
#container > a {
|
||||||
|
|
|
@ -1,40 +1,40 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '../../css/header.css';
|
import '../../css/header.css';
|
||||||
|
|
||||||
export const title: string = 'Naturalistici';
|
export const title: string = 'Naturalistici';
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
history.back();
|
history.back();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class='header'>
|
<div class="header">
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<!-- svelte-ignore a11y-missing-attribute -->
|
<!-- svelte-ignore a11y-missing-attribute -->
|
||||||
<a on:click={goBack}>
|
<a on:click={goBack}>
|
||||||
<img class="back" src="/images/black-back-arrow.png" alt="" />
|
<img class="back" src="/images/black-back-arrow.png" alt="" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<img src="/images/app-bar-logo.png" alt="" />
|
<img src="/images/app-bar-logo.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
div {
|
div {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
div a {
|
div a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
div a img {
|
div a img {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
.back {
|
.back {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class='header'>
|
<div class="header">
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<!-- svelte-ignore a11y-missing-attribute -->
|
<!-- svelte-ignore a11y-missing-attribute -->
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {PUBLIC_BACKEND_URL} from '$env/static/public'
|
import { PUBLIC_BACKEND_URL } from '$env/static/public';
|
||||||
|
|
||||||
export let name: string;
|
export let name: string;
|
||||||
export let id: number;
|
export let id: number;
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
export const path = `/paths/${id}`;
|
export const path = `/paths/${id}`;
|
||||||
export let src: string;
|
export let src: string;
|
||||||
|
|
||||||
let image = '/archi.png'
|
let image = '/archi.png';
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 1:
|
case 1:
|
||||||
image = '/archi.png';
|
image = '/archi.png';
|
||||||
|
@ -30,16 +30,16 @@
|
||||||
<div class="bold">{name}</div>
|
<div class="bold">{name}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="route-card-right" style:background-image='url({PUBLIC_BACKEND_URL}{src})' />
|
<div class="route-card-right" style:background-image="url({PUBLIC_BACKEND_URL}{src})" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
a {
|
a {
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 20% minmax(1px,1fr) 20%;
|
grid-template-columns: 20% minmax(1px, 1fr) 20%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: calc(100% - 20px);
|
width: calc(100% - 20px);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {PUBLIC_BACKEND_URL} from '$env/static/public'
|
import { PUBLIC_BACKEND_URL } from '$env/static/public';
|
||||||
|
|
||||||
export let route: App.Route;
|
export let route: App.Route;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a href="/routes/{route.id}">
|
<a href="/routes/{route.id}">
|
||||||
<div id="image" style:background-image="url({PUBLIC_BACKEND_URL}{route.cover})" />
|
<div id="image" style:background-image="url({PUBLIC_BACKEND_URL}{route.cover})" />
|
||||||
<div id='path-holder'>
|
<div id="path-holder">
|
||||||
<p class='path-name'>{route.title_it}</p>
|
<p class="path-name">{route.title_it}</p>
|
||||||
</div>
|
</div>
|
||||||
<div id='duration-holder'>
|
<div id="duration-holder">
|
||||||
<div style='font-size: 15px;'>Dislivello</div>
|
<div style="font-size: 15px;">Dislivello</div>
|
||||||
<p id="duration">{route.elevation_gain}</p>
|
<p id="duration">{route.elevation_gain}</p>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { dev } from '$app/environment'
|
import { dev } from '$app/environment';
|
||||||
|
|
||||||
let visible = dev ? false : true;
|
let visible = dev ? false : true;
|
||||||
let time = 2000;
|
let time = 2000;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if(dev) return
|
if (dev) return;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
visible = false;
|
visible = false;
|
||||||
|
@ -16,9 +16,9 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if visible}
|
{#if visible}
|
||||||
<img class='background' transition:fade src="/splash.webp" alt="splash" />
|
<img class="background" transition:fade src="/splash.webp" alt="splash" />
|
||||||
<div class='wrapper'>
|
<div class="wrapper">
|
||||||
<img transition:fade class='logo' src="/images/splash-logo.png" alt="splash-logo" />
|
<img transition:fade class="logo" src="/images/splash-logo.png" alt="splash-logo" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
let component = InfoTabTrekking;
|
let component = InfoTabTrekking;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
console.log(route)
|
console.log(route);
|
||||||
})
|
});
|
||||||
const dispatchClick = (c: InfoTabTrekking | InfoTabBike | DescTab | MapTab) => {
|
const dispatchClick = (c: InfoTabTrekking | InfoTabBike | DescTab | MapTab) => {
|
||||||
component = c;
|
component = c;
|
||||||
dispatch('tab-click', { component });
|
dispatch('tab-click', { component });
|
||||||
|
@ -21,14 +21,30 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="tabs">
|
<div id="tabs">
|
||||||
<button class:active={component === InfoTabTrekking} on:click={() => dispatchClick(InfoTabTrekking)} id="info-trekking"> <img src='/trekking.svg' alt='trekking'> </button>
|
<button
|
||||||
<button class:active={component === InfoTabBike} on:click={() => dispatchClick(InfoTabBike)} id="info-bike"> <img src='/bike.svg' alt='bike'> </button>
|
class:active={component === InfoTabTrekking}
|
||||||
<button class:active={component === DescTab} on:click={() => dispatchClick(DescTab)} id="desc"> Descrizione</button>
|
on:click={() => dispatchClick(InfoTabTrekking)}
|
||||||
<button class:active={component === MapTab} on:click={() => dispatchClick(MapTab)} id="map"> Mappa</button>
|
id="info-trekking"
|
||||||
|
>
|
||||||
|
<img src="/trekking.svg" alt="trekking" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class:active={component === InfoTabBike}
|
||||||
|
on:click={() => dispatchClick(InfoTabBike)}
|
||||||
|
id="info-bike"
|
||||||
|
>
|
||||||
|
<img src="/bike.svg" alt="bike" />
|
||||||
|
</button>
|
||||||
|
<button class:active={component === DescTab} on:click={() => dispatchClick(DescTab)} id="desc">
|
||||||
|
Descrizione</button
|
||||||
|
>
|
||||||
|
<button class:active={component === MapTab} on:click={() => dispatchClick(MapTab)} id="map">
|
||||||
|
Mappa</button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div id="container">
|
<div id="container">
|
||||||
<div class="tab" bind:this={ref} role="tab">
|
<div class="tab" bind:this={ref} role="tab">
|
||||||
<svelte:component this={component} route={route} />
|
<svelte:component this={component} {route} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -72,7 +88,8 @@
|
||||||
border-bottom: 1px solid black !important;
|
border-bottom: 1px solid black !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#info-bike, #info-trekking {
|
#info-bike,
|
||||||
|
#info-trekking {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script lang='ts'>
|
<script lang="ts">
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
export let route: App.Route;
|
export let route: App.Route;
|
||||||
|
|
|
@ -50,28 +50,28 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#grid {
|
#grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: repeat(3, 33%);
|
grid-template-rows: repeat(3, 33%);
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: white;
|
background: white;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#grid div {
|
#grid div {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
#grid div > p {
|
#grid div > p {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
#grid div p:nth-child(2) {
|
#grid div p:nth-child(2) {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -50,28 +50,28 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#grid {
|
#grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: repeat(3, 33%);
|
grid-template-rows: repeat(3, 33%);
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: white;
|
background: white;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#grid div {
|
#grid div {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
#grid div > p {
|
#grid div > p {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
#grid div p:nth-child(2) {
|
#grid div p:nth-child(2) {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, onDestroy } from 'svelte';
|
import { onMount, onDestroy } from 'svelte';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
const mapMarkerIcon = new URL('/icons/map.png', import.meta.url).href
|
const mapMarkerIcon = new URL('/icons/map.png', import.meta.url).href;
|
||||||
|
|
||||||
export let route;
|
export let route;
|
||||||
const pianelloCoordinates = [43.14, 12.53];
|
const pianelloCoordinates = [43.14, 12.53];
|
||||||
|
@ -14,54 +14,55 @@
|
||||||
let longitude;
|
let longitude;
|
||||||
let accuracy;
|
let accuracy;
|
||||||
let watchPositionId: number;
|
let watchPositionId: number;
|
||||||
const errorMessage = "Geolocation not available";
|
const errorMessage = 'Geolocation not available';
|
||||||
const attribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
|
const attribution =
|
||||||
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
|
||||||
const openStreetMapTile = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
const openStreetMapTile = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||||
|
|
||||||
let errored = false;
|
let errored = false;
|
||||||
|
|
||||||
const watchPosition = async () => {
|
const watchPosition = async () => {
|
||||||
if (!("geolocation" in navigator)) {
|
if (!('geolocation' in navigator)) {
|
||||||
errored = true;
|
errored = true;
|
||||||
throw new Error(errorMessage)
|
throw new Error(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
enableHighAccuracy: true,
|
enableHighAccuracy: true,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
maximumAge: 0,
|
maximumAge: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
function success(pos: GeolocationPosition) {
|
function success(pos: GeolocationPosition) {
|
||||||
const crd = pos.coords;
|
const crd = pos.coords;
|
||||||
|
|
||||||
let string = "";
|
let string = '';
|
||||||
|
|
||||||
latitude = crd.latitude;
|
latitude = crd.latitude;
|
||||||
longitude = crd.longitude;
|
longitude = crd.longitude;
|
||||||
accuracy = crd.accuracy;
|
accuracy = crd.accuracy;
|
||||||
|
|
||||||
const icon = leaflet.icon({
|
const icon = leaflet.icon({
|
||||||
iconUrl: mapMarkerIcon,
|
iconUrl: mapMarkerIcon,
|
||||||
iconSize: [75, 75], // size of the icon
|
iconSize: [75, 75] // size of the icon
|
||||||
});
|
});
|
||||||
userMarker = leaflet.marker([latitude, longitude], {icon}).addTo(map);
|
userMarker = leaflet.marker([latitude, longitude], { icon }).addTo(map);
|
||||||
|
|
||||||
// move the map to have the location in its center
|
// move the map to have the location in its center
|
||||||
map.panTo(userMarker.getLatLng());
|
map.panTo(userMarker.getLatLng());
|
||||||
|
|
||||||
string += "Your current position is:";
|
string += 'Your current position is:';
|
||||||
string += `Latitude : ${crd.latitude}`;
|
string += `Latitude : ${crd.latitude}`;
|
||||||
string += `Longitude: ${crd.longitude}`;
|
string += `Longitude: ${crd.longitude}`;
|
||||||
string += `More or less ${crd.accuracy} meters.`;
|
string += `More or less ${crd.accuracy} meters.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function error(err) {
|
function error(err) {
|
||||||
console.warn(`ERROR(${err.code}): ${err.message}`);
|
console.warn(`ERROR(${err.code}): ${err.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
watchPositionId = navigator.geolocation.watchPosition(success, error, options);
|
watchPositionId = navigator.geolocation.watchPosition(success, error, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderMap = () => {
|
const renderMap = () => {
|
||||||
layerGroup = leaflet.layerGroup();
|
layerGroup = leaflet.layerGroup();
|
||||||
|
@ -75,22 +76,22 @@
|
||||||
|
|
||||||
map.setView(pianelloCoordinates, 13);
|
map.setView(pianelloCoordinates, 13);
|
||||||
|
|
||||||
leaflet
|
leaflet.tileLayer(openStreetMapTile, { attribution }).addTo(map);
|
||||||
.tileLayer(openStreetMapTile, {attribution})
|
};
|
||||||
.addTo(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderGPX = () => {
|
const renderGPX = () => {
|
||||||
const gpx = "/gpx/tidone.gpx"; // URL to your GPX file or the GPX itself
|
const gpx = '/gpx/tidone.gpx'; // URL to your GPX file or the GPX itself
|
||||||
new leafletGPX(gpx, {async: true}).on('loaded', function(e) {
|
new leafletGPX(gpx, { async: true })
|
||||||
map.fitBounds(e.target.getBounds());
|
.on('loaded', function (e) {
|
||||||
}).addTo(map);
|
map.fitBounds(e.target.getBounds());
|
||||||
}
|
})
|
||||||
|
.addTo(map);
|
||||||
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await watchPosition();
|
await watchPosition();
|
||||||
leaflet = await import('leaflet');
|
leaflet = await import('leaflet');
|
||||||
const {GPX} = await import('leaflet-gpx');
|
const { GPX } = await import('leaflet-gpx');
|
||||||
leafletGPX = GPX;
|
leafletGPX = GPX;
|
||||||
|
|
||||||
renderMap();
|
renderMap();
|
||||||
|
@ -115,10 +116,14 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
<link
|
||||||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
rel="stylesheet"
|
||||||
crossorigin=""/>
|
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||||
|
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||||
|
crossorigin=""
|
||||||
|
/>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#map {
|
#map {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
let latitude;
|
let latitude;
|
||||||
let longitude;
|
let longitude;
|
||||||
|
|
||||||
|
onmessage = () => {};
|
||||||
|
|
||||||
onmessage = () => {
|
export {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
export { };
|
|
||||||
|
|
|
@ -1,61 +1,60 @@
|
||||||
import {PUBLIC_BACKEND_URL} from '$env/static/public'
|
import { PUBLIC_BACKEND_URL } from '$env/static/public';
|
||||||
|
|
||||||
const API_URL = `${PUBLIC_BACKEND_URL}/api`
|
const API_URL = `${PUBLIC_BACKEND_URL}/api`;
|
||||||
|
|
||||||
const getAllRoutes = async () => {
|
const getAllRoutes = async () => {
|
||||||
let data = [];
|
let data = [];
|
||||||
|
|
||||||
const response = await fetch(`${API_URL}/all-routes`);
|
const response = await fetch(`${API_URL}/all-routes`);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
data = json;
|
data = json;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getRouteCategories = async () => {
|
const getRouteCategories = async () => {
|
||||||
let data = [];
|
let data = [];
|
||||||
|
|
||||||
const response = await fetch(`${API_URL}/route-categories`);
|
const response = await fetch(`${API_URL}/route-categories`);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
data = json;
|
data = json;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getRouteByCategory = async (categoryId: number) => {
|
const getRouteByCategory = async (categoryId: number) => {
|
||||||
let data = [];
|
let data = [];
|
||||||
const response = await fetch(`${API_URL}/route-by-category/${categoryId}`);
|
const response = await fetch(`${API_URL}/route-by-category/${categoryId}`);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
data = json;
|
data = json;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getRoute = async (routeId: number) => {
|
const getRoute = async (routeId: number) => {
|
||||||
let data = {};
|
let data = {};
|
||||||
const response = await fetch(`${API_URL}/route/${routeId}`);
|
const response = await fetch(`${API_URL}/route/${routeId}`);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
data = json;
|
data = json;
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
const getSport = async (routeId: number, sportId: number) => {
|
const getSport = async (routeId: number, sportId: number) => {
|
||||||
let data = {};
|
let data = {};
|
||||||
const response = await fetch(`${API_URL}/route/${routeId}/${sportId}`);
|
const response = await fetch(`${API_URL}/route/${routeId}/${sportId}`);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
data = json;
|
data = json;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getPlacemarks = async (routeId: number, sportId: number) => {
|
const getPlacemarks = async (routeId: number, sportId: number) => {
|
||||||
let data = {};
|
let data = {};
|
||||||
const response = await fetch(`${API_URL}/getPlacemarks/${routeId}/${sportId}`);
|
const response = await fetch(`${API_URL}/getPlacemarks/${routeId}/${sportId}`);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
data = json;
|
data = json;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
export { getAllRoutes, getPlacemarks, getSport, getRoute, getRouteByCategory, getRouteCategories };
|
export { getAllRoutes, getPlacemarks, getSport, getRoute, getRouteByCategory, getRouteCategories };
|
|
@ -2,7 +2,7 @@
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id='container'>
|
<div id="container">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<p id="status">{$page.status}</p>
|
<p id="status">{$page.status}</p>
|
||||||
<p id="message">{$page.error?.message}</p>
|
<p id="message">{$page.error?.message}</p>
|
||||||
|
@ -22,9 +22,9 @@
|
||||||
display: grid;
|
display: grid;
|
||||||
place-content: center;
|
place-content: center;
|
||||||
height: 100dvh;
|
height: 100dvh;
|
||||||
width: 100dvw;
|
width: 100dvw;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
let node: HTMLElement;
|
let node: HTMLElement;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if(dev) return;
|
if (dev) return;
|
||||||
|
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
addEventListener('load', function () {
|
addEventListener('load', function () {
|
||||||
|
@ -32,8 +32,8 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onNavigate((navigation: { complete: any; }) => {
|
onNavigate((navigation: { complete: any }) => {
|
||||||
if (!(document.startViewTransition)) return;
|
if (!document.startViewTransition) return;
|
||||||
|
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
document?.startViewTransition(async () => {
|
document?.startViewTransition(async () => {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<div id="welcome-message">Benvenuti a <span class="bold">Pianello Val Tidone</span></div>
|
<div id="welcome-message">Benvenuti a <span class="bold">Pianello Val Tidone</span></div>
|
||||||
<div id="route-cards">
|
<div id="route-cards">
|
||||||
{#each categories as category}
|
{#each categories as category}
|
||||||
<Path src={category.cover} color={category.color} name="{category.name_it}" id={category.id} />
|
<Path src={category.cover} color={category.color} name={category.name_it} id={category.id} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -9,7 +9,7 @@ export async function load({ fetch }) {
|
||||||
const response = await fetch(`${API_URL}/route-categories`);
|
const response = await fetch(`${API_URL}/route-categories`);
|
||||||
categories = await response.json();
|
categories = await response.json();
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
error(404, { message: 'API Not Found'});
|
error(404, { message: 'API Not Found' });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { categories };
|
return { categories };
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
import { getRouteByCategory, getRouteCategories } from '$lib/repo.js';
|
|
||||||
import { error } from '@sveltejs/kit';
|
import { error } from '@sveltejs/kit';
|
||||||
import {PUBLIC_BACKEND_URL} from '$env/static/public';
|
import { PUBLIC_BACKEND_URL } from '$env/static/public';
|
||||||
|
|
||||||
const API_URL = `${PUBLIC_BACKEND_URL}/api`;
|
const API_URL = `${PUBLIC_BACKEND_URL}/api`;
|
||||||
|
|
||||||
export async function load({ params, fetch }) {
|
export async function load({ params, fetch }) {
|
||||||
const response = await fetch(`${API_URL}/route-categories`);
|
const response = await fetch(`${API_URL}/route-categories`);
|
||||||
const categories: App.Category[] = await response.json();
|
const categories: App.Category[] = await response.json();
|
||||||
const categoryId = Number(params.slug);
|
const categoryId = Number(params.slug);
|
||||||
|
|
||||||
const category: App.Category = categories.find(c => c.id === categoryId) as App.Category;
|
const category: App.Category = categories.find((c) => c.id === categoryId) as App.Category;
|
||||||
|
|
||||||
if (!category) {
|
if (!category) {
|
||||||
error(404);
|
error(404, { message: 'Path not found' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const response2 = await fetch(`${API_URL}/route-by-category/${categoryId}`);
|
const response2 = await fetch(`${API_URL}/route-by-category/${categoryId}`);
|
||||||
const routes = await response2.json();
|
const routes = await response2.json();
|
||||||
|
|
||||||
const toReturn = {
|
const toReturn = {
|
||||||
category: category.name_it,
|
category: category.name_it,
|
||||||
routes,
|
routes
|
||||||
}
|
};
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
let divider: HTMLDivElement;
|
let divider: HTMLDivElement;
|
||||||
let isMap: boolean = false;
|
let isMap: boolean = false;
|
||||||
|
|
||||||
const tabClick = (event) => {
|
const tabClick = (event) => {
|
||||||
isMap = event.detail.component === MapTab;
|
isMap = event.detail.component === MapTab;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
<div bind:this={divider} id="divider" class:move-to-top={isMap}>
|
<div bind:this={divider} id="divider" class:move-to-top={isMap}>
|
||||||
<div id="banner">
|
<div id="banner">
|
||||||
<p class='path-name'>Percorso <b>{data.name_it}</b></p>
|
<p class="path-name">Percorso <b>{data.name_it}</b></p>
|
||||||
<p id="duration">Dislivello {data?.route_sport_details[0]?.elevation_gain} m</p>
|
<p id="duration">Dislivello {data?.route_sport_details[0]?.elevation_gain} m</p>
|
||||||
</div>
|
</div>
|
||||||
<Tabs on:tab-click={tabClick} route={data}></Tabs>
|
<Tabs on:tab-click={tabClick} route={data}></Tabs>
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { error } from '@sveltejs/kit';
|
import { error } from '@sveltejs/kit';
|
||||||
import {PUBLIC_BACKEND_URL} from '$env/static/public'
|
import { PUBLIC_BACKEND_URL } from '$env/static/public';
|
||||||
|
|
||||||
const API_URL = `${PUBLIC_BACKEND_URL}/api`
|
const API_URL = `${PUBLIC_BACKEND_URL}/api`;
|
||||||
|
|
||||||
export async function load({ params, fetch }) {
|
export async function load({ params, fetch }) {
|
||||||
const routeId = Number(params.slug);
|
const routeId = Number(params.slug);
|
||||||
const response = await fetch(`${API_URL}/route/${routeId}`);
|
const response = await fetch(`${API_URL}/route/${routeId}`);
|
||||||
const route = await response.json();
|
const route = await response.json();
|
||||||
|
|
||||||
if (!route) {
|
if (!route) {
|
||||||
error(404);
|
error(404, { message: 'Route non found' });
|
||||||
}
|
}
|
||||||
|
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
|
@ -9,76 +9,72 @@ import { build, files, version, prerendered } from '$service-worker';
|
||||||
const CACHE = `sw-cache-${version}`;
|
const CACHE = `sw-cache-${version}`;
|
||||||
|
|
||||||
const ASSETS = [
|
const ASSETS = [
|
||||||
...build, // the app itself
|
...build, // the app itself
|
||||||
...files, // everything in `static`,
|
...files, // everything in `static`,
|
||||||
...prerendered // dynamic routes
|
...prerendered // dynamic routes
|
||||||
];
|
];
|
||||||
|
|
||||||
let client;
|
let client;
|
||||||
|
|
||||||
addEventListener('message', event => {
|
addEventListener('message', (event) => {
|
||||||
client = event.source;
|
client = event.source;
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('install', (event) => {
|
self.addEventListener('install', (event) => {
|
||||||
// Create a new cache and add all files to it
|
// Create a new cache and add all files to it
|
||||||
async function addFilesToCache() {
|
async function addFilesToCache() {
|
||||||
const cache = await caches.open(CACHE);
|
const cache = await caches.open(CACHE);
|
||||||
await cache.addAll(ASSETS);
|
await cache.addAll(ASSETS);
|
||||||
}
|
}
|
||||||
|
|
||||||
event.waitUntil(addFilesToCache());
|
event.waitUntil(addFilesToCache());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.addEventListener('activate', (event) => {
|
self.addEventListener('activate', (event) => {
|
||||||
// Remove previous cached data from disk
|
// Remove previous cached data from disk
|
||||||
async function deleteOldCaches() {
|
async function deleteOldCaches() {
|
||||||
for (const key of await caches.keys()) {
|
for (const key of await caches.keys()) {
|
||||||
if (key !== CACHE) await caches.delete(key);
|
if (key !== CACHE) await caches.delete(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event.waitUntil(deleteOldCaches());
|
event.waitUntil(deleteOldCaches());
|
||||||
let channel;
|
let channel;
|
||||||
if(BroadcastChannel) {
|
if (BroadcastChannel) {
|
||||||
channel = new BroadcastChannel('sw-messages');
|
channel = new BroadcastChannel('sw-messages');
|
||||||
channel.postMessage({title: 'Cache Downloaded'});
|
channel.postMessage({ title: 'Cache Downloaded' });
|
||||||
} else {
|
} else {
|
||||||
client.postMessage("Cache Downloaded")
|
client.postMessage('Cache Downloaded');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('fetch', (event) => {
|
self.addEventListener('fetch', (event) => {
|
||||||
// ignore POST requests etc
|
// ignore POST requests etc
|
||||||
if (event.request.method !== 'GET') return;
|
if (event.request.method !== 'GET') return;
|
||||||
|
|
||||||
async function respond() {
|
async function respond() {
|
||||||
const url = new URL(event.request.url);
|
const url = new URL(event.request.url);
|
||||||
const cache = await caches.open(CACHE);
|
const cache = await caches.open(CACHE);
|
||||||
|
|
||||||
// `build`/`files` can always be served from the cache
|
// `build`/`files` can always be served from the cache
|
||||||
if (ASSETS.includes(url.pathname)) {
|
if (ASSETS.includes(url.pathname)) {
|
||||||
return cache.match(url.pathname);
|
return cache.match(url.pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for everything else, try the network first, but
|
// for everything else, try the network first, but
|
||||||
// fall back to the cache if we're offline
|
// fall back to the cache if we're offline
|
||||||
try {
|
try {
|
||||||
const response = await fetch(event.request);
|
const response = await fetch(event.request);
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
cache.put(event.request, response.clone());
|
cache.put(event.request, response.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch {
|
} catch {
|
||||||
return cache.match(event.request);
|
return cache.match(event.request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event.respondWith(respond());
|
event.respondWith(respond());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,47 +1,46 @@
|
||||||
{
|
{
|
||||||
"id": "/",
|
"id": "/",
|
||||||
"name": "PianelloExperience",
|
"name": "PianelloExperience",
|
||||||
"short_name": "PianelloExperience",
|
"short_name": "PianelloExperience",
|
||||||
"start_url": "/",
|
"start_url": "/",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"background_color": "#fff",
|
"background_color": "#fff",
|
||||||
"description": "PianelloExperience",
|
"description": "PianelloExperience",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "images/app-icon-48x48.jpeg",
|
"src": "images/app-icon-48x48.jpeg",
|
||||||
"sizes": "48x48",
|
"sizes": "48x48",
|
||||||
"type": "image/jpeg"
|
"type": "image/jpeg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "images/app-icon-72x72.jpeg",
|
"src": "images/app-icon-72x72.jpeg",
|
||||||
"sizes": "72x72",
|
"sizes": "72x72",
|
||||||
"type": "image/jpeg"
|
"type": "image/jpeg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "images/app-icon-96x96.jpeg",
|
"src": "images/app-icon-96x96.jpeg",
|
||||||
"sizes": "96x96",
|
"sizes": "96x96",
|
||||||
"type": "image/jpeg"
|
"type": "image/jpeg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "images/app-icon-144x144.jpeg",
|
"src": "images/app-icon-144x144.jpeg",
|
||||||
"sizes": "144x144",
|
"sizes": "144x144",
|
||||||
"type": "image/jpeg"
|
"type": "image/jpeg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "images/app-icon-168x168.jpeg",
|
"src": "images/app-icon-168x168.jpeg",
|
||||||
"sizes": "168x168",
|
"sizes": "168x168",
|
||||||
"type": "image/jpeg"
|
"type": "image/jpeg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "images/app-icon-192x192.png",
|
"src": "images/app-icon-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "images/app-icon-512x512.png",
|
"src": "images/app-icon-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import adapter from "@sveltejs/adapter-node";
|
import adapter from '@sveltejs/adapter-node';
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
@ -6,17 +6,17 @@ const config = {
|
||||||
preprocess: vitePreprocess(),
|
preprocess: vitePreprocess(),
|
||||||
kit: {
|
kit: {
|
||||||
files: {
|
files: {
|
||||||
serviceWorker: 'src/sw.ts',
|
serviceWorker: 'src/sw.ts'
|
||||||
},
|
},
|
||||||
serviceWorker: {
|
serviceWorker: {
|
||||||
register: false,
|
register: false
|
||||||
},
|
},
|
||||||
adapter: adapter({
|
adapter: adapter({
|
||||||
fallback: null,
|
fallback: null,
|
||||||
precompress: true,
|
precompress: true,
|
||||||
strict: true
|
strict: true
|
||||||
}),
|
})
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import adapter from "@sveltejs/adapter-node";
|
import adapter from '@sveltejs/adapter-node';
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
plugins: [
|
plugins: [sveltekit()],
|
||||||
sveltekit(),
|
test: {
|
||||||
],
|
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||||
test: {
|
},
|
||||||
include: ["src/**/*.{test,spec}.{js,ts}"],
|
build: {
|
||||||
},
|
minify: 'esbuild',
|
||||||
build: {
|
target: 'esnext'
|
||||||
minify: "esbuild",
|
},
|
||||||
target: "esnext",
|
kit: {
|
||||||
},
|
adapter: adapter({
|
||||||
kit: {
|
precompress: false
|
||||||
adapter: adapter({
|
})
|
||||||
precompress: false,
|
}
|
||||||
})
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
Loading…
Reference in a new issue