Compare commits
3 Commits
ca65d2986e
...
a33c1d8f5b
| Author | SHA1 | Date | |
|---|---|---|---|
| a33c1d8f5b | |||
| ae04d2b7b3 | |||
| 8faa93d976 |
@@ -15,6 +15,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.2.5",
|
"@eslint/compat": "^1.2.5",
|
||||||
"@eslint/js": "^9.18.0",
|
"@eslint/js": "^9.18.0",
|
||||||
|
"@iconify/svelte": "^4.2.0",
|
||||||
"@sveltejs/adapter-auto": "^4.0.0",
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
"@sveltejs/kit": "^2.16.0",
|
"@sveltejs/kit": "^2.16.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
|
|||||||
18
pnpm-lock.yaml
generated
18
pnpm-lock.yaml
generated
@@ -27,6 +27,9 @@ importers:
|
|||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.18.0
|
specifier: ^9.18.0
|
||||||
version: 9.23.0
|
version: 9.23.0
|
||||||
|
'@iconify/svelte':
|
||||||
|
specifier: ^4.2.0
|
||||||
|
version: 4.2.0(svelte@5.25.3)
|
||||||
'@sveltejs/adapter-auto':
|
'@sveltejs/adapter-auto':
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.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)))
|
version: 4.0.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)))
|
||||||
@@ -322,6 +325,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==}
|
resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==}
|
||||||
engines: {node: '>=18.18'}
|
engines: {node: '>=18.18'}
|
||||||
|
|
||||||
|
'@iconify/svelte@4.2.0':
|
||||||
|
resolution: {integrity: sha512-fEl0T7SAPonK7xk6xUlRPDmFDZVDe2Z7ZstlqeDS/sS8ve2uyU+Qa8rTWbIqzZJlRvONkK5kVXiUf9nIc+6OOQ==}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: '>4.0.0'
|
||||||
|
|
||||||
|
'@iconify/types@2.0.0':
|
||||||
|
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||||
|
|
||||||
'@inlang/paraglide-js@2.0.4':
|
'@inlang/paraglide-js@2.0.4':
|
||||||
resolution: {integrity: sha512-5p2Mia2PnwafJQtG6S2UqoHKhqUK7l0goMc5mI6AqQ2lEh14Fkl5uqYwUaI49s6Du4GX5Or1Wp+yBlOA74MKOQ==}
|
resolution: {integrity: sha512-5p2Mia2PnwafJQtG6S2UqoHKhqUK7l0goMc5mI6AqQ2lEh14Fkl5uqYwUaI49s6Du4GX5Or1Wp+yBlOA74MKOQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -1792,6 +1803,13 @@ snapshots:
|
|||||||
|
|
||||||
'@humanwhocodes/retry@0.4.2': {}
|
'@humanwhocodes/retry@0.4.2': {}
|
||||||
|
|
||||||
|
'@iconify/svelte@4.2.0(svelte@5.25.3)':
|
||||||
|
dependencies:
|
||||||
|
'@iconify/types': 2.0.0
|
||||||
|
svelte: 5.25.3
|
||||||
|
|
||||||
|
'@iconify/types@2.0.0': {}
|
||||||
|
|
||||||
'@inlang/paraglide-js@2.0.4':
|
'@inlang/paraglide-js@2.0.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@inlang/recommend-sherlock': 0.2.1
|
'@inlang/recommend-sherlock': 0.2.1
|
||||||
|
|||||||
35
src/lib/FormInput.svelte
Normal file
35
src/lib/FormInput.svelte
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<script lang="ts" generics="T extends Record<string, unknown>">
|
||||||
|
import { Field, Control, FieldErrors } from "formsnap";
|
||||||
|
import type { FormPath, SuperForm } from "sveltekit-superforms";
|
||||||
|
|
||||||
|
let { form, type, label, name }: {
|
||||||
|
form: SuperForm<T>,
|
||||||
|
type: string,
|
||||||
|
label: string,
|
||||||
|
name: FormPath<T>,
|
||||||
|
} = $props();
|
||||||
|
const formData = form.form;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Field {form} {name}>
|
||||||
|
<Control>
|
||||||
|
{#snippet children({ props })}
|
||||||
|
<label class="label floating-label w-full">
|
||||||
|
<span>{label}</span>
|
||||||
|
<input {type} class="input w-full aria-[invalid]:input-error" placeholder={label}
|
||||||
|
bind:value={$formData[name]} {...props}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
{/snippet}
|
||||||
|
</Control>
|
||||||
|
<FieldErrors>
|
||||||
|
{#snippet children({ errors, errorProps })}
|
||||||
|
{#each errors as err, idx (idx)}
|
||||||
|
<p class="text-error" {...errorProps}>{err}</p>
|
||||||
|
{/each}
|
||||||
|
{/snippet}
|
||||||
|
</FieldErrors>
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
49
src/lib/PwdFormInput.svelte
Normal file
49
src/lib/PwdFormInput.svelte
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<script lang="ts" generics="T extends Record<string, unknown>">
|
||||||
|
import { Field, Control, FieldErrors } from "formsnap";
|
||||||
|
import type { FormPath, SuperForm } from "sveltekit-superforms";
|
||||||
|
import { scale } from 'svelte/transition';
|
||||||
|
import Icon from "@iconify/svelte";
|
||||||
|
|
||||||
|
let { form, label, name }: {
|
||||||
|
form: SuperForm<T>,
|
||||||
|
label: string,
|
||||||
|
name: FormPath<T>,
|
||||||
|
} = $props();
|
||||||
|
const formData = form.form;
|
||||||
|
|
||||||
|
let show = $state(false);
|
||||||
|
let type = $derived(show ? 'text' : 'password');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Field {form} {name}>
|
||||||
|
<Control>
|
||||||
|
{#snippet children({ props })}
|
||||||
|
<div class="flex w-full gap-1">
|
||||||
|
<label class="label floating-label w-full">
|
||||||
|
<span>{label}</span>
|
||||||
|
<input {type} class="input w-full aria-[invalid]:input-error" placeholder={label}
|
||||||
|
bind:value={$formData[name]} {...props}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<button class="btn btn-circle grid" onclick={() => show = !show} type="button">
|
||||||
|
{#if show}
|
||||||
|
<span transition:scale class="col-start-1 col-end-2 row-start-1 row-end-2"><Icon
|
||||||
|
icon="mdi:eye-off-outline"/></span>
|
||||||
|
{:else }
|
||||||
|
<span transition:scale class="col-start-1 col-end-2 row-start-1 row-end-2"><Icon
|
||||||
|
icon="mdi:eye-outline"/></span>
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</Control>
|
||||||
|
<FieldErrors>
|
||||||
|
{#snippet children({ errors, errorProps })}
|
||||||
|
{#each errors as err, idx (idx)}
|
||||||
|
<p class="text-error" {...errorProps}>{err}</p>
|
||||||
|
{/each}
|
||||||
|
{/snippet}
|
||||||
|
</FieldErrors>
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
22
src/lib/icons/ConnType2.svelte
Normal file
22
src/lib/icons/ConnType2.svelte
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<svg
|
||||||
|
id="Calque_1"
|
||||||
|
version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 101 92"
|
||||||
|
style="enable-background: new 0 0 101 92"
|
||||||
|
xml:space="preserve"
|
||||||
|
>
|
||||||
|
<path d="M15,40c0,5.5,4.5,10,10,10s10-4.5,10-10s-4.5-10-10-10S15,34.5,15,40z M20,40c0-2.8,2.2-5,5-5s5,2.2,5,5s-2.2,5-5,5
|
||||||
|
S20,42.8,20,40z M27,62c0,5.5,4.5,10,10,10s10-4.5,10-10s-4.5-10-10-10S27,56.5,27,62z M32,62c0-2.8,2.2-5,5-5s5,2.2,5,5s-2.2,5-5,5
|
||||||
|
S32,64.8,32,62z M53,62c0,5.5,4.5,10,10,10s10-4.5,10-10s-4.5-10-10-10S53,56.5,53,62z M58,62c0-2.8,2.2-5,5-5s5,2.2,5,5s-2.2,5-5,5
|
||||||
|
S58,64.8,58,62z M40,40c0,5.5,4.5,10,10,10s10-4.5,10-10s-4.5-10-10-10S40,34.5,40,40z M45,40c0-2.8,2.2-5,5-5s5,2.2,5,5s-2.2,5-5,5
|
||||||
|
S45,42.8,45,40z M65,40c0,5.5,4.5,10,10,10s10-4.5,10-10s-4.5-10-10-10S65,34.5,65,40z M70,40c0-2.8,2.2-5,5-5s5,2.2,5,5s-2.2,5-5,5
|
||||||
|
S70,42.8,70,40z M55,23c0,4.4,3.6,8,8,8s8-3.6,8-8s-3.6-8-8-8S55,18.6,55,23z M60,23c0-1.7,1.3-3,3-3s3,1.3,3,3s-1.3,3-3,3
|
||||||
|
S60,24.7,60,23z M30,23c0,4.4,3.6,8,8,8s8-3.6,8-8s-3.6-8-8-8S30,18.6,30,23z M35,23c0-1.7,1.3-3,3-3s3,1.3,3,3s-1.3,3-3,3
|
||||||
|
S35,24.7,35,23z M0,41.5C0,69.4,22.6,92,50.5,92S101,69.4,101,41.5c0-12.8-5.3-24.1-12.7-33.4C82,0.3,70.8,0,70.8,0H30.7
|
||||||
|
c-2.8,0-11.8,0.2-17.9,7.8C4.9,16.7,0,28.5,0,41.5z M9,42.4C9,32,13,22.5,19.5,15.3C24.4,9.2,31.7,9,34,9h32.5c0,0,9,0.2,14.2,6.5
|
||||||
|
C86.7,23,91,32.1,91,42.4C91,64.8,72.6,83,50,83S9,64.8,9,42.4z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
13
src/routes/+layout.ts
Normal file
13
src/routes/+layout.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import type { LayoutLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: LayoutLoad = async ({ fetch }) => {
|
||||||
|
const user = await fetch('/api/public/1/auth/myself/', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
user: user.ok ? await user.json() : null
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,10 +1,34 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import type { LayoutProps } from './$types';
|
import type { LayoutProps } from './$types';
|
||||||
|
import ConnType2 from "$lib/icons/ConnType2.svelte";
|
||||||
|
import Icon from "@iconify/svelte";
|
||||||
|
import { goto, invalidateAll } from "$app/navigation";
|
||||||
|
|
||||||
let { data, children }: LayoutProps = $props();
|
let { data, children }: LayoutProps = $props();
|
||||||
const cc = $derived(data.chargecontroller);
|
const cc = $derived(data.chargecontroller);
|
||||||
|
const user = $derived(data.user);
|
||||||
const qrcode = $derived(page.params.qrcode);
|
const qrcode = $derived(page.params.qrcode);
|
||||||
|
|
||||||
|
let logouting = $state(false);
|
||||||
|
|
||||||
|
async function logout() {
|
||||||
|
logouting = true;
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/public/1/auth/logout/", {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
await invalidateAll();
|
||||||
|
await goto(`/${qrcode}`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
logouting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col h-screen">
|
<div class="flex flex-col h-screen">
|
||||||
@@ -15,21 +39,50 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex-none">
|
<div class="flex-none">
|
||||||
<ul class="menu menu-horizontal px-1">
|
<ul class="menu menu-horizontal px-1">
|
||||||
<li><p>QRCODE: {qrcode}</p></li>
|
<li><p>
|
||||||
|
{#if user}
|
||||||
|
{user['username']}
|
||||||
|
{:else}
|
||||||
|
No User
|
||||||
|
{/if}
|
||||||
|
</p></li>
|
||||||
<li>
|
<li>
|
||||||
<details>
|
<details>
|
||||||
<summary>PARK: {cc['park']}</summary>
|
<summary>
|
||||||
|
EN
|
||||||
|
</summary>
|
||||||
<ul class="bg-base-100 rounded-t-none p-2">
|
<ul class="bg-base-100 rounded-t-none p-2">
|
||||||
<li><p>EN</p></li>
|
<li><p>EN</p></li>
|
||||||
<li><p>IT</p></li>
|
<li><p>IT</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<button class={["h-full w-full", logouting && "bg-gray-300"]} onclick={logout}>
|
||||||
|
<Icon class="h-5 w-5" icon="mdi:logout"/>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#await import('./Map.svelte') then { default: Map }}
|
{#await import('./Map.svelte') then { default: Map }}
|
||||||
<Map class="grow h-10 -z-20" x={cc['latitude']} y={cc['longitude']}/>
|
<Map class="grow h-10 -z-20" x={cc['latitude']} y={cc['longitude']}>
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<div class="inline-flex items-center gap-2">
|
||||||
|
<p class="!m-0">Informations</p>
|
||||||
|
<div class="tooltip" data-tip="Type 2">
|
||||||
|
<div class="w-5 h-5">
|
||||||
|
<ConnType2/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full border-b border-b-gray-300"></div>
|
||||||
|
<div class="inline-flex items-center gap-2">
|
||||||
|
<Icon class="h-5 w-5 text-success" icon="mdi:checkbox-marked-circle"/>
|
||||||
|
<p class="!m-0">Disponibile</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Map>
|
||||||
{/await}
|
{/await}
|
||||||
</div>
|
</div>
|
||||||
<div class="z-20 mt-16 grow pointer-events-none">
|
<div class="z-20 mt-16 grow pointer-events-none">
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ import { type } from "arktype";
|
|||||||
|
|
||||||
const QrcodeType = type("string.integer.parse");
|
const QrcodeType = type("string.integer.parse");
|
||||||
|
|
||||||
export const load: LayoutLoad = async ({ params, fetch }) => {
|
export const load: LayoutLoad = async ({ params, fetch, parent }) => {
|
||||||
const qrcode = QrcodeType(params.qrcode);
|
const qrcode = QrcodeType(params.qrcode);
|
||||||
if (qrcode instanceof type.errors) error(400, 'invalid qrcode');
|
if (qrcode instanceof type.errors) error(400, 'invalid qrcode');
|
||||||
const data = await fetch(`/api/v2/chargecontroller/${qrcode}/`, {
|
const cc = await fetch(`/api/v2/chargecontroller/${qrcode}/`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const parentData = await parent();
|
||||||
return {
|
return {
|
||||||
chargecontroller: await data.json(),
|
...parentData,
|
||||||
|
qrcode: qrcode,
|
||||||
|
chargecontroller: await cc.json(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
<div class="bg-black pointer-events-auto">
|
<div class="bg-black pointer-events-auto">
|
||||||
TEST CARD
|
START CARD
|
||||||
</div>
|
</div>
|
||||||
8
src/routes/[qrcode]/+page.ts
Normal file
8
src/routes/[qrcode]/+page.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { PageLoad } from './$types';
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
export const load: PageLoad = async ({ parent }) => {
|
||||||
|
const parentData = await parent();
|
||||||
|
if (parentData.user === null) return redirect(303, `${parentData.qrcode}/login`);
|
||||||
|
return parentData;
|
||||||
|
};
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as L from 'leaflet';
|
import * as L from 'leaflet';
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
import { onMount } from "svelte";
|
import { onMount, type Snippet } from "svelte";
|
||||||
import type { SvelteHTMLElements } from "svelte/elements";
|
import type { SvelteHTMLElements } from "svelte/elements";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
children?: Snippet,
|
||||||
} & SvelteHTMLElements['div']
|
} & SvelteHTMLElements['div']
|
||||||
|
|
||||||
let { x, y, ...rest }: Props = $props();
|
let { x, y, children, ...rest }: Props = $props();
|
||||||
|
|
||||||
let mapDiv: HTMLDivElement;
|
let mapDiv: HTMLDivElement;
|
||||||
|
let popupDiv: HTMLDivElement;
|
||||||
let map: L.Map;
|
let map: L.Map;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@@ -20,9 +22,16 @@
|
|||||||
maxZoom: 19,
|
maxZoom: 19,
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
L.marker([x, y]).addTo(map);
|
const marker = L.marker([x, y]).addTo(map);
|
||||||
|
if (children !== undefined)
|
||||||
|
marker.bindPopup(popupDiv, { closeOnClick: false }).openPopup();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={mapDiv} {...rest}>
|
<div bind:this={mapDiv} {...rest}>
|
||||||
|
</div>
|
||||||
|
<div class="hidden">
|
||||||
|
<div bind:this={popupDiv} class="h-full w-full">
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
89
src/routes/[qrcode]/login/+page.svelte
Normal file
89
src/routes/[qrcode]/login/+page.svelte
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<script>
|
||||||
|
import { superForm, defaults, setMessage } from 'sveltekit-superforms';
|
||||||
|
import { type } from "arktype";
|
||||||
|
import { arktypeClient } from 'sveltekit-superforms/adapters';
|
||||||
|
import FormInput from "$lib/FormInput.svelte";
|
||||||
|
import PwdFormInput from "$lib/PwdFormInput.svelte";
|
||||||
|
import { goto, invalidateAll } from "$app/navigation";
|
||||||
|
|
||||||
|
let { data } = $props();
|
||||||
|
|
||||||
|
const schema = type({
|
||||||
|
username: 'string > 3',
|
||||||
|
password: 'string > 3',
|
||||||
|
});
|
||||||
|
|
||||||
|
const schemaDefaults = {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = superForm(defaults(schemaDefaults, arktypeClient(schema)), {
|
||||||
|
SPA: true,
|
||||||
|
validators: arktypeClient(schema),
|
||||||
|
resetForm: false,
|
||||||
|
async onUpdate({ form }) {
|
||||||
|
// Equivalent to onSubmit for this context. We can validate and then execute things.
|
||||||
|
if (form.valid) {
|
||||||
|
// Call an external API with form.data, await the result and update form
|
||||||
|
const response = await fetch("/api/public/1/auth/login/", {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(form.data),
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(response.status);
|
||||||
|
|
||||||
|
if (response.status !== 200) {
|
||||||
|
setMessage(form, {
|
||||||
|
status: 'error',
|
||||||
|
text: `HTTP Code ${response.status}:\n${JSON.stringify(await response.json(), null, 2)}`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setMessage(form, {
|
||||||
|
status: 'success',
|
||||||
|
text: 'Login succeded, redirecting...',
|
||||||
|
});
|
||||||
|
await invalidateAll();
|
||||||
|
await goto(`/${data.qrcode}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { message, enhance, submitting } = form;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="pointer-events-auto bg-gray-300/50 h-full w-full flex justify-center items-center">
|
||||||
|
<div class="card bg-base-100 w-fit shadow-md">
|
||||||
|
<form class="card-body" method="POST" use:enhance>
|
||||||
|
<h2 class="card-title">Accesso Utente</h2>
|
||||||
|
<div class="flex flex-col gap-2 my-2">
|
||||||
|
<FormInput {form} type="text" label="Username" name="username"/>
|
||||||
|
<PwdFormInput {form} label="Password" name="password"/>
|
||||||
|
</div>
|
||||||
|
<div class="card-actions justify-center">
|
||||||
|
<button class="btn btn-primary" type="submit">
|
||||||
|
{#if $submitting}
|
||||||
|
<span class="loading"></span>
|
||||||
|
{/if}
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{#if $message}
|
||||||
|
<div class="card bg-base-200 mt-4 card-border max-w-[80vw]">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title" class:text-error={$message['status'] === 'error'}>
|
||||||
|
{$message['status'] === 'success' ? 'Success!' : 'Error'}
|
||||||
|
</h2>
|
||||||
|
<div>
|
||||||
|
{$message['text']}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
8
src/routes/[qrcode]/login/+page.ts
Normal file
8
src/routes/[qrcode]/login/+page.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { PageLoad } from './$types';
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
export const load: PageLoad = async ({ parent }) => {
|
||||||
|
const parentData = await parent();
|
||||||
|
if (parentData.user !== null) return redirect(303, `/${parentData.qrcode}`);
|
||||||
|
return parentData;
|
||||||
|
};
|
||||||
3
src/routes/[qrcode]/status/+page.svelte
Normal file
3
src/routes/[qrcode]/status/+page.svelte
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<div class="bg-black pointer-events-auto">
|
||||||
|
STATUS CARD
|
||||||
|
</div>
|
||||||
8
src/routes/[qrcode]/status/+page.ts
Normal file
8
src/routes/[qrcode]/status/+page.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { PageLoad } from './$types';
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
export const load: PageLoad = async ({ parent }) => {
|
||||||
|
const parentData = await parent();
|
||||||
|
if (parentData.user === null) return redirect(303, `${parentData.qrcode}/login`);
|
||||||
|
return parentData;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user