Files
Evoke/src/lib/components/chat/TextComposer.svelte
T

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>