summaryrefslogtreecommitdiff
path: root/desk/web/components/poll.hoon
diff options
context:
space:
mode:
Diffstat (limited to 'desk/web/components/poll.hoon')
-rw-r--r--desk/web/components/poll.hoon208
1 files changed, 208 insertions, 0 deletions
diff --git a/desk/web/components/poll.hoon b/desk/web/components/poll.hoon
new file mode 100644
index 0000000..3184ec0
--- /dev/null
+++ b/desk/web/components/poll.hoon
@@ -0,0 +1,208 @@
+/- *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]
+
+ --
+--