diff --git a/references/README.md b/references/README.md
deleted file mode 100644
index aeec614..0000000
--- a/references/README.md
+++ /dev/null
@@ -1 +0,0 @@
-The files here are not for use. I use them as inspiration.
diff --git a/references/members-sidebar.svelte b/references/members-sidebar.svelte
deleted file mode 100644
index 34c391d..0000000
--- a/references/members-sidebar.svelte
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
- Members ({members.length})
-
-
-
-
-
- {#each members as member (member.id)}
-
-
-
- {member.name}
-
-
- {/each}
-
-
-
-
diff --git a/references/search-form.svelte b/references/search-form.svelte
deleted file mode 100644
index ecad833..0000000
--- a/references/search-form.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
diff --git a/references/settings-dialog.svelte b/references/settings-dialog.svelte
deleted file mode 100644
index 1c84f27..0000000
--- a/references/settings-dialog.svelte
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
- Settings
-
- Configure your application settings
-
-
-
-
-
hi
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/components/member-sidebar.svelte b/src/lib/components/member-sidebar.svelte
new file mode 100644
index 0000000..0a0a15a
--- /dev/null
+++ b/src/lib/components/member-sidebar.svelte
@@ -0,0 +1,93 @@
+
+
+
+
+
+ Members
+
+
+
+ {#each members as member (member.id)}
+
+
+ {#snippet child({ props })}
+
+ {/snippet}
+
+
+ {/each}
+
+
+
+
+ {#if currentEntityId && ServerID.is(currentEntityId) && user}
+
+ Server Actions
+
+
+
+
+
+ {#snippet child({ props })}
+
+ {/snippet}
+
+
+
+ {#if user.id === members.find((m) => m.id === currentEntityId)?.ownerId}
+
+
+ {#snippet child({ props })}
+
+ {/snippet}
+
+
+ {/if}
+
+
+
+ {/if}
+
+
diff --git a/src/routes/api/members/[entityId]/+server.ts b/src/routes/api/members/[entityId]/+server.ts
new file mode 100644
index 0000000..640364c
--- /dev/null
+++ b/src/routes/api/members/[entityId]/+server.ts
@@ -0,0 +1,58 @@
+import { db } from '$lib/server/db';
+import * as table from '$lib/server/db/schema';
+import { eq, inArray } from 'drizzle-orm';
+import { GroupID, ServerID } from '$lib';
+import { error, json } from '@sveltejs/kit';
+import type { RequestHandler } from './$types';
+
+export const GET: RequestHandler = async ({ params }) => {
+ const { entityId } = params;
+
+ if (!entityId) {
+ throw error(400, 'Entity ID is required');
+ }
+
+ if (GroupID.is(entityId)) {
+ const group = await db.select().from(table.group).where(eq(table.group.id, entityId));
+
+ if (!group || group?.length == 0) {
+ throw error(404, 'Group not found');
+ }
+
+ const members = await db
+ .select()
+ .from(table.user)
+ .where(inArray(table.user.id, group[0].members as string[]));
+
+ return json({
+ members: members.map((member) => ({
+ id: member.id,
+ username: member.username,
+ image: `https://api.dicebear.com/7.x/pixel-art/svg?seed=${member.username}`
+ }))
+ });
+ }
+
+ if (ServerID.is(entityId)) {
+ const server = await db.select().from(table.server).where(eq(table.server.id, entityId));
+
+ if (!server || server?.length == 0) {
+ throw error(404, 'Server not found');
+ }
+
+ const members = await db
+ .select()
+ .from(table.user)
+ .where(inArray(table.user.id, server[0].members as string[]));
+
+ return json({
+ members: members.map((member) => ({
+ id: member.id,
+ username: member.username,
+ image: `https://api.dicebear.com/7.x/pixel-art/svg?seed=${member.username}`
+ }))
+ });
+ }
+
+ throw error(400, 'Invalid entity ID');
+};
diff --git a/src/routes/app/+page.svelte b/src/routes/app/+page.svelte
index 322445a..85a8392 100644
--- a/src/routes/app/+page.svelte
+++ b/src/routes/app/+page.svelte
@@ -24,13 +24,19 @@
import Input from '$lib/components/ui/input/input.svelte';
import { Button } from '$lib/components/ui/button';
- import { SendHorizontal } from '@lucide/svelte';
+ import SendHorizontal from '@lucide/svelte/icons/send-horizontal';
+ import PersonStanding from '@lucide/svelte/icons/person-standing';
+ import MemberSidebar from '$lib/components/member-sidebar.svelte';
+
let errorOpen = $state(true);
let { form, data }: { form: ActionData; data: PageServerData } = $props();
let currentPageID: (UserId | GroupId | ServerId) | null = $state(null);
let currentPage: OverviewUser | OverviewGroup | OverviewServer | undefined = $state();
+ let isMembersTabOpen = $state(true);
+ let members: UserWithStatus[] = $state([]);
+
let messages: ReturnMessage[] = $state([]);
let inputValue = $state();
@@ -57,6 +63,20 @@
}
});
+ $effect(() => {
+ if (!currentPageID || !currentPage) return;
+ if (ServerID.is(currentPageID) || GroupID.is(currentPageID)) {
+ async function fetchMembers() {
+ const req = await fetch(`/api/members/${currentPageID}`);
+ const data = await req.json();
+ members = data.members;
+ }
+ fetchMembers();
+ } else {
+ isMembersTabOpen = false;
+ }
+ });
+
$effect(() => {
if (!currentPageID || !currentPage) return;
if (ServerID.is(currentPageID)) return;
@@ -96,7 +116,6 @@
id: ServerID.parse(z.id),
name: z.name,
ownerId: z.ownerId,
-
image: 'https://api.dicebear.com/7.x/pixel-art/svg?seed=' + z.name
};
});
@@ -180,7 +199,6 @@
-
@@ -210,6 +228,19 @@
{group!.name} ({group.members} member{group.members > 1 ? 's' : ''})
{/if}
+ {#if ServerID.is(currentPageID) || GroupID.is(currentPageID)}
+
+ {/if}
{/if}
@@ -288,4 +319,14 @@
{/if}
+
+
+
+
+