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[]; | ||||
|   members: PartialMember[]; | ||||
|   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 { | ||||
|  | @ -80,6 +99,7 @@ export interface MemberPartialUser { | |||
|   name: string; | ||||
|   display_name: string | null; | ||||
|   avatar: string | null; | ||||
|   custom_preferences: CustomPreferences; | ||||
| } | ||||
| 
 | ||||
| export interface Invite { | ||||
|  |  | |||
|  | @ -1,16 +1,17 @@ | |||
| <script lang="ts"> | ||||
|   import type { Field } from "$lib/api/entities"; | ||||
|   import type { CustomPreferences, Field } from "$lib/api/entities"; | ||||
| 
 | ||||
|   import StatusLine from "./StatusLine.svelte"; | ||||
| 
 | ||||
|   export let field: Field; | ||||
|   export let preferences: CustomPreferences; | ||||
| </script> | ||||
| 
 | ||||
| <div> | ||||
|   <h3>{field.name}</h3> | ||||
|   <ul class="list-unstyled fs-5"> | ||||
|     {#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} | ||||
|   </ul> | ||||
| </div> | ||||
|  |  | |||
|  | @ -1,53 +1,24 @@ | |||
| <script lang="ts"> | ||||
|   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; | ||||
| 
 | ||||
|   const iconFor = (wordStatus: WordStatus) => { | ||||
|     switch (wordStatus) { | ||||
|       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"; | ||||
|     } | ||||
|   }; | ||||
|   let mergedPreferences: CustomPreferences; | ||||
|   $: mergedPreferences = Object.assign(defaultPreferences, preferences); | ||||
| 
 | ||||
|   const textFor = (wordStatus: WordStatus) => { | ||||
|     switch (wordStatus) { | ||||
|       case WordStatus.Favourite: | ||||
|         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 currentPreference: CustomPreference; | ||||
|   $: currentPreference = | ||||
|     status in mergedPreferences ? mergedPreferences[status] : defaultPreferences.okay; | ||||
| 
 | ||||
|   let iconElement: HTMLElement; | ||||
| </script> | ||||
| 
 | ||||
| <span bind:this={iconElement} tabindex={0}><Icon name={statusIcon} class={className} /></span> | ||||
| <Tooltip target={iconElement} placement="top">{statusText}</Tooltip> | ||||
| <span bind:this={iconElement} tabindex={0} | ||||
|   ><Icon name={currentPreference.icon} class={className} /></span | ||||
| > | ||||
| <Tooltip target={iconElement} placement="top">{currentPreference.tooltip}</Tooltip> | ||||
|  |  | |||
|  | @ -1,14 +1,44 @@ | |||
| <script lang="ts"> | ||||
|   import { WordStatus } from "$lib/api/entities"; | ||||
|   import { PreferenceSize } from "$lib/api/entities"; | ||||
|   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> | ||||
| 
 | ||||
| {#if status === WordStatus.Favourite} | ||||
|   <strong class="fs-5"><StatusIcon {status} /> <slot /></strong> | ||||
| {:else if status === WordStatus.Avoid} | ||||
|   <span class="fs-6 text-muted"><StatusIcon {status} /> <slot /></span> | ||||
| {#if currentPreference.size === PreferenceSize.Large} | ||||
|   <strong class={classes}><StatusIcon {preferences} {status} /> <slot /></strong> | ||||
| {:else} | ||||
|   <StatusIcon {status} /> <slot /> | ||||
|   <span class={classes}><StatusIcon {preferences} {status} /> <slot /></span> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -146,7 +146,7 @@ | |||
|           <h3>Names</h3> | ||||
|           <ul class="list-unstyled fs-5"> | ||||
|             {#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} | ||||
|           </ul> | ||||
|         </div> | ||||
|  | @ -156,14 +156,14 @@ | |||
|           <h3>Pronouns</h3> | ||||
|           <ul class="list-unstyled fs-5"> | ||||
|             {#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} | ||||
|           </ul> | ||||
|         </div> | ||||
|       {/if} | ||||
|       {#each data.fields as field} | ||||
|         <div class="col"> | ||||
|           <FieldCard {field} /> | ||||
|           <FieldCard preferences={data.custom_preferences} {field} /> | ||||
|         </div> | ||||
|       {/each} | ||||
|     </div> | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ | |||
|           <h3>Names</h3> | ||||
|           <ul class="list-unstyled fs-5"> | ||||
|             {#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} | ||||
|           </ul> | ||||
|         </div> | ||||
|  | @ -91,14 +91,14 @@ | |||
|           <h3>Pronouns</h3> | ||||
|           <ul class="list-unstyled fs-5"> | ||||
|             {#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} | ||||
|           </ul> | ||||
|         </div> | ||||
|       {/if} | ||||
|       {#each data.fields as field} | ||||
|         <div class="col"> | ||||
|           <FieldCard {field} /> | ||||
|           <FieldCard preferences={data.user.custom_preferences} {field} /> | ||||
|         </div> | ||||
|       {/each} | ||||
|     </div> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue