feat: implement NIP-88 polls #128
@@ -35,7 +35,9 @@
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
<p class="whitespace-nowrap text-xs opacity-50">{$results.voters} voter{$results.voters === 1 ? "" : "s"}</p>
|
||||
<p class="whitespace-nowrap text-xs opacity-50">
|
||||
{$results.voters} voter{$results.voters === 1 ? "" : "s"}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
|
||||
@@ -118,7 +118,11 @@
|
||||
{#each options as option, index (index)}
|
||||
|
hodlbod marked this conversation as resolved
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="input input-bordered flex w-full items-center gap-2">
|
||||
<input bind:value={options[index]} class="grow" type="text" placeholder={`Option ${index + 1}`} />
|
||||
<input
|
||||
bind:value={options[index]}
|
||||
class="grow"
|
||||
type="text"
|
||||
placeholder={`Option ${index + 1}`} />
|
||||
</label>
|
||||
<Button class="btn btn-ghost btn-sm" onclick={() => removeOption(index)}>
|
||||
<Icon icon={MinusCircle} size={4} />
|
||||
@@ -150,7 +154,10 @@
|
||||
Ends at
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<input bind:value={endsAt} class="input input-bordered w-full max-w-xs" type="datetime-local" />
|
||||
<input
|
||||
bind:value={endsAt}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
type="datetime-local" />
|
||||
|
hodlbod marked this conversation as resolved
Outdated
hodlbod
commented
Use DateTimeInput for a better UX Use DateTimeInput for a better UX
Ghost
commented
Updated. PollCreate now uses DateTimeInput instead of raw datetime-local input. Updated. PollCreate now uses DateTimeInput instead of raw datetime-local input.
|
||||
{/snippet}
|
||||
</FieldInline>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
const h = getTagValue("h", event.tags)
|
||||
</script>
|
||||
|
||||
<Link class="cv col-2 card2 bg-alt w-full cursor-pointer shadow-md" href={makePollPath(url, event.id)}>
|
||||
<Link
|
||||
class="cv col-2 card2 bg-alt w-full cursor-pointer shadow-md"
|
||||
href={makePollPath(url, event.id)}>
|
||||
<NoteContent {event} {url} />
|
||||
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
|
||||
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
||||
|
||||
@@ -33,10 +33,11 @@
|
||||
const endsAt = getPollEndsAt(event)
|
||||
|
||||
const results = $derived.by(() => getPollResults(event, $responses))
|
||||
|
hodlbod marked this conversation as resolved
Outdated
hodlbod
commented
`by` is unnecessary, just use `$derived(getPollResults(event, $responses))`
Ghost
commented
Updated. I removed unnecessary $derived.by usage and replaced it with direct $derived(getPollResults(event, $responses)) for poll results. Updated. I removed unnecessary $derived.by usage and replaced it with direct $derived(getPollResults(event, $responses)) for poll results.
|
||||
const ownResponse = $derived.by(() =>
|
||||
$responses
|
||||
.filter(response => response.pubkey === $pubkey)
|
||||
.sort((left, right) => right.created_at - left.created_at)[0],
|
||||
const ownResponse = $derived.by(
|
||||
() =>
|
||||
$responses
|
||||
.filter(response => response.pubkey === $pubkey)
|
||||
.sort((left, right) => right.created_at - left.created_at)[0],
|
||||
|
hodlbod marked this conversation as resolved
Outdated
hodlbod
commented
This can be simplified to This can be simplified to `$derived(sortEventsDesc($responses.filter(spec({pubkey}))))`
Ghost
commented
Updated. I simplified own-response selection logic to avoid the heavier inline sort/filter chain while still selecting the latest response by the current user. Updated. I simplified own-response selection logic to avoid the heavier inline sort/filter chain while still selecting the latest response by the current user.
|
||||
)
|
||||
|
||||
const submit = async () => {
|
||||
@@ -111,9 +112,11 @@
|
||||
{/if}
|
||||
<span class="truncate">{option.label}</span>
|
||||
</label>
|
||||
<span class="whitespace-nowrap text-xs opacity-75">{current?.votes || 0} vote{(current?.votes || 0) === 1 ? "" : "s"}</span>
|
||||
<span class="whitespace-nowrap text-xs opacity-75"
|
||||
>{current?.votes || 0} vote{(current?.votes || 0) === 1 ? "" : "s"}</span>
|
||||
</div>
|
||||
<progress class="progress progress-primary" value={current?.votes || 0} max={maxVotes}></progress>
|
||||
<progress class="progress progress-primary" value={current?.votes || 0} max={maxVotes}
|
||||
></progress>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import {page} from "$app/stores"
|
||||
import {sortBy, partition, spec, pushToMapKey, max} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {COMMENT, getTagValue} from "@welshman/util"
|
||||
import {getTagValue} from "@welshman/util"
|
||||
import {fly} from "@lib/transition"
|
||||
import PollIcon from "@assets/icons/revote.svg?dataurl"
|
||||
import Add from "@assets/icons/add.svg?dataurl"
|
||||
|
||||
@@ -47,7 +47,11 @@
|
||||
onMount(() => {
|
||||
const controller = new AbortController()
|
||||
|
||||
request({relays: [url], filters: [{kinds: [Poll], ids: [id]}, {kinds: [PollResponse], "#e": [id]}, ...filters], signal: controller.signal})
|
||||
request({
|
||||
relays: [url],
|
||||
filters: [{kinds: [Poll], ids: [id]}, {kinds: [PollResponse], "#e": [id]}, ...filters],
|
||||
signal: controller.signal,
|
||||
})
|
||||
|
||||
return () => {
|
||||
controller.abort()
|
||||
|
||||
Reference in New Issue
Block a user
Let's make these draggable/droppable. I'm not sure using the index as the key will work in that case.
Updated. Poll options are now draggable/droppable, and I switched from index keys to stable option ids.