/- *polls /+ sr=sortug, kaji, lib=boke |% ++ css ^~ %- trip ''' .new-poll{ border: 1px solid black; width: 80%; margin: auto; margin-bottom: 1rem; padding: 1rem; #poll-title{ font-size: 1.5rem; padding: 0.3rem; margin-bottom: 0.5rem; text-align: center; } & input[type=text]{ display: block; line-height: 1.5rem; width: 80%; margin: 0.3rem auto; } #final-row{ border-top: 1px solid black; } #bet-input{ width: 30%; display: inline-block; margin-left: 1ch; } } @media (max-width: 800px){ #final-row{ display: block; } } ''' ++ script ^~ %- trip ''' function newOpts(){ const button = document.getElementById("add-opt-button"); const container = document.getElementById("options"); button.addEventListener("click", (e) => { console.log(e, "clck") e.preventDefault(); e.stopPropagation(); const currentOpts = container.querySelectorAll(".opt"); const index = currentOpts.length; const input = document.createElement("input"); input.classList.add("opt"); input.type = "text"; input.name = `poll-opt-${index}`; input.placeholder = "New Option"; input.autocomplete = "off"; container.appendChild(input); }) } setTimeout(newOpts, 500); ''' ++ form |= =bowl:gall ^- manx ;form ;div.new-poll ;style:"{css}" ;input#poll-title(type "text", name "poll-title", placeholder "Poll Question"); ;div#options ;input.opt(type "text", name "poll-opt-0", placeholder "First Option", autocomplete "off"); ;input.opt(type "text", name "poll-opt-1", placeholder "Second Option", autocomplete "off"); == ;div.f1 ;div ;label: Multiple Choice ;input(type "checkbox", name "poll-multiple"); == ;button#add-opt-button(type "button"):"Add" == ;div#final-row.f1 ;div ;label: Require betting ;input#bet-input(type "text", name "poll-min-bet"); == ;div ;label: Expires ;input(type "datetime-local", name "poll-expiry"); == == ;script:"{script}" == == +$ opt $: text=@t votes=(set @p) == ++ show |= [=poll =bowl:gall] ^- manx =/ poll-type=tape ?: ?=(%exc -.votes.poll) "Single choice poll" "Multiple choice poll" =/ pid-string (enc:kaji [author.poll time.poll]) =/ total=@ud ?: ?=(%exc -.votes.poll) ~(wyt by p.votes.poll) %- ~(rep by p.votes.poll) |= [it=[@ud m=(map @p (set @ud))] acc=@ud] (add acc ~(wyt by m.it)) |^ ?: (gth now.bowl expiry.poll) expired-poll fresh-poll ++ fresh-poll ^- manx =/ expiry-string (post-date-ago:lib now.bowl expiry.poll %yau) ;div.poll ;div.top-row ;h6:"Open Poll" ;h3.hs:"{(trip text.poll)}" == ;div.options ;* %+ mapi:sr options.poll fresh-opt == ;div.bottom-row.f1 ;div.poll-type:"{poll-type}" ;div.expiry:"Expires in {expiry-string}" == == ++ fresh-opt |= [i=@ud text=@t] =/ payload (enc:kaji [author.poll time.poll i]) =/ stats (opt-stats i) =/ pct (scow %ud pct.stats) =/ style "width: {pct}%;" =/ classes ?: ?=(%exc -.votes.poll) =/ have-voted (~(get by p.votes.poll) src.bowl) ?~ have-voted "poll-option open" ?: .=(u.have-voted i) "poll-option voted" "poll-option not-voted" :: inc =/ opt-votes (~(get by p.votes.poll) i) ?~ opt-votes "poll-option open" =/ my-votes (~(get by u.opt-votes) src.bowl) ?~ my-votes "poll-option open" ?: (~(has in u.my-votes) i) "poll-option voted" "poll-option open" ;div =class classes =kaji "poke" =action "vote-poll" =name "option" =payload payload ;div.poll-option-color(style style); ;div.f1.inner =name "option-{(scow %ud i)}" =payload "vote" ;div.poll-option-name.hs:"{(trip text)}" ;div:"{pct}%" == == ++ expired-poll ^- manx =/ expiry-string (post-date-ago:lib expiry.poll now.bowl %yau) ;div.poll ;div.top-row ;h6:"Closed Poll" ;h3.hs:"{(trip text.poll)}" == ;div.options ;* %+ mapi:sr options.poll dead-opt == ;div.bottom-row ;div.poll-type:"{poll-type}" ;div.expiry:"Expired {expiry-string} ago" == == ++ dead-opt |= [i=@ud text=@t] ^- manx =/ stats (opt-stats i) =/ pct (scow %ud pct.stats) =/ style "width: {pct}%;" ;div.poll-option ;div.poll-option-color(style style); ;div.inner.f1 ;div.poll-option-name.hs:"{(trip text)}" ;div:"{pct}%" == == ++ opt-stats |= i=@ud ^- [count=@ud pct=@ud voters=(set @p)] =/ voters ?: ?=(%exc -.votes.poll) =/ all-votes ~(tap by p.votes.poll) %+ roll all-votes |= [[sip=@p vote=@ud] acc=(set @p)] ?. .=(vote i) acc %- ~(put in acc) sip :: =/ all-votes (~(get by p.votes.poll) i) ?~ all-votes ~ ~(key by u.all-votes) =/ voter-count ~(wyt in voters) =/ pct ?: .=(total 0) 0 (div (mul voter-count 100) total) [voter-count pct voters] -- --