Compare commits

...

2 Commits

Author SHA1 Message Date
Roman Krček
6c2e80ecc1 Kill the QRcode scanner when exiting the view 2025-06-25 14:54:06 +02:00
Roman Krček
c28c338de4 Styling changes and rebrand to ScanWave 2025-06-25 14:53:51 +02:00
6 changed files with 79 additions and 33 deletions

View File

@@ -1,20 +1,24 @@
<script> <script>
import { invalidate } from '$app/navigation' import { invalidate } from '$app/navigation';
import { onMount } from 'svelte' import { onMount } from 'svelte';
import "../app.css"; import '../app.css';
let { data, children } = $props() let { data, children } = $props();
let { session, supabase } = $derived(data) let { session, supabase } = $derived(data);
onMount(() => { onMount(() => {
const { data } = supabase.auth.onAuthStateChange((_, newSession) => { const { data } = supabase.auth.onAuthStateChange((_, newSession) => {
if (newSession?.expires_at !== session?.expires_at) { if (newSession?.expires_at !== session?.expires_at) {
invalidate('supabase:auth') invalidate('supabase:auth');
} }
}) });
return () => data.subscription.unsubscribe() return () => data.subscription.unsubscribe();
}) });
</script> </script>
{@render children()} <svelte:head>
<title>ScanWave</title>
</svelte:head>
{@render children()}

View File

@@ -3,7 +3,7 @@
<div class="mb-8"> <div class="mb-8">
<img class="w-32 h-auto" src="/qr-code.png" alt=""> <img class="w-32 h-auto" src="/qr-code.png" alt="">
</div> </div>
<h1 class="text-3xl font-bold text-center mb-2">ESN Scanner App</h1> <h1 class="text-3xl font-bold text-center mb-2">ScanWave</h1>
<h2 class="text-lg text-gray-600 text-center mb-8">Make entrance to your events a breeze.</h2> <h2 class="text-lg text-gray-600 text-center mb-8">Make entrance to your events a breeze.</h2>
<div class="flex space-x-4 w-full justify-center"> <div class="flex space-x-4 w-full justify-center">
<a href="/private/home" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-8 rounded-full shadow-none border border-gray-300 w-64 text-center transition"> <a href="/private/home" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-8 rounded-full shadow-none border border-gray-300 w-64 text-center transition">

View File

@@ -2,13 +2,18 @@
// Add any navbar logic here if needed // Add any navbar logic here if needed
</script> </script>
<nav class="bg-white border-b border-gray-300 text-gray-900 p-4 flex items-center justify-between"> <nav class="bg-gray-50 border-b border-gray-300 text-gray-900 p-2">
<div class="font-bold text-lg">ESN Scanner</div> <div class="container max-w-2xl mx-auto p-2">
<ul class="flex space-x-4"> <div class="flex items-center justify-between">
<li><a href="/private/home" class="hover:underline">Home</a></li> <div class="font-bold text-lg">ScanWave</div>
<li><a href="/private/scanner" class="hover:underline">Scanner</a></li>
<li><a href="/private/events" class="hover:underline">Events</a></li> <ul class="flex space-x-4">
</ul> <li><a href="/private/home" class="hover:underline">Home</a></li>
<li><a href="/private/scanner" class="hover:underline">Scanner</a></li>
<li><a href="/private/events" class="hover:underline">Events</a></li>
</ul>
</div>
</div>
</nav> </nav>
<div class="container max-w-2xl mx-auto p-2 bg-white"> <div class="container max-w-2xl mx-auto p-2 bg-white">

View File

@@ -3,6 +3,5 @@ export async function load({ locals }) {
.from('events') .from('events')
.select('*') .select('*')
.order('date', { ascending: false }); .order('date', { ascending: false });
console.log('events', events);
return { events }; return { events };
} }

View File

@@ -7,13 +7,45 @@
}; };
</script> </script>
<div class="user-profile"> <h1 class="mt-2 mb-4 text-center text-2xl font-bold">User Profile</h1>
<h2 class="mb-2 text-2xl font-bold">Currently logged in</h2>
<p><strong>Username:</strong> {data.user?.user_metadata.display_name}</p> <div class="mb-4 rounded border border-gray-300 bg-white p-6">
<p><strong>Email:</strong> {data.user?.email}</p> <div class="flex flex-col gap-2">
<p><strong>Section:</strong> {data.user_profile?.section.name}</p> <div class="flex items-center gap-3 mb-4">
<p><strong>Position:</strong> {data.user_profile?.section_position}</p> <div class="h-12 w-12 rounded-full bg-gray-200 flex items-center justify-center text-xl font-bold text-gray-600">
{data.user?.user_metadata.display_name?.[0] ?? "U"}
</div>
<div>
<span class="text-lg font-semibold text-gray-800">{data.user?.user_metadata.display_name}</span>
<div class="text-sm text-gray-500">{data.user?.email}</div>
</div>
</div>
<div class="flex flex-col gap-1">
<div>
<span class="font-medium text-gray-700">Section:</span>
<span class="text-gray-900">{data.user_profile?.section.name ?? "N/A"}</span>
</div>
<div>
<span class="font-medium text-gray-700">Position:</span>
<span class="text-gray-900">{data.user_profile?.section_position ?? "N/A"}</span>
</div>
</div>
<h2 class="text-lg mb-2 mt-4">User guide</h2>
<p class="text-gray-700 text-sm leading-relaxed">
To scan a QR code, head over to Scanner in the top right corner. Click on Start scanning and allow camera permissions.
If you close and open your browser and your camera is stuck, simply refresh the page or click Stop scanning and then Start scanning again.
When you scan a QR code, a request is sent to the server to get the user's personal information and to mark their tickets as scanned.
</p>
<h2 class="text-lg mb-2 mt-4">Administrator guide</h2>
<p class="text-gray-700 text-sm leading-relaxed">
You can view events
</p>
</div>
</div> </div>
<button class="mt-4 rounded bg-red-500 px-4 py-2 text-white hover:bg-red-600">
<a href="/auth/signout">Sign out</a> <a
</button> href="/auth/signout"
class="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 bg-red-500 hover:bg-red-600 text-white font-semibold py-3 px-8 rounded-full shadow-none border border-gray-300 transition"
>
Sign out
</a>

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount, onDestroy } from 'svelte';
import { import {
Html5QrcodeScanner, Html5QrcodeScanner,
type Html5QrcodeResult, type Html5QrcodeResult,
@@ -37,6 +37,12 @@
); );
scanner.render(onScanSuccess, onScanFailure); scanner.render(onScanSuccess, onScanFailure);
}); });
onDestroy(() => {
if (scanner) {
scanner.clear().catch(() => {});
}
});
</script> </script>
<div id="qr-scanner" class="w-full h-full max-w-none overflow-hidden rounded-sm"></div> <div id="qr-scanner" class="w-full h-full max-w-none overflow-hidden rounded-sm"></div>