First Layout with Leaflet map and centered slot for overlays

This commit is contained in:
2025-03-24 18:53:57 +01:00
parent 00b340307b
commit ca65d2986e
8 changed files with 127 additions and 12 deletions

View File

@@ -19,6 +19,7 @@
"@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/vite": "^4.0.0",
"@types/leaflet": "^1.9.17",
"daisyui": "^5.0.9",
"eslint": "^9.18.0",
"eslint-plugin-svelte": "^3.0.0",
@@ -34,7 +35,8 @@
"dependencies": {
"@inlang/paraglide-js": "^2.0.0",
"arktype": "^2.1.12",
"formsnap": "^2.0.0"
"formsnap": "^2.0.0",
"leaflet": "^1.9.4"
},
"pnpm": {
"onlyBuiltDependencies": [

23
pnpm-lock.yaml generated
View File

@@ -17,6 +17,9 @@ importers:
formsnap:
specifier: ^2.0.0
version: 2.0.0(svelte@5.25.3)(sveltekit-superforms@2.24.0(@sveltejs/kit@2.20.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.25.3)(vite@6.2.3(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.25.3)(vite@6.2.3(jiti@2.4.2)(lightningcss@1.29.2)))(@types/json-schema@7.0.15)(svelte@5.25.3)(typescript@5.8.2))
leaflet:
specifier: ^1.9.4
version: 1.9.4
devDependencies:
'@eslint/compat':
specifier: ^1.2.5
@@ -36,6 +39,9 @@ importers:
'@tailwindcss/vite':
specifier: ^4.0.0
version: 4.0.15(vite@6.2.3(jiti@2.4.2)(lightningcss@1.29.2))
'@types/leaflet':
specifier: ^1.9.17
version: 1.9.17
daisyui:
specifier: ^5.0.9
version: 5.0.9
@@ -614,9 +620,15 @@ packages:
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
'@types/geojson@7946.0.16':
resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/leaflet@1.9.17':
resolution: {integrity: sha512-IJ4K6t7I3Fh5qXbQ1uwL3CFVbCi6haW9+53oLWgdKlLP7EaS21byWFJxxqOx9y8I0AP0actXSJLVMbyvxhkUTA==}
'@types/validator@13.12.2':
resolution: {integrity: sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==}
@@ -1108,6 +1120,9 @@ packages:
resolution: {integrity: sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==}
engines: {node: '>=14.0.0'}
leaflet@1.9.4:
resolution: {integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==}
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -2047,8 +2062,14 @@ snapshots:
'@types/estree@1.0.7': {}
'@types/geojson@7946.0.16': {}
'@types/json-schema@7.0.15': {}
'@types/leaflet@1.9.17':
dependencies:
'@types/geojson': 7946.0.16
'@types/validator@13.12.2':
optional: true
@@ -2575,6 +2596,8 @@ snapshots:
kysely@0.27.6: {}
leaflet@1.9.4: {}
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1

View File

@@ -1,12 +1,12 @@
<!doctype html>
<html lang="%paraglide.lang%">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<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>
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@@ -1,2 +1,2 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
<h1>Demo Charge.re</h1>
<p>This page can be a view or just a basic redirect to rossinienergy.com</p>

View File

@@ -0,0 +1,40 @@
<script lang="ts">
import { page } from '$app/state';
import type { LayoutProps } from './$types';
let { data, children }: LayoutProps = $props();
const cc = $derived(data.chargecontroller);
const qrcode = $derived(page.params.qrcode);
</script>
<div class="flex flex-col h-screen">
<div class="flex flex-col fixed w-screen h-screen top-0 left-0 overflow-hidden">
<div class="navbar bg-base-100 not-dark:shadow-xl dark:shadow-sm h-16">
<div class="flex-1">
<a class="btn btn-ghost text-xl" href="/">RossiniEnergy</a>
</div>
<div class="flex-none">
<ul class="menu menu-horizontal px-1">
<li><p>QRCODE: {qrcode}</p></li>
<li>
<details>
<summary>PARK: {cc['park']}</summary>
<ul class="bg-base-100 rounded-t-none p-2">
<li><p>EN</p></li>
<li><p>IT</p></li>
</ul>
</details>
</li>
</ul>
</div>
</div>
{#await import('./Map.svelte') then { default: Map }}
<Map class="grow h-10 -z-20" x={cc['latitude']} y={cc['longitude']}/>
{/await}
</div>
<div class="z-20 mt-16 grow pointer-events-none">
<div class="flex justify-center items-center h-full pointer-events-none">
{@render children()}
</div>
</div>
</div>

View File

@@ -0,0 +1,19 @@
import type { LayoutLoad } from './$types';
import { error } from "@sveltejs/kit";
import { type } from "arktype";
const QrcodeType = type("string.integer.parse");
export const load: LayoutLoad = async ({ params, fetch }) => {
const qrcode = QrcodeType(params.qrcode);
if (qrcode instanceof type.errors) error(400, 'invalid qrcode');
const data = await fetch(`/api/v2/chargecontroller/${qrcode}/`, {
method: 'GET',
headers: {
'Accept': 'application/json',
}
});
return {
chargecontroller: await data.json(),
};
};

View File

@@ -0,0 +1,3 @@
<div class="bg-black pointer-events-auto">
TEST CARD
</div>

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import * as L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { onMount } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
type Props = {
x: number,
y: number,
} & SvelteHTMLElements['div']
let { x, y, ...rest }: Props = $props();
let mapDiv: HTMLDivElement;
let map: L.Map;
onMount(() => {
map = L.map(mapDiv).setView([x, y], 13);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
L.marker([x, y]).addTo(map);
});
</script>
<div bind:this={mapDiv} {...rest}>
</div>