Skip to content

Instantly share code, notes, and snippets.

@jraines
Created August 4, 2015 19:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jraines/e234223292c9e8588e2d to your computer and use it in GitHub Desktop.
Save jraines/e234223292c9e8588e2d to your computer and use it in GitHub Desktop.
Attempt to do a kinda sorta redux like app in ClojureScript
(ns ^:figwheel-always ramquiz.core
(:require [quiescent.core :as q]
[quiescent.dom :as d]))
(enable-console-print!)
(declare render-app)
;; the data
(defonce questions
[{:question "How old are you?"
:options [["Less Than 50" 0] ["Older Than 50" 2]]}
{:question "Do either of your parents have heart disease?"
:options [["Yes" 2] ["No" 0]]}
{:question "Do you smoke?"
:options [["Yes" 2] ["No" 0]]}
{:question "Do you eat red meat more than 5x/week?"
:options [["Yes" 2] ["No" 0]]}
{:question "Do you drink more than 3x/week?"
:options [["Yes" 2] ["No" 0]]}
])
;; define your app data so that it doesn't get over-written on reload
(defonce app-state (atom {:questions questions
:total 0}))
(defonce original-state @app-state)
;action creators
(defn selectedOption [option]
{:type "selectedOption"
:amount (second option)})
;state change functions
(defn incTotal [amount]
(partial (fn [a m]
(assoc m :total (+ a (:total m)))) amount))
(defn unshift-question [m]
(assoc m :questions (vec (rest (:questions m)))))
;handle order
(defn dispatch [action]
(println "dispatching")
(condp = (:type action)
"selectedOption" (do
(swap! app-state (incTotal (:amount action)))
(swap! app-state unshift-question))
"reset" (do
(reset! app-state original-state))
)
(render-app)
)
;components
(q/defcomponent Option
[o]
(let [answer (first o)
updateState (fn [] (dispatch (selectedOption o)))]
(d/div {}
(d/p {:onClick updateState} answer))))
(q/defcomponent Question
[q]
(d/div {}
(d/h1 {} (:question q))
(apply d/div {} (map Option (:options q)))))
(q/defcomponent Total
[t]
(let [c (condp >= t
3 "low"
6 "medium"
8 "high")]
(d/div {:className (str t " " c)} t)))
(q/defcomponent Quiz
[q state]
(let [data (:questions state)
total (:total state)
totalClass (condp >= total
3 "low"
6 "medium"
8 "high")
updateState (fn [] (dispatch {:type "reset"}))]
(d/div {:className "quiz"}
(Total total)
(d/div {:onClick updateState} "Reset")
(d/div {} (Question q)))))
(q/defcomponent EmptyView
[_]
(d/div {:className "quiz"}
(Total (:total @app-state))
(d/p {} "No more questions!")))
(defn render-app []
(let [q (first (:questions @app-state))
total (:total @app-state)]
(if (nil? q)
(q/render (EmptyView nil)
(.getElementById js/document "root"))
(q/render (Quiz q @app-state)
(.getElementById js/document "root")))))
(render-app)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment