Monorepo for Tangled
Something went wrong. Try again.
3.2 kB · 135 lines
Svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136<script lang="ts"> import Check from "$icon/check"; import X from "$icon/x"; import TriangleAlert from "$icon/triangle-alert"; import { createAction } from "$lib/action.svelte"; import { createReport, reportErrorMessage, type ReportSubject } from "$lib/api/moderation"; import { getAuth } from "$lib/auth.svelte"; import type { Did } from "@atcute/lexicons/syntax"; import Button from "$lib/components/ui/Button.svelte"; import Combobox from "$lib/components/ui/Combobox.svelte"; import ErrorAlert from "$lib/components/ui/Error.svelte"; import Field from "$lib/components/ui/Field.svelte"; import Modal from "$lib/components/ui/Modal.svelte"; import Textarea from "$lib/components/ui/Textarea.svelte"; import { REPORT_REASONS } from "$lib/components/moderation/reportReasons";
interface Props { open?: boolean; subject: ReportSubject; subjectLabel: string; labelerDid: string; reporterDid?: string; }
let { open = $bindable(false), subject, subjectLabel, labelerDid, reporterDid }: Props = $props();
const auth = getAuth();
let reasonType = $state(""); let details = $state(""); let sent = $state(false);
const clear = () => { reasonType = ""; details = ""; sent = false; };
$effect(() => { void subject; clear(); });
let showing = false; $effect(() => { if (open && !showing && sent) clear(); showing = open; });
const submit = createAction(async () => { const did = reporterDid ?? auth.currentDid; if (!did || !reasonType) return; const agent = await auth.agentFor(did as Did); await createReport(agent, labelerDid, { subject, reasonType, reason: details }); sent = true; }, reportErrorMessage);</script>
<Modal bind:open title={sent ? "Report sent" : `Report ${subjectLabel}`} titleIcon={TriangleAlert} description={!sent ? "Reports go to Tangled's moderation service. They are not shared with the person you are reporting." : ""}> {#if !sent} <Field label="Reason" required> {#snippet children({ id })} <Combobox {id} options={REPORT_REASONS} bind:value={reasonType} placeholder="Pick a reason" disabled={submit.loading} filter={false} /> {/snippet} </Field>
<Field label="Details" subtitle="Optional, but it helps."> {#snippet children({ id })} <Textarea {id} bind:value={details} size="small" resizeable maxlength={2000} placeholder="Anything the moderators should know?" disabled={submit.loading} /> {/snippet} </Field>
<ErrorAlert label={submit.error} /> {:else} <p class="text-foreground-muted"> The moderation team will take it from here. Thanks for the report. </p> {/if}
{#snippet footer()} {#if sent} <Button variant="default" class="flex-1" icon={Check} onclick={() => (open = false)}> Done </Button> {:else} <Button variant="default" class="flex-1" icon={X} disabled={submit.loading} onclick={() => (open = false)} > Cancel </Button> <Button variant="danger" icon={Check} class="flex-1" loading={submit.loading} disabled={!reasonType} onclick={() => submit.run()} > Submit report </Button> {/if} {/snippet}</Modal>