55 lines
1.5 KiB
Svelte
55 lines
1.5 KiB
Svelte
<script lang="ts">
|
|
import { Button } from '$lib/components/ui/button';
|
|
|
|
interface Props {
|
|
channelId: string;
|
|
placeholder?: string;
|
|
onSent?: () => void;
|
|
}
|
|
let { channelId, placeholder = 'Message...', onSent }: Props = $props();
|
|
|
|
let text = $state('');
|
|
let sending = $state(false);
|
|
|
|
async function send() {
|
|
const trimmed = text.trim();
|
|
if (!trimmed || sending) return;
|
|
sending = true;
|
|
text = '';
|
|
try {
|
|
const res = await fetch(`/api/channels/${channelId}/messages`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ type: 'text', body: trimmed }),
|
|
credentials: 'include'
|
|
});
|
|
if (!res.ok) {
|
|
const data = await res.json().catch(() => ({}));
|
|
throw new Error(data.error ?? 'Send failed');
|
|
}
|
|
onSent?.();
|
|
} catch (err) {
|
|
console.error('Send failed', err);
|
|
text = trimmed;
|
|
} finally {
|
|
sending = false;
|
|
}
|
|
}
|
|
|
|
function handleSubmit(e: Event) {
|
|
e.preventDefault();
|
|
send();
|
|
}
|
|
</script>
|
|
|
|
<form class="flex gap-2 items-end" onsubmit={handleSubmit}>
|
|
<input
|
|
type="text"
|
|
bind:value={text}
|
|
placeholder={placeholder}
|
|
class="flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
disabled={sending}
|
|
/>
|
|
<Button type="submit" disabled={sending || !text.trim()}>Send</Button>
|
|
</form>
|