Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.

Commit 16ca4e3

Browse files
committed
Management docs chat rooms
1 parent fbf69fc commit 16ca4e3

3 files changed

Lines changed: 372 additions & 15 deletions

File tree

src/lib/config/navigation.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,11 @@ function buildManagementDocsItems(): NavigationItem[] {
578578
label: "Entitlements",
579579
iconComponent: KeyRound,
580580
},
581+
{
582+
href: "/management-docs/chat-rooms",
583+
label: "Chat Rooms",
584+
iconComponent: MessageSquare,
585+
},
581586
];
582587

583588
return items;

src/routes/(protected)/chat-rooms/[chat_room_id]/+page.svelte

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<script lang="ts">
22
import { page } from "$app/state";
33
import { trackedFetch } from "$lib/utils/trackedFetch";
4-
import type { OBPChatRoomParticipant } from "$lib/obp/types";
4+
import type { OBPChatRoom, OBPChatRoomParticipant } from "$lib/obp/types";
55
66
const chatRoomId = $derived(page.params.chat_room_id);
77
const level = $derived(page.url.searchParams.get("level") || "system");
88
const bankId = $derived(page.url.searchParams.get("bank_id") || "");
99
10+
let room = $state<OBPChatRoom | null>(null);
1011
let participants = $state<OBPChatRoomParticipant[]>([]);
1112
let loading = $state(false);
1213
let error = $state<string | null>(null);
@@ -16,6 +17,24 @@
1617
let addUserId = $state("");
1718
let addPermissions = $state("can_send_message");
1819
20+
async function fetchRoom() {
21+
if (!chatRoomId) return;
22+
try {
23+
const bankParam = bankId ? `?bank_id=${encodeURIComponent(bankId)}` : "";
24+
const res = await trackedFetch(
25+
`/proxy/obp/v6.0.0/chat-rooms/${encodeURIComponent(chatRoomId)}${bankParam}`,
26+
);
27+
if (!res.ok) {
28+
const data = await res.json().catch(() => ({}));
29+
throw new Error(data.error || "Failed to fetch chat room");
30+
}
31+
room = await res.json();
32+
} catch (err) {
33+
error = err instanceof Error ? err.message : "Failed to fetch chat room";
34+
room = null;
35+
}
36+
}
37+
1938
async function fetchParticipants() {
2039
if (!chatRoomId) return;
2140
loading = true;
@@ -69,6 +88,37 @@
6988
}
7089
}
7190
91+
async function refreshJoiningKey() {
92+
if (!chatRoomId) return;
93+
error = null;
94+
successMessage = null;
95+
try {
96+
const endpoint =
97+
level === "bank" && bankId
98+
? `/proxy/obp/v6.0.0/banks/${encodeURIComponent(bankId)}/chat-rooms/${encodeURIComponent(chatRoomId)}/joining-key`
99+
: `/proxy/obp/v6.0.0/chat-rooms/${encodeURIComponent(chatRoomId)}/joining-key`;
100+
const res = await trackedFetch(endpoint, { method: "PUT" });
101+
if (!res.ok) {
102+
const data = await res.json().catch(() => ({}));
103+
throw new Error(data.error || "Failed to refresh joining key");
104+
}
105+
successMessage = "Joining key refreshed.";
106+
fetchRoom();
107+
} catch (err) {
108+
error = err instanceof Error ? err.message : "Failed to refresh joining key";
109+
}
110+
}
111+
112+
async function copyJoiningKey() {
113+
if (!room?.joining_key) return;
114+
try {
115+
await navigator.clipboard.writeText(room.joining_key);
116+
successMessage = "Joining key copied.";
117+
} catch {
118+
error = "Could not copy to clipboard.";
119+
}
120+
}
121+
72122
async function removeParticipant(userId: string) {
73123
if (!chatRoomId) return;
74124
error = null;
@@ -105,6 +155,7 @@
105155
}
106156
107157
$effect(() => {
158+
fetchRoom();
108159
fetchParticipants();
109160
});
110161
</script>
@@ -135,16 +186,41 @@
135186
Participants: {participants.length}
136187
</span>
137188
{/if}
138-
<button
139-
onclick={() => (showAddForm = !showAddForm)}
140-
class="inline-flex items-center rounded-lg bg-blue-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600"
141-
data-testid="add-participant-btn"
142-
>
143-
{showAddForm ? "Cancel" : "Add Participant"}
144-
</button>
189+
{#if !room?.is_open_room}
190+
<button
191+
onclick={() => (showAddForm = !showAddForm)}
192+
class="inline-flex items-center rounded-lg bg-blue-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600"
193+
data-testid="add-participant-btn"
194+
>
195+
{showAddForm ? "Cancel" : "Add Participant"}
196+
</button>
197+
{/if}
145198
</div>
146199
</div>
147200

201+
{#if room && !room.is_open_room && room.joining_key}
202+
<div class="mb-4 rounded-lg border border-gray-200 bg-white p-3 dark:border-gray-700 dark:bg-gray-800" data-testid="joining-key-panel">
203+
<div class="flex flex-wrap items-center gap-3">
204+
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">Joining Key:</span>
205+
<code class="flex-1 min-w-0 truncate rounded bg-gray-100 px-2 py-1 font-mono text-sm text-gray-900 dark:bg-gray-900 dark:text-gray-100" data-testid="joining-key-value">{room.joining_key}</code>
206+
<button
207+
onclick={copyJoiningKey}
208+
class="inline-flex items-center rounded border border-gray-300 bg-white px-2 py-1 text-xs font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600"
209+
data-testid="copy-joining-key-btn"
210+
>
211+
Copy
212+
</button>
213+
<button
214+
onclick={refreshJoiningKey}
215+
class="inline-flex items-center rounded border border-gray-300 bg-white px-2 py-1 text-xs font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600"
216+
data-testid="refresh-joining-key-btn"
217+
>
218+
Refresh
219+
</button>
220+
</div>
221+
</div>
222+
{/if}
223+
148224
{#if successMessage}
149225
<div class="mb-4 rounded-lg border border-green-200 bg-green-50 p-3 text-sm text-green-800 dark:border-green-800 dark:bg-green-900/20 dark:text-green-200" data-testid="success-message">
150226
{successMessage}
@@ -258,12 +334,18 @@
258334
</table>
259335
</div>
260336
{:else if !error}
261-
<div class="rounded-lg bg-gray-100 p-8 text-center dark:bg-gray-800">
262-
<p class="text-lg font-medium text-gray-700 dark:text-gray-300">
263-
No participants found
264-
</p>
265-
<p class="mt-1 text-gray-600 dark:text-gray-400">
266-
Add a participant to this chat room.
267-
</p>
337+
<div class="rounded-lg bg-gray-100 p-8 text-center dark:bg-gray-800" data-testid="empty-participants">
338+
{#if room?.is_open_room}
339+
<p class="text-lg font-medium text-gray-700 dark:text-gray-300" data-testid="everyone-label">
340+
This room is Open. Everyone can join.
341+
</p>
342+
{:else}
343+
<p class="text-lg font-medium text-gray-700 dark:text-gray-300">
344+
No participants found
345+
</p>
346+
<p class="mt-1 text-gray-600 dark:text-gray-400">
347+
Add a participant to this chat room.
348+
</p>
349+
{/if}
268350
</div>
269351
{/if}

0 commit comments

Comments
 (0)