username update, status message update, status overwriting, global

status in client
This commit is contained in:
Soph :3 2026-01-13 00:20:10 +02:00
parent 9ffb3cf283
commit d9f5919b60
11 changed files with 235 additions and 79 deletions

View file

@ -14,7 +14,8 @@
import Button, { buttonVariants } from './ui/button/button.svelte';
import User from './extra/User.svelte';
import type { SessionValidationResult } from '$lib/server/auth';
import type { OverviewData } from '$lib';
import { Status, statuses, type OverviewData, type OverviewUser } from '$lib';
import Label from './ui/label/label.svelte';
let {
currentPage = $bindable<string | null>(),
@ -259,6 +260,7 @@
subPage = null;
}}
user={friend}
crown={false}
></User>
</Sidebar.MenuSubButton>
</Sidebar.MenuSubItem>
@ -349,5 +351,66 @@
</Sidebar.Menu>
</Sidebar.Group>
</Sidebar.Content>
<Sidebar.Footer class="border-t-2 p-2">
<Dialog.Root>
<Dialog.Trigger>
<User user={user as unknown as OverviewUser} crown={false} />
</Dialog.Trigger>
<Dialog.Content>
<form method="POST" action="?/updateProfile">
<Dialog.Header>
<Dialog.Title>Edit profile</Dialog.Title>
<Dialog.Description>Update how others see you.</Dialog.Description>
</Dialog.Header>
<div class="">
<Label for="userName">Username</Label>
<Input
id="userName"
name="userName"
placeholder="Your name"
value={user?.username}
required
minlength={2}
maxlength={32}
/>
</div>
<!-- Presence -->
<div class="space-y-1">
<Label for="status">Status</Label>
<select id="status" name="status" class="input" required>
<option value={Status.ONLINE} selected={user?.statusOverwrite === Status.ONLINE}
>Online</option
>
<option value={Status.DND} selected={user?.statusOverwrite === Status.DND}
>Do Not Disturb</option
>
<option value={Status.OFFLINE} selected={user?.statusOverwrite === Status.OFFLINE}
>Offline</option
>
</select>
</div>
<div class="space-y-1">
<Label for="statusMessage">Status message</Label>
<Input
id="statusMessage"
name="statusMessage"
placeholder="What's going on?"
value={user?.statusMessage ?? ''}
maxlength={64}
/>
</div>
<Dialog.Footer>
<Dialog.Close class={buttonVariants({ variant: 'outline' })}>Cancel</Dialog.Close>
<Button type="submit">Save</Button>
</Dialog.Footer>
</form>
</Dialog.Content>
</Dialog.Root>
</Sidebar.Footer>
<Sidebar.Rail />
</Sidebar.Root>

View file

@ -1,12 +1,14 @@
<script lang="ts">
import { Status, type UserWithStatus } from '$lib';
import { Status, statuses, type OverviewUser } from '$lib';
import Crown from '@lucide/svelte/icons/crown';
const {
onclick,
user,
crown
}: { crown: boolean; onclick?: (e: MouseEvent) => void; user: UserWithStatus } = $props();
}: { crown: boolean; onclick?: (e: MouseEvent) => void; user: OverviewUser } = $props();
let status: Status | undefined = $derived(statuses.get(user.id));
</script>
<div class="flex flex-row gap-2">
@ -16,20 +18,23 @@
alt={user.username}
class="size-6 rounded-full"
/>
<div class="relative">
{#if user.status === Status.OFFLINE}
<span
class="absolute end-0 bottom-0 block size-2 rounded-full bg-gray-500 ring-1 ring-white"
></span>
{:else if user.status === Status.DND}
<span class="absolute end-0 bottom-0 block size-2 rounded-full bg-red-500 ring-1 ring-white"
></span>
{:else if user.status === Status.ONLINE}
<span
class="absolute end-0 bottom-0 block size-2 rounded-full bg-green-500 ring-1 ring-white"
></span>
{/if}
</div>
{#if status}
<div class="relative">
{#if status.status === Status.OFFLINE}
<span
class="absolute end-0 bottom-0 block size-2 rounded-full bg-gray-500 ring-1 ring-white"
></span>
{:else if status.status === Status.DND}
<span
class="absolute end-0 bottom-0 block size-2 rounded-full bg-red-500 ring-1 ring-white"
></span>
{:else if status.status === Status.ONLINE}
<span
class="absolute end-0 bottom-0 block size-2 rounded-full bg-green-500 ring-1 ring-white"
></span>
{/if}
</div>
{/if}
</div>
<div>
<a
@ -46,8 +51,10 @@
<Crown></Crown>
{/if}
</a>
<div class="pl-2 text-xs text-gray-400 italic">
{user.statusMessage}
</div>
{#if status}
<div class="pl-2 text-xs text-gray-400 italic">
{status.statusMessage}
</div>
{/if}
</div>
</div>

View file

@ -12,7 +12,7 @@
type OverviewData,
type OverviewGroup,
type OverviewServer,
type UserWithStatus
type OverviewUser
} from '$lib';
import Button from './ui/button/button.svelte';
import Input from './ui/input/input.svelte';
@ -20,14 +20,14 @@
// Props for the member sidebar.
let {
open = $bindable(true),
members = $bindable<UserWithStatus[]>([]),
members = $bindable<OverviewUser[]>([]),
user,
data,
currentEntity,
currentEntityId = $bindable<string | null>(null)
}: {
open: boolean;
members: UserWithStatus[];
members: OverviewUser[];
data: OverviewData;
user: SessionValidationResult['user'];
currentEntity: OverviewGroup | OverviewServer;
@ -49,13 +49,13 @@
{#if user && currentEntityId}
<Dialog.Root>
<Dialog.Trigger><Button variant="outline"><Cog></Cog></Button></Dialog.Trigger>
<Dialog.Content class="sm:max-w-[425px]">
<Dialog.Content class="sm:max-w-106.25">
<Dialog.Header>
<Dialog.Title>Group Settings</Dialog.Title>
<Dialog.Description>Configure your group settings here.</Dialog.Description>
</Dialog.Header>
<Tabs.Root value="users" class="w-[400px]">
<Tabs.Root value="users" class="w-100">
<Tabs.List class="grid w-full grid-cols-2">
<Tabs.Trigger value="users">User Permissions</Tabs.Trigger>
{#if user.id == currentEntity.ownerId}
@ -194,9 +194,7 @@
{#each members as member (member.id)}
<Sidebar.MenuItem>
<Sidebar.MenuButton>
{#snippet child({ props })}
<User user={member} crown={member.id == currentEntity.ownerId} />
{/snippet}
<User user={member} crown={member.id == currentEntity.ownerId} />
</Sidebar.MenuButton>
</Sidebar.MenuItem>
{/each}