import { Check } from 'lucide-react'; import type { ReactNode } from 'react'; import { fs } from '../shared/DialogShell'; import { Tooltip } from '../shared/Tooltip'; /** * The pieces a poll of the trip is drawn with, shared by the Collab tab and * the assistant chat's poll cards: an option with its bar, its check, its * voters and its share, a voter's face and a fact on the poll's head band. * An option is a button where it can be voted for and a plain row where it * only shows; a vote the assistant holds marks its option with a dashed * frame until it is decided. */ /** A voter as an option shows them: a name and the picture TREK serves, if any. */ interface PollVoterFace { key: string | number; name: string; src: string | null; } /** One voter's face; faces after the first overlap the one before. */ function VoterChip({ name, src, offset }: { name: string; src: string | null; offset: boolean }) { return ( {src ? ( {name} ) : ( (name || '?').charAt(0).toUpperCase() )} ); } /** The voters past the third, as a count on the end of the stack; their names on hover. */ function MoreVoters({ names }: { names: string[] }) { return ( name || '?').join(', ')}> +{names.length} ); } /** A fact about the poll on its head band, set like the type chip on a booking card. */ export function PollChip({ icon, tone = 'muted', children, }: { icon?: ReactNode; tone?: 'muted' | 'warning' | 'info'; children: ReactNode; }) { const color = tone === 'warning' ? 'text-warning' : tone === 'info' ? 'text-info' : 'text-content-muted'; return ( {icon} {children} ); } interface PollOptionRowProps { text: string; /** Its share of all votes, which the bar draws. */ pct: number; /** The signed-in user voted for it. */ mine: boolean; /** The poll ended and it has the most votes. */ winner: boolean; /** Shares and voters show once the user voted or the poll ended. */ showResults: boolean; voters: readonly PollVoterFace[]; /** A button to vote with, or a row that only shows. */ as?: 'button' | 'div'; /** A vote waiting for its decision: the frame is dashed, and says so to a screen reader. */ pending?: { label: string } | null; disabled?: boolean; onClick?: () => void; } /** One option of a poll, as the Collab tab draws it. */ export function PollOptionRow({ text, pct, mine, winner, showResults, voters, as = 'button', pending = null, disabled = false, onClick, }: PollOptionRowProps) { const frame = pending ? 'border-dashed border-accent' : mine ? 'border-accent' : 'border-edge-faint enabled:hover:border-edge'; const body = ( <> {/* The bar behind it: the user's choice in the accent, the winner in green. */}