feat(frontend): custom preference editor
This commit is contained in:
parent
41a008799a
commit
507b9c3f4c
10 changed files with 302 additions and 8 deletions
|
@ -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>
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
|
||||
<ClientPaginator center bind:currentPage {pageCount} />
|
||||
|
||||
<Accordion>
|
||||
<Accordion class="mb-3">
|
||||
{#each arr as flag (flag.id)}
|
||||
<AccordionItem>
|
||||
<span slot="header">
|
||||
|
|
|
@ -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>
|
||||
|
|
99
Foxnouns.Frontend/src/routes/settings/prefs/+page.svelte
Normal file
99
Foxnouns.Frontend/src/routes/settings/prefs/+page.svelte
Normal 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>
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue