feat: add invites page
This commit is contained in:
parent
fb10f29e2b
commit
1647ec16a4
8 changed files with 141 additions and 7 deletions
|
@ -1,5 +1,10 @@
|
|||
<script>
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores";
|
||||
import type { LayoutData } from "./$types";
|
||||
|
||||
import { ListGroup, ListGroupItem } from "sveltestrap";
|
||||
|
||||
export let data: LayoutData;
|
||||
</script>
|
||||
|
||||
<div class="grid">
|
||||
|
@ -8,9 +13,32 @@
|
|||
<h1>Settings</h1>
|
||||
|
||||
<ListGroup>
|
||||
<ListGroupItem tag="a" href="/settings">Your profile</ListGroupItem>
|
||||
<ListGroupItem tag="a" href="/settings/invites">Invites</ListGroupItem>
|
||||
<ListGroupItem tag="a" href="/settings/tokens">API tokens</ListGroupItem>
|
||||
<ListGroupItem tag="a" active={$page.url.pathname === "/settings"} href="/settings">
|
||||
Your profile
|
||||
</ListGroupItem>
|
||||
{#if data.require_invite}
|
||||
<ListGroupItem
|
||||
tag="a"
|
||||
active={$page.url.pathname === "/settings/invites"}
|
||||
href="/settings/invites"
|
||||
>
|
||||
Invites
|
||||
</ListGroupItem>
|
||||
{/if}
|
||||
<ListGroupItem
|
||||
tag="a"
|
||||
active={$page.url.pathname === "/settings/tokens"}
|
||||
href="/settings/tokens"
|
||||
>
|
||||
API tokens
|
||||
</ListGroupItem>
|
||||
<ListGroupItem
|
||||
tag="a"
|
||||
active={$page.url.pathname === "/settings/export"}
|
||||
href="/settings/export"
|
||||
>
|
||||
Data export
|
||||
</ListGroupItem>
|
||||
</ListGroup>
|
||||
</div>
|
||||
<div class="col-md m-3">
|
||||
|
|
|
@ -1 +1,8 @@
|
|||
import type { LayoutLoad } from "./$types";
|
||||
|
||||
export const ssr = false;
|
||||
|
||||
export const load = (async ({ parent }) => {
|
||||
const data = await parent();
|
||||
return data;
|
||||
}) satisfies LayoutLoad;
|
||||
|
|
69
frontend/src/routes/settings/invites/+page.svelte
Normal file
69
frontend/src/routes/settings/invites/+page.svelte
Normal file
|
@ -0,0 +1,69 @@
|
|||
<script lang="ts">
|
||||
import type { APIError, Invite } from "$lib/api/entities";
|
||||
import { apiFetchClient } from "$lib/api/fetch";
|
||||
import { Alert, Button, Modal, Table } from "sveltestrap";
|
||||
import type { PageData } from "./$types";
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let error: APIError | null = null;
|
||||
let latestInvite: Invite | null = null;
|
||||
let open = false;
|
||||
|
||||
const toggle = () => (open = !open);
|
||||
const createInvite = async () => {
|
||||
try {
|
||||
const invite = await apiFetchClient<Invite>("/auth/invites", "POST");
|
||||
|
||||
error = null;
|
||||
data.invites = [...data.invites, invite];
|
||||
latestInvite = invite;
|
||||
open = true;
|
||||
} catch (e) {
|
||||
latestInvite = null;
|
||||
error = e as APIError;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<h1>Invites ({data.invites.length})</h1>
|
||||
|
||||
<div>
|
||||
{#if !data.invitesEnabled}
|
||||
<p>Invites aren't required to sign up to pronouns.cc right now!</p>
|
||||
{:else}
|
||||
<Table striped hover>
|
||||
<thead>
|
||||
<th>Code</th>
|
||||
<th>Created at</th>
|
||||
<th>Used?</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each data.invites as invite}
|
||||
<tr>
|
||||
<td><code>{invite.code}</code></td>
|
||||
<td>{invite.created}</td>
|
||||
<td>{invite.used ? "yes" : "no"}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</Table>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<Button color="primary" on:click={createInvite}>Create invite</Button>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
{#if error}
|
||||
<Alert color="danger" fade={false}>
|
||||
<h4 class="alert-heading">An error occurred</h4>
|
||||
<b>{error.code}</b>: {error.message}
|
||||
</Alert>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<Modal body header="Invite created" isOpen={open} {toggle}>
|
||||
Successfully created a new invite! Give the person you're sending it to this code:
|
||||
<code>{latestInvite?.code}</code>
|
||||
</Modal>
|
||||
{/if}
|
||||
</div>
|
25
frontend/src/routes/settings/invites/+page.ts
Normal file
25
frontend/src/routes/settings/invites/+page.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { ErrorCode, type APIError, type Invite } from "$lib/api/entities";
|
||||
import { apiFetchClient } from "$lib/api/fetch";
|
||||
import { error } from "@sveltejs/kit";
|
||||
import type { PageLoad } from "../$types";
|
||||
|
||||
export const load = (async () => {
|
||||
const data = {
|
||||
invitesEnabled: true,
|
||||
invites: [] as Invite[],
|
||||
};
|
||||
|
||||
try {
|
||||
const invites = await apiFetchClient<Invite[]>("/auth/invites");
|
||||
data.invites = invites;
|
||||
} catch (e) {
|
||||
if ((e as APIError).code === ErrorCode.InvitesDisabled) {
|
||||
data.invitesEnabled = false;
|
||||
data.invites = [];
|
||||
} else {
|
||||
throw error(500, (e as APIError).message);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}) satisfies PageLoad;
|
Loading…
Add table
Add a link
Reference in a new issue