feat(frontend): notifications
This commit is contained in:
parent
f99d10ecf0
commit
dd9d35249c
9 changed files with 129 additions and 6 deletions
|
@ -2,16 +2,24 @@ import { clearToken, TOKEN_COOKIE_NAME } from "$lib";
|
|||
import { apiRequest } from "$api";
|
||||
import ApiError, { ErrorCode } from "$api/error";
|
||||
import type { Meta, MeUser } from "$api/models";
|
||||
import type { Notification } from "$api/models/moderation";
|
||||
import log from "$lib/log";
|
||||
import type { LayoutServerLoad } from "./$types";
|
||||
|
||||
export const load = (async ({ fetch, cookies }) => {
|
||||
let token: string | null = null;
|
||||
let meUser: MeUser | null = null;
|
||||
let unreadNotifications: boolean = false;
|
||||
if (cookies.get(TOKEN_COOKIE_NAME)) {
|
||||
try {
|
||||
meUser = await apiRequest<MeUser>("GET", "/users/@me", { fetch, cookies });
|
||||
token = cookies.get(TOKEN_COOKIE_NAME) || null;
|
||||
|
||||
const notifications = await apiRequest<Notification[]>("GET", "/notifications", {
|
||||
fetch,
|
||||
cookies,
|
||||
});
|
||||
unreadNotifications = notifications.filter((n) => !n.acknowledged).length > 0;
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError && e.code === ErrorCode.AuthenticationRequired) clearToken(cookies);
|
||||
else log.error("Could not fetch /users/@me and token has not expired:", e);
|
||||
|
@ -19,5 +27,5 @@ export const load = (async ({ fetch, cookies }) => {
|
|||
}
|
||||
|
||||
const meta = await apiRequest<Meta>("GET", "/meta", { fetch, cookies });
|
||||
return { meta, meUser, token };
|
||||
return { meta, meUser, token, unreadNotifications };
|
||||
}) satisfies LayoutServerLoad;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<div class="flex-grow-1">
|
||||
<Navbar user={data.meUser} meta={data.meta} />
|
||||
<Navbar user={data.meUser} meta={data.meta} unreadNotifications={data.unreadNotifications} />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<Footer meta={data.meta} />
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { apiRequest } from "$api";
|
||||
import type { Notification } from "$api/models/moderation";
|
||||
import { alertKey } from "$lib";
|
||||
|
||||
export const load = async ({ url, fetch, cookies }) => {
|
||||
const notifications = await apiRequest<Notification[]>("GET", "/notifications", {
|
||||
fetch,
|
||||
cookies,
|
||||
});
|
||||
return { notifications, alertKey: alertKey(url) };
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from "./$types";
|
||||
import Notification from "$components/settings/Notification.svelte";
|
||||
import UrlAlert from "$components/URLAlert.svelte";
|
||||
|
||||
type Props = { data: PageData };
|
||||
let { data }: Props = $props();
|
||||
</script>
|
||||
|
||||
<UrlAlert {data} />
|
||||
|
||||
{#each data.notifications as notification (notification.id)}
|
||||
<Notification {notification} />
|
||||
{:else}
|
||||
You have no notifications.
|
||||
{/each}
|
|
@ -0,0 +1,14 @@
|
|||
import { redirect } from "@sveltejs/kit";
|
||||
import type { RequestHandler } from "./$types";
|
||||
import { fastRequest } from "$api";
|
||||
import log from "$lib/log";
|
||||
|
||||
export const GET: RequestHandler = async ({ params, fetch, cookies }) => {
|
||||
try {
|
||||
await fastRequest("PUT", `/notifications/${params.id}/ack`, { fetch, cookies });
|
||||
} catch (e) {
|
||||
log.error("error acking notification %s:", params.id, e);
|
||||
redirect(303, "/settings/notifications?alert=notif-ack-fail");
|
||||
}
|
||||
redirect(303, "/settings/notifications?alert=notif-ack-successful");
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue