Add coauthor invitations tab with accept and reject

This commit is contained in:
2026-09-25 02:22:46 +02:00
parent 058a902a81
commit dddb57c98b
6 changed files with 151 additions and 2 deletions
@@ -0,0 +1,9 @@
import type { LayoutServerLoad } from './$types';
import { apiFor } from '$lib/server/api';
import { requireUser } from '$lib/server/guards';
import { loadInvitationCount } from '$lib/server/coauthors';
export const load: LayoutServerLoad = async ({ locals, url, fetch }) => {
requireUser(locals, url);
return { invitationCount: await loadInvitationCount(apiFor({ fetch, locals })) };
};
@@ -24,7 +24,7 @@
import PageHeader from '$lib/components/ui/layout/PageHeader.svelte';
import Tabs from '$lib/components/ui/primitives/Tabs.svelte';
let { children } = $props();
let { data, children } = $props();
const pathname = $derived(page.url.pathname.replace(/\/$/, ''));
const current = $derived(
@@ -35,7 +35,12 @@
) ?? SECTIONS[0]
);
const tabs = $derived(
SECTIONS.map(({ href, label }) => ({ href, label, active: href === current.href }))
SECTIONS.map(({ href, label }) => ({
href,
label,
active: href === current.href,
count: href === '/library/invitations' ? data.invitationCount : undefined
}))
);
</script>
@@ -0,0 +1,25 @@
import type { PageServerLoad, Actions } from './$types';
import { fail } from '@sveltejs/kit';
import { apiFor } from '$lib/server/api';
import { requireUser } from '$lib/server/guards';
import { formString } from '$lib/server/forms/fields';
import { tagged } from '$lib/server/actions/tagged';
import { loadInvitations, respondToInvitation } from '$lib/server/coauthors';
export const load: PageServerLoad = async ({ locals, url, fetch }) => {
requireUser(locals, url);
return { invitations: await loadInvitations(apiFor({ fetch, locals })) };
};
function respond(decision: 'accept' | 'reject') {
return tagged(decision, async ({ api, form }) => {
const invitationId = formString(form, 'invitationId');
if (!invitationId) return fail(400, { message: 'Falta la invitación.' });
return respondToInvitation(api, invitationId, decision);
});
}
export const actions: Actions = {
accept: respond('accept'),
reject: respond('reject')
};
@@ -0,0 +1,7 @@
<script lang="ts">
import LibraryInvitationsSection from '$lib/components/music/library/LibraryInvitationsSection.svelte';
let { data } = $props();
</script>
<LibraryInvitationsSection invitations={data.invitations.items} />