new-room-window.svelte RawHistoryFolder
1<script lang="ts">
2 import XpWindow from './xp-window.svelte';
3 import { desktop } from '$lib/states/desktop.svelte';
4 import { chatState } from '$lib/states/chat.svelte';
5 import { useAimClient } from '$lib/aim/client';
6
7 const client = useAimClient();
8 const signedIn = $derived(Boolean(chatState.getCurrentUser()));
9 let name = $state('');
10 let topic = $state('');
11 let pending = $state(false);
12 let error = $state('');
13
14 async function create() {
15 const trimmedName = name.trim();
16 const trimmedTopic = topic.trim();
17 if (trimmedName.length < 2 || trimmedName.length > 40) {
18 error = 'Le nom du salon doit contenir entre 2 et 40 caractères.';
19 return;
20 }
21 if (trimmedTopic.length > 120) {
22 error = 'Le sujet ne peut pas dépasser 120 caractères.';
23 return;
24 }
25 pending = true;
26 error = '';
27 try {
28 const room = await client.createGroupRoom(trimmedName, trimmedTopic || undefined);
29 desktop.openChatRoom(room.id, trimmedName);
30 desktop.close('new-room');
31 } catch (err) {
32 error = err instanceof Error ? err.message : 'Impossible de créer le salon.';
33 } finally {
34 pending = false;
35 }
36 }
37</script>
38
39<XpWindow id="new-room" width={340} height={220} resizableWindow={false}>
40 <div class="content">
41 {#if signedIn}
42 <label for="room-name">Nom du salon</label>
43 <input
44 id="room-name"
45 type="text"
46 maxlength="40"
47 minlength="2"
48 bind:value={name}
49 oninput={() => (error = '')}
50 />
51 <label for="room-topic">Sujet (facultatif)</label>
52 <input
53 id="room-topic"
54 type="text"
55 maxlength="120"
56 bind:value={topic}
57 oninput={() => (error = '')}
58 />
59 {#if error}<span role="alert">{error}</span>{/if}
60 {:else}
61 <p>Connectez-vous pour créer un salon.</p>
62 {/if}
63 <div class="actions">
64 {#if signedIn}<button disabled={pending} onclick={create}>Créer</button>{:else}<button
65 onclick={() => desktop.openLogin('signin')}>Se connecter</button
66 >{/if}
67 <button onclick={() => desktop.close('new-room')}>Annuler</button>
68 </div>
69 </div>
70</XpWindow>
71
72<style>
73 .content {
74 display: flex;
75 flex-direction: column;
76 gap: 7px;
77 height: 100%;
78 font:
79 11px Tahoma,
80 'Pixelated MS Sans Serif',
81 sans-serif;
82 }
83 input {
84 width: 100%;
85 box-sizing: border-box;
86 font: inherit;
87 }
88 .actions {
89 display: flex;
90 justify-content: flex-end;
91 gap: 6px;
92 margin-top: auto;
93 }
94 [role='alert'] {
95 color: #a00;
96 }
97</style>