Files
beavergram/frontend/src/lib/components/watches/WatchEditor.svelte
T

122 lines
2.5 KiB
Svelte

<script lang="ts">
import Button from "../ui/Button.svelte";
interface Props {
onsave: (data: {
kind: string;
params: Record<string, unknown>;
enabled: boolean;
}) => void;
saving?: boolean;
}
const { saving = false, onsave }: Props = $props();
const KINDS = [
{ value: "keyword", label: "Keyword" },
{ value: "peer_online", label: "Peer online" },
];
let kind = $state("keyword");
let keyword = $state("");
let peerId = $state("");
let enabled = $state(true);
const isKeyword = $derived(kind === "keyword");
const valid = $derived(
isKeyword ? keyword.trim() !== "" : peerId.trim() !== ""
);
function submit() {
if (!valid) {
return;
}
const params: Record<string, unknown> = isKeyword
? { keyword: keyword.trim() }
: { peer_id: Number(peerId.trim()) };
onsave({ kind, params, enabled });
keyword = "";
peerId = "";
enabled = true;
}
</script>
<form
class="watch-editor"
onsubmit={(e) => {
e.preventDefault();
submit();
}}
>
<label class="field">
<span class="field-label">Type</span>
<select bind:value={kind}>
{#each KINDS as option (option.value)}
<option value={option.value}>{option.label}</option>
{/each}
</select>
</label>
{#if isKeyword}
<label class="field">
<span class="field-label">Keyword</span>
<input type="text" bind:value={keyword} placeholder="Text to match…">
</label>
{:else}
<label class="field">
<span class="field-label">Peer ID</span>
<input
type="text"
inputmode="numeric"
bind:value={peerId}
placeholder="123456789"
>
</label>
{/if}
<label class="field-inline">
<input type="checkbox" bind:checked={enabled}>
<span>Enabled</span>
</label>
<Button type="submit" disabled={saving || !valid}>Add watch</Button>
</form>
<style lang="scss">
.watch-editor {
display: flex;
flex-direction: column;
gap: 0.625rem;
padding: 0.75rem;
border: 1px solid var(--color-borders);
border-radius: 0.75rem;
}
.field {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.field-label {
font-size: 0.8125rem;
color: var(--color-text-secondary);
}
.field-inline {
display: flex;
align-items: center;
gap: 0.5rem;
}
input[type="text"],
select {
width: 100%;
padding: 0.5rem;
border: 1px solid var(--color-borders);
border-radius: 0.5rem;
background: var(--color-background);
color: var(--color-text);
}
</style>