Coves frontend - a photon fork
at main 143 lines 3.6 kB view raw
1<script lang="ts"> 2 import { coves } from '$lib/api/client.svelte' 3 import type { CreateCommentOutput, StrongRef } from '$lib/api/coves/types' 4 import { profile } from '$lib/app/auth.svelte' 5 import { errorMessage } from '$lib/app/error' 6 import { t } from '$lib/app/i18n' 7 import Markdown from '$lib/app/markdown/Markdown.svelte' 8 import MarkdownEditor from '$lib/app/markdown/MarkdownEditor.svelte' 9 import { placeholders } from '$lib/app/util.svelte' 10 import { Button, toast } from 'mono-svelte' 11 import { Icon, XMark } from 'svelte-hero-icons/dist' 12 import type { ClassValue, HTMLTextareaAttributes } from 'svelte/elements' 13 14 interface Props extends Omit<HTMLTextareaAttributes, 'oncancel'> { 15 postRef: StrongRef 16 parentRef?: StrongRef | undefined 17 locked?: boolean 18 banned?: boolean 19 rows?: number 20 placeholder?: string | undefined 21 value?: string 22 actions?: boolean 23 tools?: boolean 24 preview?: boolean 25 class?: ClassValue 26 required?: boolean 27 id?: string 28 label?: string 29 editing?: boolean 30 oncomment?: (output: CreateCommentOutput, content: string) => void 31 onconfirm?: (value: string) => void 32 oncancel?: (cancel: boolean) => void 33 } 34 35 let { 36 postRef, 37 parentRef = undefined, 38 locked = false, 39 banned = false, 40 rows = 7, 41 placeholder = undefined, 42 value = $bindable(''), 43 actions = true, 44 preview: previewAction = true, 45 editing = false, 46 oncancel, 47 oncomment, 48 ...rest 49 }: Props = $props() 50 51 let loading = $state(false) 52 let preview = false 53 54 async function submit() { 55 if (!profile.current?.jwt) { 56 toast({ content: $t('toast.loginVoteGate'), type: 'warning' }) 57 return 58 } 59 if (value.trim() === '') return 60 if (editing) return 61 62 loading = true 63 64 try { 65 const response = await coves().createComment({ 66 reply: { 67 root: postRef, 68 parent: parentRef ?? postRef, 69 }, 70 content: value, 71 }) 72 oncomment?.(response, value) 73 74 value = '' 75 } catch (err) { 76 console.error(err) 77 toast({ 78 content: errorMessage(err), 79 type: 'error', 80 }) 81 } 82 83 loading = false 84 } 85</script> 86 87<form 88 onsubmit={(e) => { 89 e.preventDefault() 90 submit() 91 }} 92 class="flex flex-col gap-2 relative" 93> 94 {#if preview} 95 <div 96 class="bg-slate-100 dark:bg-zinc-900 px-3 py-2.5 h-64 border 97 border-slate-300 dark:border-zinc-700 rounded-md overflow-auto text-sm resize-y" 98 > 99 <Markdown source={value} /> 100 </div> 101 {:else} 102 <MarkdownEditor 103 {...rest} 104 {rows} 105 placeholder={locked 106 ? $t('comment.locked') 107 : banned 108 ? $t('comment.banned') 109 : (placeholder ?? placeholders.get('comment'))} 110 bind:value 111 disabled={locked || loading || banned} 112 previewButton={previewAction} 113 > 114 <div class="flex-1"></div> 115 {#if actions} 116 <Button 117 size="custom" 118 title={$t('common.cancel')} 119 onclick={() => oncancel?.(true)} 120 color="tertiary" 121 class="w-8 h-8" 122 rounding="xl" 123 > 124 <Icon 125 src={XMark} 126 size="16" 127 micro 128 class="text-slate-600 dark:text-zinc-400" 129 /> 130 </Button> 131 <Button 132 submit 133 color="primary" 134 rounding="xl" 135 {loading} 136 disabled={locked || loading || banned} 137 > 138 {$t('form.submit')} 139 </Button> 140 {/if} 141 </MarkdownEditor> 142 {/if} 143</form>