Creator scaffolding
This commit is contained in:
69
src/routes/private/creator/steps/StepConnectGoogle.svelte
Normal file
69
src/routes/private/creator/steps/StepConnectGoogle.svelte
Normal file
@@ -0,0 +1,69 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
let refreshToken = '';
|
||||
let authorized = false;
|
||||
|
||||
let to = '';
|
||||
let subject = '';
|
||||
let body = '';
|
||||
|
||||
async function validateToken(token: string): Promise<boolean> {
|
||||
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 () => {
|
||||
console.log("on mount");
|
||||
refreshToken = localStorage.getItem('gmail_refresh_token') ?? '';
|
||||
authorized = await validateToken(refreshToken);
|
||||
});
|
||||
|
||||
/* ⇢ redirects straight to Google via server 302 */
|
||||
const connect = () => goto('/private/api/gmail?action=auth');
|
||||
|
||||
async function sendEmail() {
|
||||
const r = await fetch('/private/api/gmail', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
action: 'send',
|
||||
to,
|
||||
subject,
|
||||
text: body,
|
||||
refreshToken
|
||||
})
|
||||
});
|
||||
r.ok ? alert('Sent!') : alert(await r.text());
|
||||
to = subject = body = '';
|
||||
}
|
||||
|
||||
async function disconnect() {
|
||||
if (!confirm('Disconnect Google account?')) return;
|
||||
await fetch('/private/api/gmail', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'revoke', refreshToken })
|
||||
});
|
||||
localStorage.removeItem('gmail_refresh_token');
|
||||
refreshToken = '';
|
||||
authorized = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !authorized}
|
||||
<section class="space-y-4">
|
||||
<p>You haven’t connected your Google account yet.</p>
|
||||
<button class="btn" on:click={connect}>Connect Google</button>
|
||||
</section>
|
||||
{:else}
|
||||
Your connection is good, proceed to next step
|
||||
{/if}
|
||||
1
src/routes/private/creator/steps/StepCraftEmail.svelte
Normal file
1
src/routes/private/creator/steps/StepCraftEmail.svelte
Normal file
@@ -0,0 +1 @@
|
||||
emaillk
|
||||
17
src/routes/private/creator/steps/StepCreateEvent.svelte
Normal file
17
src/routes/private/creator/steps/StepCreateEvent.svelte
Normal file
@@ -0,0 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
|
||||
let { events, new_event } = $props();
|
||||
|
||||
</script>
|
||||
|
||||
<p class="bg-grey-200">{JSON.stringify(events)}</p>
|
||||
|
||||
<form method="POST" action="?/create" use:enhance>
|
||||
<input type="text" name="name" />
|
||||
<input type="date" name="date" />
|
||||
<textarea name="description"></textarea>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<p class="bg-grey-200">{JSON.stringify(new_event)}</p>
|
||||
11
src/routes/private/creator/steps/StepOverview.svelte
Normal file
11
src/routes/private/creator/steps/StepOverview.svelte
Normal file
@@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
let { new_event, participants } = $props();
|
||||
</script>
|
||||
|
||||
<p>New event:</p>
|
||||
{JSON.stringify(new_event)}
|
||||
|
||||
|
||||
<br />
|
||||
<p>Participants</p>
|
||||
{JSON.stringify(participants)}
|
||||
34
src/routes/private/creator/steps/StepUploadFiles.svelte
Normal file
34
src/routes/private/creator/steps/StepUploadFiles.svelte
Normal file
@@ -0,0 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
|
||||
let { participants = [] } = $props();
|
||||
|
||||
function removeParticipant(index: number) {
|
||||
participants = participants.slice(0, index).concat(participants.slice(index + 1));
|
||||
}
|
||||
</script>
|
||||
|
||||
<form method="POST" action="?/participants" use:enhance enctype="multipart/form-data">
|
||||
<input type="file" name="participants" id="participants" accept=".csv" required />
|
||||
<button type="submit"> Submit </button>
|
||||
|
||||
</form>
|
||||
|
||||
{JSON.stringify(participants)}
|
||||
|
||||
{#if participants.length === 0}
|
||||
<p class="text-gray-500">No participants added yet.</p>
|
||||
{/if}
|
||||
|
||||
{#if participants.length > 0}
|
||||
<ul class="mt-4 space-y-2">
|
||||
{#each participants as p, i}
|
||||
<li class="flex items-center gap-2 border-b pb-1">
|
||||
<span>{p.name} {p.surname} ({p.email})</span>
|
||||
<button class="ml-auto text-red-600 hover:underline" type="button" onclick={() => removeParticipant(i)}>
|
||||
Remove
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user