diff --git a/src/auto-imports.d.ts b/src/auto-imports.d.ts index abef9a6..074b47d 100644 --- a/src/auto-imports.d.ts +++ b/src/auto-imports.d.ts @@ -20,6 +20,8 @@ declare global { const IconMdiAccountCircle: typeof import('~icons/mdi/account-circle.jsx').default const IconMdiAccountPlus: typeof import('~icons/mdi/account-plus.jsx').default const IconMdiCheck: typeof import('~icons/mdi/check.jsx').default + const IconMdiCheckCircle: typeof import('~icons/mdi/check-circle.jsx').default + const IconMdiCheckboxMultipleMarked: typeof import('~icons/mdi/checkbox-multiple-marked.jsx').default const IconMdiClock: typeof import('~icons/mdi/clock.jsx').default const IconMdiClockOutline: typeof import('~icons/mdi/clock-outline.jsx').default const IconMdiClose: typeof import('~icons/mdi/close.jsx').default diff --git a/src/components/OGPoll.tsx b/src/components/OGPoll.tsx index ef15dbc..5438839 100644 --- a/src/components/OGPoll.tsx +++ b/src/components/OGPoll.tsx @@ -45,8 +45,14 @@ export function RawOGC({ {/* Multiplicity */} - - {multiple || !privateProviderHandle ? 'Select multiple options' : 'Select one option'} + + {multiple || !privateProviderHandle ? () : ()} + {multiple || !privateProviderHandle ? "Select one or more options" : "Select one option"} + + + + + All votes are public @@ -55,7 +61,7 @@ export function RawOGC({ {options.map((optionText, index) => (
{optionText}
@@ -84,9 +90,11 @@ export function RawOGC({ ) : ( - - All votes are public - +
+ View all votes +
)} diff --git a/src/components/UniversalPostRenderer.tsx b/src/components/UniversalPostRenderer.tsx index 987588c..e3191fb 100644 --- a/src/components/UniversalPostRenderer.tsx +++ b/src/components/UniversalPostRenderer.tsx @@ -1268,6 +1268,7 @@ import { } from "~/routes/profile.$did"; import type { LightboxProps } from "~/routes/profile.$did/post.$rkey.image.$i"; import { useFastLike } from "~/utils/likeMutationQueue"; + // import type { OutputSchema } from "@atproto/api/dist/client/types/app/bsky/feed/getFeed"; // import type { // ViewRecord, @@ -2260,7 +2261,11 @@ function PollEmbed({ did, rkey }: { did: string; rkey: string }) { - const poll = pollRecord?.value as { + // todo: hardcoded to multiple for all public polls + const poll = { + ...(pollRecord?.value ?? {}), + multiple: true, + } as { a: string; b: string; c?: string; @@ -2413,137 +2418,140 @@ function PollEmbed({ did, rkey }: { did: string; rkey: string }) { }; return ( -
- {/* Header */} -
- {/* Type Pill */} -
- - Public Poll -
+ <> +
+ {/* Header */} +
+ {/* Type Pill */} +
+ + Public Poll +
- {/* Multiplicity */} - - {poll.multiple ? "Select multiple options" : "Select one option"} - + {/* Multiplicity */} + + {poll.multiple ? () : ()} + {poll.multiple ? "Select one or more options" : "Select one option"} + - {/* Total Votes */} - - {totalVotes} vote{totalVotes !== 1 ? "s" : ""} - -
+
- {/* Options List with Results */} -
- {options.map((optionText, index) => { - const optionKey = ["a", "b", "c", "d"][index]; - - // Check if user has voted for this option - const userVotesForOption = (() => { - switch (optionKey) { - case "a": - return userVotesA; - case "b": - return userVotesB; - case "c": - return userVotesC; - case "d": - return userVotesD; - default: - return []; - } - })(); - - const rowData = voteData.find((v) => v.option === optionKey); - const hasVotedForOption = - userVotesForOption && userVotesForOption.length > 0; - const voteCount = - voteData.find((v) => v.option === optionKey)?.count ?? 0; - const votePercentage = - totalVotes > 0 ? (voteCount / totalVotes) * 100 : 0; - - // Extract just the DIDs we want to show (top 2) - const topVoters = rowData?.voters - .filter(v => !!v.did) - .slice(0, 2) || []; - - return ( -
!isExpired && handleVote(optionKey)} - > - {/* Vote percentage bar - always show */} + {/* Options List with Results */} +
+ {options.map((optionText, index) => { + const optionKey = ["a", "b", "c", "d"][index]; + + // Check if user has voted for this option + const userVotesForOption = (() => { + switch (optionKey) { + case "a": + return userVotesA; + case "b": + return userVotesB; + case "c": + return userVotesC; + case "d": + return userVotesD; + default: + return []; + } + })(); + + const rowData = voteData.find((v) => v.option === optionKey); + const hasVotedForOption = + userVotesForOption && userVotesForOption.length > 0; + const voteCount = + voteData.find((v) => v.option === optionKey)?.count ?? 0; + const votePercentage = + totalVotes > 0 ? (voteCount / totalVotes) * 100 : 0; + + // Extract just the DIDs we want to show (top 2) + const topVoters = rowData?.voters + .filter(v => !!v.did) + .slice(0, 5) || []; + + return (
- - {/* Option text */} - - {optionText} - {hasVotedForOption && ( - - {poll.multiple ? "✓" : "✓ (click to remove)"} - - )} - + key={index} + className={`group relative h-12 items-center justify-between rounded-lg border px-4 flex overflow-hidden ${!isExpired + ? hasVotedForOption + ? "bg-gray-100 dark:bg-gray-950 border-gray-200 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-gray-900 cursor-pointer outline-2 outline-gray-500 dark:outline-gray-400" + : "bg-gray-100 dark:bg-gray-950 border-gray-200 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-gray-900 cursor-pointer" + : "bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700" + }`} + onClick={(e) => { + e.stopPropagation(); + if (!isExpired) { + handleVote(optionKey) + } + }} + > + {/* Vote percentage bar - always show */} +
- {/* Avatar circles and vote count */} -
- {/* Avatar circles - semi overlapping */} + {/* Option text */} + + {optionText} + {hasVotedForOption && ( + + {poll.multiple ? "✓" : "✓ (click to remove)"} + + )} + - {topVoters.length > 0 && ( -
- {topVoters.map((voter, idx) => ( -
- {/* The Component handles the async fetch! */} - -
- ))} -
- )} + {/* Avatar circles and vote count */} +
+ {/* Avatar circles - semi overlapping */} + + {topVoters.length > 0 && ( +
+ {topVoters.map((voter, idx) => ( +
+ {/* The Component handles the async fetch! */} + +
+ ))} +
+ )} - {/* Vote count */} - - {votePercentage.toFixed(0)}% - + {/* Vote count */} + + {votePercentage.toFixed(0)}% + +
-
- ); - })} -
+ ); + })} +
- {/* Footer */} -
- {/* Expiry */} -
- - {/* Expires {formattedDate} */} - {formattedDate ? ( - !isExpired ? ( - Expires {formattedDate} + {/* Footer */} +
+ {/* Expiry */} +
+ + {/* Expires {formattedDate} */} + {formattedDate ? ( + !isExpired ? ( + Expires {formattedDate} + ) : ( + Expired at {formattedDate} + ) ) : ( - Expired at {formattedDate} - ) - ) : ( - Never expires - )} -
+ Never expires + )} +
- {/* Status */} -
+ {/* Status */} + {/*
{isExpired ? ( Poll ended @@ -2553,9 +2561,27 @@ function PollEmbed({ did, rkey }: { did: string; rkey: string }) { All votes are public )} +
*/} +
-
+ {/*
+ +
*/} + ); }