Files
flotilla/src/app/components/AlertAdd.svelte
T
2025-03-20 09:38:57 -07:00

167 lines
4.7 KiB
Svelte

<script lang="ts">
import {preventDefault} from "@lib/html"
import {randomInt} from "@welshman/lib"
import {displayRelayUrl, THREAD, MESSAGE, EVENT_TIME, COMMENT} from "@welshman/util"
import type {Filter} from "@welshman/util"
import {pubkey} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import {GENERAL, getMembershipUrls, getMembershipRoomsByUrl, userMembership} from "@app/state"
import {loadAlertStatuses} from "@app/requests"
import {publishAlert} from "@app/commands"
import {pushToast} from "@app/toast"
const timezone = new Date()
.toString()
.match(/GMT[^\s]+/)![0]
.slice(3)
const timezoneOffset = parseInt(timezone) / 100
const minute = randomInt(0, 59)
const hour = (17 - timezoneOffset) % 24
const WEEKLY = `0 ${minute} ${hour} * * 1`
const DAILY = `0 ${minute} ${hour} * * *`
let loading = false
let cron = WEEKLY
let email = ""
let relay = ""
let notifyThreads = true
let notifyCalendar = true
let notifyChat = false
const back = () => history.back()
const submit = async () => {
if (!email.includes("@")) {
return pushToast({
theme: "error",
message: "Please provide an email address",
})
}
if (!relay) {
return pushToast({
theme: "error",
message: "Please select a space",
})
}
if (!notifyThreads && !notifyCalendar && !notifyChat) {
return pushToast({
theme: "error",
message: "Please select something to be notified about",
})
}
const filters: Filter[] = []
if (notifyThreads) {
filters.push({kinds: [THREAD]})
filters.push({kinds: [COMMENT], "#k": [String(THREAD)]})
}
if (notifyCalendar) {
filters.push({kinds: [EVENT_TIME]})
filters.push({kinds: [COMMENT], "#k": [String(EVENT_TIME)]})
}
if (notifyChat) {
filters.push({
kinds: [MESSAGE],
"#h": [GENERAL, ...getMembershipRoomsByUrl(relay, $userMembership)],
})
}
loading = true
try {
const thunk = await publishAlert({cron, email, relay, filters})
await thunk.result
await loadAlertStatuses($pubkey!)
pushToast({message: "Your alert has been successfully created!"})
back()
} finally {
loading = false
}
}
</script>
<form class="column gap-4" onsubmit={preventDefault(submit)}>
<ModalHeader>
{#snippet title()}
Add an Alert
{/snippet}
</ModalHeader>
<FieldInline>
{#snippet label()}
<p>Email Address*</p>
{/snippet}
{#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2">
<input placeholder="email@example.com" bind:value={email} />
</label>
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Frequency*</p>
{/snippet}
{#snippet input()}
<select bind:value={cron} class="select select-bordered">
<option value={WEEKLY}>Weekly</option>
<option value={DAILY}>Daily</option>
</select>
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Space*</p>
{/snippet}
{#snippet input()}
<select bind:value={relay} class="select select-bordered">
<option value="" disabled selected>Choose a space URL</option>
{#each getMembershipUrls($userMembership) as url (url)}
<option value={url}>{displayRelayUrl(url)}</option>
{/each}
</select>
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Notifications*</p>
{/snippet}
{#snippet input()}
<div class="flex items-center justify-end gap-4">
<span class="flex gap-3">
<input type="checkbox" class="checkbox" bind:checked={notifyThreads} />
Threads
</span>
<span class="flex gap-3">
<input type="checkbox" class="checkbox" bind:checked={notifyCalendar} />
Calendar
</span>
<span class="flex gap-3">
<input type="checkbox" class="checkbox" bind:checked={notifyChat} />
Chat
</span>
</div>
{/snippet}
</FieldInline>
<ModalFooter>
<Button class="btn btn-link" onclick={back}>
<Icon icon="alt-arrow-left" />
Go back
</Button>
<Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading}>Confirm</Spinner>
<Icon icon="alt-arrow-right" />
</Button>
</ModalFooter>
</form>