feat(frontend): custom preference editor

This commit is contained in:
sam 2024-12-15 00:32:11 +01:00
parent 41a008799a
commit 507b9c3f4c
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
10 changed files with 302 additions and 8 deletions

View file

@ -29,6 +29,12 @@
<NavLink active={isActive("/settings/profile", true)} href="/settings/profile">
{$t("settings.your-profile-tab")}
</NavLink>
<NavLink active={isActive("/settings/flags")} href="/settings/flags">
{$t("settings.flag-title")}
</NavLink>
<NavLink active={isActive("/settings/prefs")} href="/settings/prefs">
{$t("settings.custom-preferences-title")}
</NavLink>
<NavLink active={isActive("/settings/members", true)} href="/settings/members">
{$t("settings.members-tab")}
</NavLink>

View file

@ -112,7 +112,7 @@
<ClientPaginator center bind:currentPage {pageCount} />
<Accordion>
<Accordion class="mb-3">
{#each arr as flag (flag.id)}
<AccordionItem>
<span slot="header">

View file

@ -147,7 +147,7 @@
</div>
<div class="row mb-3">
<h4>{$t("edit-profile.bio-tab")}</h4>
<form method="POST" action="?/bio" use:enhance>
<form method="POST" action="?/bio">
<BioEditor bind:value={bio} maxLength={data.meta.limits.bio_length} />
</form>
</div>

View file

@ -0,0 +1,99 @@
<script lang="ts">
import { apiRequest } from "$api";
import ApiError, { type RawApiError } from "$api/error";
import { PreferenceSize, type CustomPreference } from "$api/models";
import CustomPreferenceEditor from "$components/editor/CustomPreferenceEditor.svelte";
import FormStatusMarker from "$components/editor/FormStatusMarker.svelte";
import { t } from "$lib/i18n";
import log from "$lib/log";
import type { PageData } from "./$types";
type Props = { data: PageData };
let { data }: Props = $props();
type EditableCustomPreference = CustomPreference & {
id: string | undefined;
};
let customPreferences = $state(
Object.keys(data.user.custom_preferences)
.sort()
.map(
(id) =>
({
...data.user.custom_preferences[id],
id,
}) as EditableCustomPreference,
),
);
let canAdd = $derived(customPreferences.length < data.meta.limits.custom_preferences);
// Used for form status
let ok: { ok: boolean; error: RawApiError | null } | null = $state(null);
const remove = (idx: number) => {
customPreferences.splice(idx, 1);
customPreferences = [...customPreferences];
};
const add = () => {
customPreferences = [
...customPreferences,
{
id: undefined,
tooltip: "",
icon: "question-lg",
size: PreferenceSize.Normal,
muted: false,
favourite: false,
},
];
};
const save = async () => {
try {
const resp = await apiRequest<Record<string, CustomPreference>>(
"PATCH",
"/users/@me/custom-preferences",
{
body: customPreferences,
token: data.token,
},
);
customPreferences = Object.keys(resp)
.sort()
.map(
(id) =>
({
...resp[id],
id,
}) as EditableCustomPreference,
);
ok = { ok: true, error: null };
} catch (e) {
log.error("error saving custom preferences:", e);
if (e instanceof ApiError) ok = { ok: false, error: e.obj };
else ok = null;
}
};
</script>
<h3>
{$t("settings.custom-preferences-title")}
<div class="btn-group">
<button class="btn btn-primary" onclick={() => save()}>{$t("save-changes")}</button>
<button class="btn btn-success" onclick={add}>{$t("editor.add-custom-preference")}</button>
</div>
</h3>
<FormStatusMarker form={ok} />
<div>
{#each customPreferences as _, idx}
<CustomPreferenceEditor bind:pref={customPreferences[idx]} remove={() => remove(idx)} />
{/each}
</div>
<form></form>

View file

@ -3,7 +3,6 @@
import type { ActionData, PageData } from "./$types";
import BioEditor from "$components/editor/BioEditor.svelte";
import { t } from "$lib/i18n";
import { enhance } from "$app/forms";
type Props = { data: PageData; form: ActionData };
let { data, form }: Props = $props();
@ -13,6 +12,6 @@
<h4>{$t("edit-profile.bio-tab")}</h4>
<FormStatusMarker {form} />
<form method="POST" use:enhance>
<form method="POST">
<BioEditor bind:value={bio} maxLength={data.meta.limits.bio_length} />
</form>