Slightly working

This commit is contained in:
Roman Krček
2025-06-19 19:42:08 +02:00
parent 51dbfcc1bb
commit 9c94f9c717
12 changed files with 162 additions and 92 deletions

17
src/app.d.ts vendored
View File

@@ -1,13 +1,16 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
// src/app.d.ts
import { SupabaseClient, Session } from '@supabase/supabase-js'
declare global {
namespace App {
interface Locals {
supabase: SupabaseClient
safeGetSession(): Promise<{ session: Session | null; user: User | null }>
}
interface PageData {
session: Session | null
user: User | null
}
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};

53
src/hooks.server.ts Normal file
View File

@@ -0,0 +1,53 @@
// src/hooks.server.ts
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'
import { createServerClient } from '@supabase/ssr'
import type { Handle } from '@sveltejs/kit'
export const handle: Handle = async ({ event, resolve }) => {
event.locals.supabase = createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
cookies: {
getAll: () => event.cookies.getAll(),
/**
* SvelteKit's cookies API requires `path` to be explicitly set in
* the cookie options. Setting `path` to `/` replicates previous/
* standard behavior.
*/
setAll: (cookiesToSet) => {
cookiesToSet.forEach(({ name, value, options }) => {
event.cookies.set(name, value, { ...options, path: '/' })
})
},
},
})
/**
* Unlike `supabase.auth.getSession()`, which returns the session _without_
* validating the JWT, this function also calls `getUser()` to validate the
* JWT before returning the session.
*/
event.locals.safeGetSession = async () => {
const {
data: { session },
} = await event.locals.supabase.auth.getSession()
if (!session) {
return { session: null, user: null }
}
const {
data: { user },
error,
} = await event.locals.supabase.auth.getUser()
if (error) {
// JWT validation has failed
return { session: null, user: null }
}
return { session, user }
}
return resolve(event, {
filterSerializedResponseHeaders(name) {
return name === 'content-range' || name === 'x-supabase-api-version'
},
})
}

31
src/lib/types.ts Normal file
View File

@@ -0,0 +1,31 @@
export enum ScanState {
scanning,
scan_successful,
scan_failed
}
export type TicketData = {
id: string;
name: string;
surname: string;
email: string;
event: string;
created_at: string;
created_by: string | null;
scanned: boolean;
scanned_at: string | null;
scanned_by: string | null;
};
export const defaultTicketData: TicketData = {
id: '',
name: '',
surname: '',
email: '',
event: '',
created_at: new Date().toISOString(),
created_by: null,
scanned: false,
scanned_at: null,
scanned_by: null,
};

View File

@@ -0,0 +1,10 @@
// src/routes/+layout.server.ts
import type { LayoutServerLoad } from './$types'
export const load: LayoutServerLoad = async ({ locals: { safeGetSession }, cookies }) => {
const { session, user } = await safeGetSession()
return {
session,
user,
cookies: cookies.getAll(),
}
}

View File

@@ -2,6 +2,7 @@
import '../app.css';
let { children } = $props();
</script>
{@render children()}

View File

@@ -8,7 +8,7 @@ export const load: LayoutLoad = async ({ fetch, data, depends }) => {
? createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
global: {
fetch,
},
}
})
: createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
global: {
@@ -16,7 +16,7 @@ export const load: LayoutLoad = async ({ fetch, data, depends }) => {
},
cookies: {
getAll() {
return data?.cookies ?? []
return data.cookies ?? []
},
},
})

View File

@@ -1,15 +1,5 @@
<script lang="ts">
import { onMount } from 'svelte';
let data = $props();
onMount( async () => {
await handleClick();
});
async function handleClick() {
console.log( await data.data.supabase.from('qrcodes').select().eq('id', "4b461fd7-d7db-4739-8ca0-6e78cc299813"));
}
</script>

View File

View File

@@ -0,0 +1,42 @@
<script lang="ts">
import QRScanner from './QRScanner.svelte';
import TicketDisplay from './TicketDisplay.svelte';
import type { TicketData } from '$lib/types';
import { ScanState, defaultTicketData } from '$lib/types';
let { data } = $props();
let scanned_id = $state<string>("");
let ticket_data = $state<TicketData>(defaultTicketData);
let scan_state = $state<ScanState>(ScanState.scanning);
$effect(() => {
if (scanned_id === "") return;
console.log('New QR code found:', scanned_id);
scan_state = ScanState.scanning;
data.supabase.from('qrcodes').select().eq('id', scanned_id).then( response => {
if (response.data && response.data.length > 0) {
ticket_data = response.data[0];
scan_state = ScanState.scan_successful;
} else {
ticket_data = defaultTicketData;
scan_state = ScanState.scan_failed;
}
})
});
</script>
<QRScanner bind:message={scanned_id} />
{#if scan_state === ScanState.scan_successful}
<TicketDisplay {ticket_data} />
{/if}
{#if scan_state === ScanState.scan_failed}
<p>Scan failed. Please try again.</p>
{/if}
{#if scan_state === ScanState.scanning}
<p>Fetching data...</p>
{/if}

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import type { TicketData } from '$lib/types';
let { ticket_data }: { ticket_data: TicketData } = $props();
</script>
<p>{ticket_data.name}</p>
<p>{ticket_data.surname}</p>

View File

@@ -1,68 +0,0 @@
<script>
import { onMount, tick } from 'svelte';
import QRScanner from './QRScanner.svelte';
let scanned_id = $state('');
let scan_user = $state('Roman');
let scan_data = $state({});
let ticket_state = $state('not_scanned');
onMount(() => {reset_scan_data()});
function reset_scan_data() {
ticket_state = 'unknown';
scan_data = {
id: 0,
created_at: 'none',
name: 'none',
surname: 'none',
email: 'none@esnvutbrno.cz',
uuid: 'none',
scanned: 'none',
scanned_at: 'none',
event_name: 'none',
scanned_by: 'none'
};
}
$effect(() => {
if (scan_data.scanned === true) {
ticket_state = 'Already scanned';
} else if (scan_data.scanned === false) {
ticket_state = 'Good to go in 2';
console.log(scan_data.scanned);
} else {
ticket_state = 'Ticket invalid';
}
});
$effect(() => {
console.log('Message updated:', scanned_id);
reset_scan_data();
fetch('https://n8n.orebolt.cz/webhook/9d32752c-47c9-46db-be6d-f473e97a7c25', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ scanned_id, scan_user })
})
.then((response) => response.json())
.then((data) => {
scan_data = data;
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
ticket_state = "Ticket invalid";
});
});
</script>
<QRScanner bind:message={scanned_id} />
<p>CODE: {scanned_id}</p>
<p>Name: {scan_data.name} {scan_data.surname}</p>
<p>State: {ticket_state}</p>
<p>Event: {scan_data.event_name}</p>