initial commit

This commit is contained in:
Moon.eth
2026-07-29 09:16:38 +09:00
commit 586b599d4c
67 changed files with 9906 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
<script lang="ts">
/** Read-only poll results. Voting needs a write scope and a UI of its own. */
import type { Poll } from '$lib/api/types'
import { relativeTime } from '$lib/util/time'
import { formatCount } from '$lib/util/profile'
interface Props {
poll: Poll
}
let { poll }: Props = $props()
const total = $derived(poll.votes_count || 0)
function share(votes: number | null): number {
if (!total || votes === null) return 0
return Math.round((votes / total) * 100)
}
</script>
<div class="poll" data-expired={poll.expired ? 'true' : 'false'}>
{#each poll.options as option, index (index)}
<div class="poll-option" data-own-vote={poll.own_votes?.includes(index) ? 'true' : 'false'}>
<div class="poll-option-label">
<span class="poll-option-title">{option.title}</span>
<span class="poll-option-share">{share(option.votes_count)}%</span>
</div>
<div class="poll-option-bar">
<span class="poll-option-fill" style="width: {share(option.votes_count)}%"></span>
</div>
</div>
{/each}
<p class="poll-meta">
{formatCount(total)} vote{total === 1 ? '' : 's'}
{#if poll.expired}
&middot; closed
{:else if poll.expires_at}
&middot; closes {relativeTime(poll.expires_at).replace(' ago', ' from now')}
{/if}
</p>
</div>