username update, status message update, status overwriting, global
status in client
This commit is contained in:
parent
9ffb3cf283
commit
d9f5919b60
11 changed files with 235 additions and 79 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue