import React, { FormEventHandler, useState } from 'react'; import FocusTrap from 'focus-trap-react'; import { Box, Button, Dialog, Header, Icon, IconButton, Icons, Input, Overlay, OverlayBackdrop, OverlayCenter, Spinner, Text, color, config, } from 'folds'; import { Room } from 'matrix-js-sdk'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { stopPropagation } from '../../utils/keyboard'; import { useModalStyle } from '../../hooks/useModalStyle'; interface PollCreatorProps { roomId: string; room: Room; onClose: () => void; } export function PollCreator({ roomId, onClose }: PollCreatorProps) { const mx = useMatrixClient(); const modalStyle = useModalStyle(440); const [question, setQuestion] = useState(''); const [options, setOptions] = useState(['', '']); const [isMultiple, setIsMultiple] = useState(false); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); const handleOptionChange = (index: number, value: string) => { setOptions((prev) => { const next = [...prev]; next[index] = value; return next; }); }; const handleAddOption = () => { if (options.length >= 10) return; setOptions((prev) => [...prev, '']); }; const handleRemoveOption = (index: number) => { if (options.length <= 2) return; setOptions((prev) => prev.filter((_, i) => i !== index)); }; const handleSubmit: FormEventHandler = async (e) => { e.preventDefault(); if (submitting) return; const trimmedQuestion = question.trim(); if (!trimmedQuestion) { setError('Please enter a question.'); return; } const filledOptions = options.map((o) => o.trim()).filter((o) => o.length > 0); if (filledOptions.length < 2) { setError('Please provide at least 2 answer options.'); return; } setError(null); setSubmitting(true); try { await mx.sendEvent(roomId, 'm.poll.start' as any, { 'm.poll': { question: { 'm.text': trimmedQuestion }, answers: filledOptions.map((o, i) => ({ 'm.id': `${i}`, 'm.text': o })), max_selections: isMultiple ? filledOptions.length : 1, kind: 'm.poll.undisclosed', }, body: trimmedQuestion, msgtype: 'm.text', }); onClose(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to send poll.'); setSubmitting(false); } }; return ( }> {/* Header */}
Create Poll
{/* Body */} {/* Question */} Question ) => setQuestion(e.target.value)} // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus /> {/* Options */} Options {options.map((opt, index) => ( // eslint-disable-next-line react/no-array-index-key ) => handleOptionChange(index, e.target.value) } aria-label={`Option ${index + 1}`} /> handleRemoveOption(index)} disabled={options.length <= 2} aria-label={`Remove option ${index + 1}`} > ))} {options.length < 10 && ( )} {/* Selection type */} Selection Type {(['single', 'multiple'] as const).map((type) => { const active = type === 'multiple' ? isMultiple : !isMultiple; return ( ); })} {/* Error */} {error && ( {error} )} {/* Footer actions */}
); }