309 lines
13 KiB
Svelte
309 lines
13 KiB
Svelte
<script lang="ts">
|
|
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
|
import * as Tabs from '$lib/components/ui/tabs/index.js';
|
|
import Cog from '@lucide/svelte/icons/cog';
|
|
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
|
import { useSidebar } from '$lib/components/ui/sidebar/context.svelte.js';
|
|
import User from './extra/User.svelte';
|
|
import type { SessionValidationResult } from '$lib/server/auth';
|
|
import {
|
|
GroupID,
|
|
type AppPSD,
|
|
type OverviewGroup,
|
|
type OverviewServer,
|
|
type OverviewUser
|
|
} from '$lib';
|
|
import Button from './ui/button/button.svelte';
|
|
import Input from './ui/input/input.svelte';
|
|
import { enhance } from '$app/forms';
|
|
import { invalidateAll } from '$app/navigation';
|
|
import { fill_overview_data } from '$lib/state.svelte';
|
|
import { toast } from 'svelte-sonner';
|
|
|
|
import { overview_data } from '$lib/state.svelte';
|
|
|
|
// Props for the member sidebar.
|
|
let {
|
|
open = $bindable(true),
|
|
members = $bindable<OverviewUser[]>([]),
|
|
user,
|
|
psd,
|
|
currentEntity,
|
|
currentEntityId = $bindable<string | null>(null)
|
|
}: {
|
|
open: boolean;
|
|
members: OverviewUser[];
|
|
psd: AppPSD;
|
|
user: SessionValidationResult['user'];
|
|
currentEntity: OverviewGroup | OverviewServer;
|
|
currentEntityId: string | null;
|
|
} = $props();
|
|
|
|
let this_sidebar = useSidebar();
|
|
|
|
$effect(() => {
|
|
if (this_sidebar.open != open) {
|
|
this_sidebar.setOpen(open);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<Sidebar.Root side="right">
|
|
<Sidebar.Header>
|
|
<div class="align-center flex w-full justify-center">
|
|
{#if user && currentEntityId}
|
|
<Dialog.Root>
|
|
<Dialog.Trigger><Button variant="outline"><Cog></Cog></Button></Dialog.Trigger>
|
|
<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-100">
|
|
<Tabs.List class="grid w-full grid-cols-2">
|
|
<Tabs.Trigger value="users">User Permissions</Tabs.Trigger>
|
|
{#if user.id == currentEntity.ownerId}
|
|
<Tabs.Trigger value="admins">Admin Settings</Tabs.Trigger>
|
|
{/if}
|
|
</Tabs.List>
|
|
{#if GroupID.is(currentEntityId)}
|
|
{#if user.id == currentEntity.ownerId}
|
|
<Tabs.Content value="admins">
|
|
<form
|
|
method="POST"
|
|
action="?/configureGroup"
|
|
class="space-y-4 p-2"
|
|
use:enhance={() => {
|
|
return async ({ result }) => {
|
|
if (result.type == 'success') {
|
|
toast.success('Configured group succesfully');
|
|
}
|
|
|
|
if (result.type == 'error' || result.type == 'failure') {
|
|
toast.error(
|
|
'Could not configure group successfully: ' +
|
|
(result.type === 'error' ? result.error : result.data?.error)
|
|
);
|
|
}
|
|
|
|
await invalidateAll();
|
|
await fill_overview_data(psd);
|
|
};
|
|
}}
|
|
>
|
|
<input type="hidden" name="groupId" value={currentEntityId} />
|
|
|
|
<div class="flex items-center justify-between">
|
|
<label for="addMembers">Allow everyone to add users</label>
|
|
<input
|
|
type="checkbox"
|
|
id="addMembers"
|
|
name="addMembers"
|
|
checked={(currentEntity as OverviewGroup).permissions.addMembers}
|
|
class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
|
/>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between">
|
|
<label for="removeMembers">Allow everyone to remove users</label>
|
|
<input
|
|
type="checkbox"
|
|
id="removeMembers"
|
|
name="removeMembers"
|
|
checked={(currentEntity as OverviewGroup).permissions.removeMembers}
|
|
class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
|
/>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between">
|
|
<label for="changeTitle">Allow everyone to change title</label>
|
|
<input
|
|
type="checkbox"
|
|
id="changeTitle"
|
|
name="changeTitle"
|
|
checked={(currentEntity as OverviewGroup).permissions.changeTitle}
|
|
class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
|
/>
|
|
</div>
|
|
|
|
<Button type="submit" class="w-full">Save Changes</Button>
|
|
</form>
|
|
|
|
{#if (currentEntity as OverviewGroup).members === 1}
|
|
<form
|
|
method="POST"
|
|
action="?/deleteGroup"
|
|
class="border-t border-red-500/30 pt-4"
|
|
use:enhance={() => {
|
|
return async ({ result }) => {
|
|
if (result.type == 'success') {
|
|
toast.success('Group deleted successfully');
|
|
}
|
|
|
|
if (result.type == 'error' || result.type == 'failure') {
|
|
toast.error(
|
|
'Could not delete group successfully: ' +
|
|
(result.type === 'error' ? result.error : result.data?.error)
|
|
);
|
|
}
|
|
|
|
await invalidateAll();
|
|
await fill_overview_data(psd);
|
|
};
|
|
}}
|
|
>
|
|
<input type="hidden" name="groupId" value={currentEntityId} />
|
|
|
|
<Button type="submit" variant="destructive" class="w-full">
|
|
Delete group
|
|
</Button>
|
|
</form>
|
|
{/if}
|
|
</Tabs.Content>
|
|
{/if}
|
|
<Tabs.Content value="users">
|
|
<div class="space-y-6 p-2">
|
|
{#if (currentEntity as OverviewGroup).permissions.addMembers || user.id == currentEntity.ownerId}
|
|
{@const addableMembers = overview_data.friends.filter(
|
|
(z) => !members.find((h) => h.id == z.id)
|
|
)}
|
|
|
|
{#if addableMembers.length !== 0}
|
|
<form
|
|
method="POST"
|
|
action="?/addMembers"
|
|
class="space-y-4"
|
|
use:enhance={() => {
|
|
return async ({ result }) => {
|
|
if (result.type == 'success') {
|
|
toast.success('Users added successfully');
|
|
}
|
|
|
|
if (result.type == 'error' || result.type == 'failure') {
|
|
toast.error(
|
|
'Could not add users successfully: ' +
|
|
(result.type === 'error' ? result.error : result.data?.error)
|
|
);
|
|
}
|
|
|
|
await invalidateAll();
|
|
await fill_overview_data(psd);
|
|
};
|
|
}}
|
|
>
|
|
<input type="hidden" name="groupId" value={currentEntityId} />
|
|
|
|
<h1>Add members</h1>
|
|
|
|
{#each addableMembers as friend (friend.id)}
|
|
<label class="flex items-center gap-2">
|
|
<input type="checkbox" name="memberIds" value={friend.id} />
|
|
<User crown={false} user={friend} />
|
|
</label>
|
|
{/each}
|
|
|
|
<Button type="submit">Add selected members</Button>
|
|
</form>
|
|
<hr />
|
|
{/if}
|
|
{/if}
|
|
|
|
{#if (currentEntity as OverviewGroup).permissions.changeTitle || user.id == currentEntity.ownerId}
|
|
<form
|
|
method="POST"
|
|
action="?/changeTitle"
|
|
class="space-y-4"
|
|
use:enhance={() => {
|
|
return async ({ result }) => {
|
|
if (result.type == 'success') {
|
|
toast.success('Title changed successfully');
|
|
}
|
|
|
|
if (result.type == 'error' || result.type == 'failure') {
|
|
toast.error(
|
|
'Could not change title successfully: ' +
|
|
(result.type === 'error' ? result.error : result.data?.error)
|
|
);
|
|
}
|
|
|
|
await invalidateAll();
|
|
await fill_overview_data(psd);
|
|
};
|
|
}}
|
|
>
|
|
<input type="hidden" name="groupId" value={currentEntityId} />
|
|
|
|
<h1>Change title</h1>
|
|
|
|
<Input name="title" placeholder="New group title" required />
|
|
|
|
<Button type="submit">Change title</Button>
|
|
</form>
|
|
<hr />
|
|
{/if}
|
|
|
|
{#if (currentEntity as OverviewGroup).permissions.removeMembers || user.id == currentEntity.ownerId}
|
|
<form
|
|
method="POST"
|
|
action="?/removeMembers"
|
|
class="space-y-4"
|
|
use:enhance={() => {
|
|
return async ({ result }) => {
|
|
if (result.type == 'success') {
|
|
toast.success('Users removed successfully');
|
|
}
|
|
|
|
if (result.type == 'error' || result.type == 'failure') {
|
|
toast.error(
|
|
'Could not remove users successfully: ' +
|
|
(result.type === 'error' ? result.error : result.data?.error)
|
|
);
|
|
}
|
|
|
|
await invalidateAll();
|
|
await fill_overview_data(psd);
|
|
};
|
|
}}
|
|
>
|
|
<input type="hidden" name="groupId" value={currentEntityId} />
|
|
|
|
<h1>Remove members</h1>
|
|
|
|
{#each members.filter((z) => z.id != currentEntity.ownerId) as member (member.id)}
|
|
<label class="flex items-center gap-2">
|
|
<input type="checkbox" name="memberIds" value={member.id} />
|
|
<User crown={false} user={member} />
|
|
</label>
|
|
{/each}
|
|
|
|
<Button type="submit">Remove selected members</Button>
|
|
</form>
|
|
{/if}
|
|
</div>
|
|
</Tabs.Content>
|
|
{/if}
|
|
</Tabs.Root>
|
|
</Dialog.Content>
|
|
</Dialog.Root>
|
|
{/if}
|
|
</div>
|
|
</Sidebar.Header>
|
|
<Sidebar.Content>
|
|
<Sidebar.Group>
|
|
<Sidebar.GroupLabel>Members</Sidebar.GroupLabel>
|
|
|
|
<Sidebar.GroupContent>
|
|
<Sidebar.Menu>
|
|
{#each members as member (member.id)}
|
|
<Sidebar.MenuItem>
|
|
<Sidebar.MenuButton>
|
|
<User user={member} crown={member.id == currentEntity.ownerId} />
|
|
</Sidebar.MenuButton>
|
|
</Sidebar.MenuItem>
|
|
{/each}
|
|
</Sidebar.Menu>
|
|
</Sidebar.GroupContent>
|
|
</Sidebar.Group>
|
|
</Sidebar.Content>
|
|
</Sidebar.Root>
|