From fe8789af87f7b33e3075f20e870f8eaa4d63e12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Kr=C4=8Dek?= Date: Mon, 23 Jun 2025 14:09:14 +0200 Subject: [PATCH 1/5] Fixed signing out --- src/routes/+page.svelte | 15 ++------------- src/routes/auth/signout/+page.server.ts | 7 +++++++ src/routes/auth/signout/+page.svelte | 2 -- src/routes/auth/signout/+server.ts | 9 --------- src/routes/login/+page.svelte | 0 static/qr-code.png | Bin 0 -> 1543 bytes 6 files changed, 9 insertions(+), 24 deletions(-) create mode 100644 src/routes/auth/signout/+page.server.ts delete mode 100644 src/routes/auth/signout/+server.ts delete mode 100644 src/routes/login/+page.svelte create mode 100644 static/qr-code.png diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 0447531..3d640c9 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,22 +1,11 @@
- - - - - - - - - - - +

ESN Scanner App

Make entrance to your events a breeze.

diff --git a/src/routes/auth/signout/+page.server.ts b/src/routes/auth/signout/+page.server.ts new file mode 100644 index 0000000..56ad767 --- /dev/null +++ b/src/routes/auth/signout/+page.server.ts @@ -0,0 +1,7 @@ +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ locals }) => { + await locals.supabase.auth.signOut(); + throw redirect(303, '/'); +}; \ No newline at end of file diff --git a/src/routes/auth/signout/+page.svelte b/src/routes/auth/signout/+page.svelte index dceffee..38bb23b 100644 --- a/src/routes/auth/signout/+page.svelte +++ b/src/routes/auth/signout/+page.svelte @@ -1,10 +1,8 @@ diff --git a/src/routes/auth/signout/+server.ts b/src/routes/auth/signout/+server.ts deleted file mode 100644 index 25340c9..0000000 --- a/src/routes/auth/signout/+server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { RequestHandler } from './$types'; -import { redirect } from '@sveltejs/kit'; - -export const GET: RequestHandler = async ({ locals }) => { - // If using supabase-js client on the server, you can sign out here - if (locals.supabase) { - await locals.supabase.auth.signOut(); - } -}; diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte deleted file mode 100644 index e69de29..0000000 diff --git a/static/qr-code.png b/static/qr-code.png new file mode 100644 index 0000000000000000000000000000000000000000..9fa23cfbf5fa0ad7d76b770df2fc849bed6009a7 GIT binary patch literal 1543 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6%N?Bp530R%N1DIGvQXMsm# zF#`kJ8xUrcE445M3QCr^MwA5SrEaktG3V{wz`WaTA`TZ5AGTJe7nUuXyHVb=!Gxo0R~?`Gp65CV21{N@2Xf8t+j?!M zMCrWeg%|`I?R#7io4uD$@2AE2&xSkX)@*%Oxi(I&;p^L$I?1@thI{1J zlpfB$s>{&A2}5r`C@T0rvFO`=^6R%&W5&aB>DectE5+_>ededaSWMttA5;ay2ixz)7)r?)d4kYH>ufT0Z^+Z&hJFKs#h zDC#R8!zF^DTlOPWp)P1P=ZUSy(wR10*Jt+Kec8w14wJ(y28S6ibmO$~KPxWZbyq9z zF(O3a(rAnuh4VHCPg|CLYwmN)UGrvESI?}gRhK>fao4q~y%o~`4gP)qz{w~PTkwl> z!`|Rd0^Xg|p?o_GV_;BX< z^{v;E3-)p@Rz3wxhVS%WT>CwH+wYIJ?r&Yze;zr8;ZaSHVSCtP!}fzuLfXzi*F`XVKm@TldB7?X-Wf z@n=;w?|!-6{db~f$Jg)f5Ba^~u}!}1C!P14Ob1$l5rr1|Xxtm8@7DkS!}V{!&G|!U z8Kin=6|>Fs#}@b2-8;PB^8DxAqP;I4|9$aq+4tf#TWfeN-YCa2zq31({e69Jx&6KV zcllNJ#KcU_pUea4bK1B6X4d-j-P8R%B{IifN4+jBI0+2w{)1m1Y}4aE@ax<0|EU#ckAJ8t z@FwV>oc46aA1Bp&KHU1{?q4>0N3b%(owL_Z9yOcOXi-(ebYN{w$%|*}%c|K;|Ms0s zN6N|D4!1XeGVSe8ryXA3+po6y_VOG1Z@rB9doJ(!d9+Li&wX$PC>xgj-hcVbtUvo- z9539%8?PU~T%GCeT|R$ir;{&y_V)`h{Aez#ZhvHql-= Date: Mon, 23 Jun 2025 14:18:05 +0200 Subject: [PATCH 2/5] More signout fixes --- src/routes/auth/signout/+page.server.ts | 7 ------- src/routes/auth/signout/+page.svelte | 9 --------- src/routes/auth/signout/+server.ts | 11 +++++++++++ 3 files changed, 11 insertions(+), 16 deletions(-) delete mode 100644 src/routes/auth/signout/+page.server.ts delete mode 100644 src/routes/auth/signout/+page.svelte create mode 100644 src/routes/auth/signout/+server.ts diff --git a/src/routes/auth/signout/+page.server.ts b/src/routes/auth/signout/+page.server.ts deleted file mode 100644 index 56ad767..0000000 --- a/src/routes/auth/signout/+page.server.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { redirect } from '@sveltejs/kit'; -import type { PageServerLoad } from './$types'; - -export const load: PageServerLoad = async ({ locals }) => { - await locals.supabase.auth.signOut(); - throw redirect(303, '/'); -}; \ No newline at end of file diff --git a/src/routes/auth/signout/+page.svelte b/src/routes/auth/signout/+page.svelte deleted file mode 100644 index 38bb23b..0000000 --- a/src/routes/auth/signout/+page.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - -

Signing out...

diff --git a/src/routes/auth/signout/+server.ts b/src/routes/auth/signout/+server.ts new file mode 100644 index 0000000..e863937 --- /dev/null +++ b/src/routes/auth/signout/+server.ts @@ -0,0 +1,11 @@ +import type { RequestHandler } from './$types'; +export const GET: RequestHandler = async ({ locals}) => { + await locals.supabase.auth.signOut(); + + const html = ` + `; + return new Response(html, { headers: { 'Content-Type': 'text/html' } }); +}; \ No newline at end of file From 0a60ea7ffbd2d18597bcdfb18b17c8871d3fc650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Kr=C4=8Dek?= Date: Mon, 23 Jun 2025 14:28:44 +0200 Subject: [PATCH 3/5] Fix validation fo google tokens --- src/routes/private/api/gmail/+server.ts | 19 +++++++++++++++++++ src/routes/private/creator/+page.svelte | 16 ++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/routes/private/api/gmail/+server.ts b/src/routes/private/api/gmail/+server.ts index aa76b34..83bc247 100644 --- a/src/routes/private/api/gmail/+server.ts +++ b/src/routes/private/api/gmail/+server.ts @@ -60,5 +60,24 @@ export const POST: RequestHandler = async ({ request }) => { } } + /* validate token */ + if (action === 'validate') { + if (!refreshToken) { + console.log('No refreshToken provided'); + return json({ valid: false }); + } + try { + console.log('Validating refreshToken:', refreshToken); + const oAuth2Client = getOAuthClient(); + oAuth2Client.setCredentials({ refresh_token: refreshToken }); + await oAuth2Client.getAccessToken(); // This will throw if invalid + console.log('Token is valid'); + return json({ valid: true }); + } catch (err) { + console.error('Token validation error:', err); + return json({ valid: false, error: (err as Error).message }); + } + } + return new Response('Bad request', { status: 400 }); }; diff --git a/src/routes/private/creator/+page.svelte b/src/routes/private/creator/+page.svelte index 42a156a..0489a10 100644 --- a/src/routes/private/creator/+page.svelte +++ b/src/routes/private/creator/+page.svelte @@ -9,9 +9,21 @@ let subject = ''; let body = ''; - onMount(() => { + async function validateToken(token: string): Promise { + if (!token) return false; + const res = await fetch('/private/api/gmail', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action: 'validate', refreshToken: token }) + }); + if (!res.ok) return false; + const data = await res.json(); + return !!data.valid; + } + + onMount(async () => { refreshToken = localStorage.getItem('gmail_refresh_token') ?? ''; - authorized = !!refreshToken; + authorized = await validateToken(refreshToken); }); /* ⇢ redirects straight to Google via server 302 */ From 864c77133e6f5f98ab5d9121472575ef93ec76a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Kr=C4=8Dek?= Date: Mon, 23 Jun 2025 14:38:55 +0200 Subject: [PATCH 4/5] remove debugging --- src/routes/private/api/gmail/+server.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/routes/private/api/gmail/+server.ts b/src/routes/private/api/gmail/+server.ts index 83bc247..8cd7ce3 100644 --- a/src/routes/private/api/gmail/+server.ts +++ b/src/routes/private/api/gmail/+server.ts @@ -63,18 +63,14 @@ export const POST: RequestHandler = async ({ request }) => { /* validate token */ if (action === 'validate') { if (!refreshToken) { - console.log('No refreshToken provided'); return json({ valid: false }); } try { - console.log('Validating refreshToken:', refreshToken); const oAuth2Client = getOAuthClient(); oAuth2Client.setCredentials({ refresh_token: refreshToken }); await oAuth2Client.getAccessToken(); // This will throw if invalid - console.log('Token is valid'); return json({ valid: true }); } catch (err) { - console.error('Token validation error:', err); return json({ valid: false, error: (err as Error).message }); } } From 0fdf77a8c37a42ef020d49173edfef857eab80b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Kr=C4=8Dek?= Date: Mon, 23 Jun 2025 18:07:23 +0200 Subject: [PATCH 5/5] Creator scaffolding --- package-lock.json | 9 +- package.json | 3 +- src/routes/private/creator/+page.server.ts | 61 +++++++++ src/routes/private/creator/+page.svelte | 122 ++++++++---------- .../creator/steps/StepConnectGoogle.svelte | 69 ++++++++++ .../creator/steps/StepCraftEmail.svelte | 1 + .../creator/steps/StepCreateEvent.svelte | 17 +++ .../private/creator/steps/StepOverview.svelte | 11 ++ .../creator/steps/StepUploadFiles.svelte | 34 +++++ 9 files changed, 260 insertions(+), 67 deletions(-) create mode 100644 src/routes/private/creator/+page.server.ts create mode 100644 src/routes/private/creator/steps/StepConnectGoogle.svelte create mode 100644 src/routes/private/creator/steps/StepCraftEmail.svelte create mode 100644 src/routes/private/creator/steps/StepCreateEvent.svelte create mode 100644 src/routes/private/creator/steps/StepOverview.svelte create mode 100644 src/routes/private/creator/steps/StepUploadFiles.svelte diff --git a/package-lock.json b/package-lock.json index 7fe9a7f..7bf4e88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "@supabase/ssr": "^0.6.1", "@supabase/supabase-js": "^2.50.0", "@sveltejs/adapter-node": "^5.2.12", - "googleapis": "^150.0.1" + "googleapis": "^150.0.1", + "papaparse": "^5.5.3" }, "devDependencies": { "@sveltejs/kit": "^2.16.0", @@ -2497,6 +2498,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/papaparse": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.3.tgz", + "integrity": "sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==", + "license": "MIT" + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", diff --git a/package.json b/package.json index bb5447b..d856c29 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@supabase/ssr": "^0.6.1", "@supabase/supabase-js": "^2.50.0", "@sveltejs/adapter-node": "^5.2.12", - "googleapis": "^150.0.1" + "googleapis": "^150.0.1", + "papaparse": "^5.5.3" } } diff --git a/src/routes/private/creator/+page.server.ts b/src/routes/private/creator/+page.server.ts new file mode 100644 index 0000000..f324d97 --- /dev/null +++ b/src/routes/private/creator/+page.server.ts @@ -0,0 +1,61 @@ +import type { Actions } from './$types'; +import { error as kitError } from '@sveltejs/kit'; +import Papa from 'papaparse'; +import { fail } from '@sveltejs/kit'; + +export async function load({ locals }) { + console.log("▶️ fetching events…"); + + const { data: events, error } = await locals.supabase + .from('events') + .select('*') + .order('date', { ascending: true }); + + if (error) { + console.error('❌ supabase error:', error); + // optional: throw to render SvelteKit error page + throw kitError(500, 'Could not load events'); + } + + return { events }; +} + +export const actions = { + create: async (event) => { + const formData = await event.request.formData(); + console.log(Array.from(formData.entries())); + console.log('create_event date', formData.get("date"), formData.get("name"), formData.get("description")); + let { data: new_event, error } = await event.locals.supabase.rpc("create_event", + { + "p_name": formData.get('name'), + "p_date": formData.get('date'), + "p_description": formData.get('description'), + }); + return { + new_event, + error + } + }, + participants: async (event) => { + const formData = await event.request.formData(); + const file = formData.get('participants') as File; + + let csvText = await file.text(); + + const { data: parsedRows, errors } = Papa.parse(csvText, { + skipEmptyLines: true, + header: false + }); + + // Map each row to an object with keys: name, surname, email + const participants = parsedRows.map((row: string[]) => ({ + name: row[0], + surname: row[1], + email: row[2] + })); + + return { + participants, + } + } +} satisfies Actions; \ No newline at end of file diff --git a/src/routes/private/creator/+page.svelte b/src/routes/private/creator/+page.svelte index 0489a10..83681d0 100644 --- a/src/routes/private/creator/+page.svelte +++ b/src/routes/private/creator/+page.svelte @@ -1,75 +1,67 @@ -{#if !authorized} -
-

You haven’t connected your Google account yet.

- -
-{:else} - - -
- - - + +
+ +

{JSON.stringify(new_event)}

\ No newline at end of file diff --git a/src/routes/private/creator/steps/StepOverview.svelte b/src/routes/private/creator/steps/StepOverview.svelte new file mode 100644 index 0000000..f961fb8 --- /dev/null +++ b/src/routes/private/creator/steps/StepOverview.svelte @@ -0,0 +1,11 @@ + + +

New event:

+{JSON.stringify(new_event)} + + +
+

Participants

+{JSON.stringify(participants)} \ No newline at end of file diff --git a/src/routes/private/creator/steps/StepUploadFiles.svelte b/src/routes/private/creator/steps/StepUploadFiles.svelte new file mode 100644 index 0000000..1858ed3 --- /dev/null +++ b/src/routes/private/creator/steps/StepUploadFiles.svelte @@ -0,0 +1,34 @@ + + +
+ + + +
+ +{JSON.stringify(participants)} + +{#if participants.length === 0} +

No participants added yet.

+{/if} + +{#if participants.length > 0} +
    + {#each participants as p, i} +
  • + {p.name} {p.surname} ({p.email}) + +
  • + {/each} +
+{/if}