forked from mirrors/pronouns.cc
feat(frontend): show custom preferences
This commit is contained in:
parent
2c71741d7c
commit
8bda5f9860
7 changed files with 120 additions and 57 deletions
41
frontend/src/lib/api/default_preferences.ts
Normal file
41
frontend/src/lib/api/default_preferences.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { type CustomPreferences, PreferenceSize } from "./entities";
|
||||||
|
|
||||||
|
const defaultPreferences: CustomPreferences = {
|
||||||
|
favourite: {
|
||||||
|
icon: "heart-fill",
|
||||||
|
tooltip: "Favourite",
|
||||||
|
size: PreferenceSize.Large,
|
||||||
|
muted: false,
|
||||||
|
favourite: true,
|
||||||
|
},
|
||||||
|
okay: {
|
||||||
|
icon: "hand-thumbs-up",
|
||||||
|
tooltip: "Okay",
|
||||||
|
size: PreferenceSize.Normal,
|
||||||
|
muted: false,
|
||||||
|
favourite: false,
|
||||||
|
},
|
||||||
|
jokingly: {
|
||||||
|
icon: "emoji-laughing",
|
||||||
|
tooltip: "Jokingly",
|
||||||
|
size: PreferenceSize.Normal,
|
||||||
|
muted: false,
|
||||||
|
favourite: false,
|
||||||
|
},
|
||||||
|
friends_only: {
|
||||||
|
icon: "people",
|
||||||
|
tooltip: "Friends only",
|
||||||
|
size: PreferenceSize.Normal,
|
||||||
|
muted: false,
|
||||||
|
favourite: false,
|
||||||
|
},
|
||||||
|
avoid: {
|
||||||
|
icon: "people",
|
||||||
|
tooltip: "Avoid",
|
||||||
|
size: PreferenceSize.Small,
|
||||||
|
muted: true,
|
||||||
|
favourite: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defaultPreferences;
|
|
@ -16,6 +16,25 @@ export interface User {
|
||||||
pronouns: Pronoun[];
|
pronouns: Pronoun[];
|
||||||
members: PartialMember[];
|
members: PartialMember[];
|
||||||
fields: Field[];
|
fields: Field[];
|
||||||
|
custom_preferences: CustomPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CustomPreferences {
|
||||||
|
[key: string]: CustomPreference;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CustomPreference {
|
||||||
|
icon: string;
|
||||||
|
tooltip: string;
|
||||||
|
size: PreferenceSize;
|
||||||
|
muted: boolean;
|
||||||
|
favourite: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PreferenceSize {
|
||||||
|
Large = "large",
|
||||||
|
Normal = "normal",
|
||||||
|
Small = "small",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MeUser extends User {
|
export interface MeUser extends User {
|
||||||
|
@ -80,6 +99,7 @@ export interface MemberPartialUser {
|
||||||
name: string;
|
name: string;
|
||||||
display_name: string | null;
|
display_name: string | null;
|
||||||
avatar: string | null;
|
avatar: string | null;
|
||||||
|
custom_preferences: CustomPreferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Invite {
|
export interface Invite {
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Field } from "$lib/api/entities";
|
import type { CustomPreferences, Field } from "$lib/api/entities";
|
||||||
|
|
||||||
import StatusLine from "./StatusLine.svelte";
|
import StatusLine from "./StatusLine.svelte";
|
||||||
|
|
||||||
export let field: Field;
|
export let field: Field;
|
||||||
|
export let preferences: CustomPreferences;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3>{field.name}</h3>
|
<h3>{field.name}</h3>
|
||||||
<ul class="list-unstyled fs-5">
|
<ul class="list-unstyled fs-5">
|
||||||
{#each field.entries as entry}
|
{#each field.entries as entry}
|
||||||
<li><StatusLine status={entry.status}>{entry.value}</StatusLine></li>
|
<li><StatusLine {preferences} status={entry.status}>{entry.value}</StatusLine></li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,53 +1,24 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Icon, Tooltip } from "sveltestrap";
|
import { Icon, Tooltip } from "sveltestrap";
|
||||||
|
|
||||||
import { WordStatus } from "$lib/api/entities";
|
import type { CustomPreference, CustomPreferences } from "$lib/api/entities";
|
||||||
|
import defaultPreferences from "$lib/api/default_preferences";
|
||||||
|
|
||||||
export let status: WordStatus;
|
export let preferences: CustomPreferences;
|
||||||
|
export let status: string;
|
||||||
export let className: string | null = null;
|
export let className: string | null = null;
|
||||||
|
|
||||||
const iconFor = (wordStatus: WordStatus) => {
|
let mergedPreferences: CustomPreferences;
|
||||||
switch (wordStatus) {
|
$: mergedPreferences = Object.assign(defaultPreferences, preferences);
|
||||||
case WordStatus.Favourite:
|
|
||||||
return "heart-fill";
|
|
||||||
case WordStatus.Okay:
|
|
||||||
return "hand-thumbs-up";
|
|
||||||
case WordStatus.Jokingly:
|
|
||||||
return "emoji-laughing";
|
|
||||||
case WordStatus.FriendsOnly:
|
|
||||||
return "people";
|
|
||||||
case WordStatus.Avoid:
|
|
||||||
return "hand-thumbs-down";
|
|
||||||
default:
|
|
||||||
return "hand-thumbs-up";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const textFor = (wordStatus: WordStatus) => {
|
let currentPreference: CustomPreference;
|
||||||
switch (wordStatus) {
|
$: currentPreference =
|
||||||
case WordStatus.Favourite:
|
status in mergedPreferences ? mergedPreferences[status] : defaultPreferences.okay;
|
||||||
return "Favourite";
|
|
||||||
case WordStatus.Okay:
|
|
||||||
return "Okay";
|
|
||||||
case WordStatus.Jokingly:
|
|
||||||
return "Jokingly";
|
|
||||||
case WordStatus.FriendsOnly:
|
|
||||||
return "Friends only";
|
|
||||||
case WordStatus.Avoid:
|
|
||||||
return "Avoid";
|
|
||||||
default:
|
|
||||||
return "Okay";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let statusIcon: string;
|
|
||||||
$: statusIcon = iconFor(status);
|
|
||||||
|
|
||||||
let statusText: string;
|
|
||||||
$: statusText = textFor(status);
|
|
||||||
|
|
||||||
let iconElement: HTMLElement;
|
let iconElement: HTMLElement;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<span bind:this={iconElement} tabindex={0}><Icon name={statusIcon} class={className} /></span>
|
<span bind:this={iconElement} tabindex={0}
|
||||||
<Tooltip target={iconElement} placement="top">{statusText}</Tooltip>
|
><Icon name={currentPreference.icon} class={className} /></span
|
||||||
|
>
|
||||||
|
<Tooltip target={iconElement} placement="top">{currentPreference.tooltip}</Tooltip>
|
||||||
|
|
|
@ -1,14 +1,44 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { WordStatus } from "$lib/api/entities";
|
import { PreferenceSize } from "$lib/api/entities";
|
||||||
import StatusIcon from "$lib/components/StatusIcon.svelte";
|
import StatusIcon from "$lib/components/StatusIcon.svelte";
|
||||||
|
|
||||||
export let status: WordStatus;
|
import type { CustomPreference, CustomPreferences } from "$lib/api/entities";
|
||||||
|
import defaultPreferences from "$lib/api/default_preferences";
|
||||||
|
|
||||||
|
export let preferences: CustomPreferences;
|
||||||
|
export let status: string;
|
||||||
|
|
||||||
|
let mergedPreferences: CustomPreferences;
|
||||||
|
$: mergedPreferences = Object.assign(defaultPreferences, preferences);
|
||||||
|
|
||||||
|
let currentPreference: CustomPreference;
|
||||||
|
$: currentPreference =
|
||||||
|
status in mergedPreferences ? mergedPreferences[status] : defaultPreferences.okay;
|
||||||
|
|
||||||
|
let classes: string;
|
||||||
|
$: classes = setClasses(currentPreference);
|
||||||
|
|
||||||
|
const setClasses = (pref: CustomPreference) => {
|
||||||
|
let classes = "";
|
||||||
|
if (pref.muted) {
|
||||||
|
classes += "text-muted ";
|
||||||
|
}
|
||||||
|
switch (pref.size) {
|
||||||
|
case PreferenceSize.Large:
|
||||||
|
classes += "fs-5";
|
||||||
|
break;
|
||||||
|
case PreferenceSize.Normal:
|
||||||
|
break;
|
||||||
|
case PreferenceSize.Small:
|
||||||
|
classes += "fs-6";
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes.trim();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if status === WordStatus.Favourite}
|
{#if currentPreference.size === PreferenceSize.Large}
|
||||||
<strong class="fs-5"><StatusIcon {status} /> <slot /></strong>
|
<strong class={classes}><StatusIcon {preferences} {status} /> <slot /></strong>
|
||||||
{:else if status === WordStatus.Avoid}
|
|
||||||
<span class="fs-6 text-muted"><StatusIcon {status} /> <slot /></span>
|
|
||||||
{:else}
|
{:else}
|
||||||
<StatusIcon {status} /> <slot />
|
<span class={classes}><StatusIcon {preferences} {status} /> <slot /></span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -146,7 +146,7 @@
|
||||||
<h3>Names</h3>
|
<h3>Names</h3>
|
||||||
<ul class="list-unstyled fs-5">
|
<ul class="list-unstyled fs-5">
|
||||||
{#each data.names as name}
|
{#each data.names as name}
|
||||||
<li><StatusLine status={name.status}>{name.value}</StatusLine></li>
|
<li><StatusLine preferences={data.custom_preferences} status={name.status}>{name.value}</StatusLine></li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -156,14 +156,14 @@
|
||||||
<h3>Pronouns</h3>
|
<h3>Pronouns</h3>
|
||||||
<ul class="list-unstyled fs-5">
|
<ul class="list-unstyled fs-5">
|
||||||
{#each data.pronouns as pronouns}
|
{#each data.pronouns as pronouns}
|
||||||
<li><StatusLine status={pronouns.status}><PronounLink {pronouns} /></StatusLine></li>
|
<li><StatusLine preferences={data.custom_preferences} status={pronouns.status}><PronounLink {pronouns} /></StatusLine></li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#each data.fields as field}
|
{#each data.fields as field}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<FieldCard {field} />
|
<FieldCard preferences={data.custom_preferences} {field} />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
<h3>Names</h3>
|
<h3>Names</h3>
|
||||||
<ul class="list-unstyled fs-5">
|
<ul class="list-unstyled fs-5">
|
||||||
{#each data.names as name}
|
{#each data.names as name}
|
||||||
<li><StatusLine status={name.status}>{name.value}</StatusLine></li>
|
<li><StatusLine preferences={data.user.custom_preferences} status={name.status}>{name.value}</StatusLine></li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -91,14 +91,14 @@
|
||||||
<h3>Pronouns</h3>
|
<h3>Pronouns</h3>
|
||||||
<ul class="list-unstyled fs-5">
|
<ul class="list-unstyled fs-5">
|
||||||
{#each data.pronouns as pronouns}
|
{#each data.pronouns as pronouns}
|
||||||
<li><StatusLine status={pronouns.status}><PronounLink {pronouns} /></StatusLine></li>
|
<li><StatusLine preferences={data.user.custom_preferences} status={pronouns.status}><PronounLink {pronouns} /></StatusLine></li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#each data.fields as field}
|
{#each data.fields as field}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<FieldCard {field} />
|
<FieldCard preferences={data.user.custom_preferences} {field} />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue