diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cdd1de3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +/resources/public/js/compiled/** +figwheel_server.log +pom.xml +*jar +/lib/ +/classes/ +/out/ +/target/ +.lein-deps-sum +.lein-repl-history +.lein-plugins/ +.repl +.nrepl-port diff --git a/README.md b/README.md new file mode 100644 index 0000000..a8c0133 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# simplecalculator + +FIXME: Write a one-line description of your library/project. + +## Overview + +FIXME: Write a paragraph about the library/project and highlight its goals. + +## Setup + +To get an interactive development environment run: + + lein figwheel + +and open your browser at [localhost:3449](http://localhost:3449/). +This will auto compile and send all changes to the browser without the +need to reload. After the compilation process is complete, you will +get a Browser Connected REPL. An easy way to try it is: + + (js/alert "Am I connected?") + +and you should see an alert in the browser window. + +To clean all compiled files: + + lein clean + +To create a production build run: + + lein cljsbuild once min + +And open your browser in `resources/public/index.html`. You will not +get live reloading, nor a REPL. + +## License + +Copyright © 2014 FIXME + +Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version. diff --git a/project.clj b/project.clj new file mode 100644 index 0000000..1b46a44 --- /dev/null +++ b/project.clj @@ -0,0 +1,79 @@ +(defproject simplecalculator "0.1.0-SNAPSHOT" + :description "FIXME: write this!" + :url "http://example.com/FIXME" + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + + :dependencies [[org.clojure/clojure "1.7.0"] + [org.clojure/clojurescript "1.7.170"] + [org.clojure/core.async "0.2.374"] + [reagent "0.5.1" + :exclusions [org.clojure/tools.reader]] + [reagent-forms "0.5.13"] + [reagent-utils "0.1.7"] + [secretary "1.2.3"] + [cljs-pikaday "0.1.2"] + [com.andrewmcveigh/cljs-time "0.3.14"] + [venantius/accountant "0.1.6" + :exclusions [org.clojure/tools.reader]] + + ] + + :plugins [[lein-cljsbuild "1.1.1"] + [lein-figwheel "0.5.0-1"]] + + :source-paths ["src"] + + :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"] + + :cljsbuild {:builds + [{:id "dev" + :source-paths ["src"] + + :figwheel {:on-jsload "simplecalculator.core/on-js-reload"} + + :compiler {:main simplecalculator.core + :asset-path "js/compiled/out" + :output-to "resources/public/js/compiled/simplecalculator.js" + :output-dir "resources/public/js/compiled/out" + :source-map-timestamp true}} + ;; This next build is an compressed minified build for + ;; production. You can build this with: + ;; lein cljsbuild once min + {:id "min" + :source-paths ["src"] + :compiler {:output-to "resources/public/js/compiled/simplecalculator.js" + :main simplecalculator.core + :optimizations :advanced + :pretty-print false}}]} + + :figwheel {;; :http-server-root "public" ;; default and assumes "resources" + ;; :server-port 3449 ;; default + ;; :server-ip "127.0.0.1" + + :css-dirs ["resources/public/css"] ;; watch and update CSS + + ;; Start an nREPL server into the running figwheel process + ;; :nrepl-port 7888 + + ;; Server Ring Handler (optional) + ;; if you want to embed a ring handler into the figwheel http-kit + ;; server, this is for simple ring servers, if this + ;; doesn't work for you just run your own server :) + ;; :ring-handler hello_world.server/handler + + ;; To be able to open files in your editor from the heads up display + ;; you will need to put a script on your path. + ;; that script will have to take a file path and a line number + ;; ie. in ~/bin/myfile-opener + ;; #! /bin/sh + ;; emacsclient -n +$2 $1 + ;; + ;; :open-file-command "myfile-opener" + + ;; if you want to disable the REPL + ;; :repl false + + ;; to configure a different figwheel logfile path + ;; :server-logfile "tmp/logs/figwheel-logfile.log" + }) diff --git a/resources/public/css/style.css b/resources/public/css/style.css new file mode 100644 index 0000000..26163d2 --- /dev/null +++ b/resources/public/css/style.css @@ -0,0 +1,2 @@ +/* some style */ + diff --git a/resources/public/index.html b/resources/public/index.html new file mode 100644 index 0000000..d53220c --- /dev/null +++ b/resources/public/index.html @@ -0,0 +1,15 @@ + + + + + + + + +

dfgh

+
+
+ + + + diff --git a/src/simplecalculator/core.cljs b/src/simplecalculator/core.cljs new file mode 100644 index 0000000..d344e08 --- /dev/null +++ b/src/simplecalculator/core.cljs @@ -0,0 +1,237 @@ +(ns simplecalculator.core + (:require [reagent.core :as r :refer [atom]] + [reagent.session :as session] + [secretary.core :as secretary :include-macros true] + [accountant.core :as accountant] + + )) + +(enable-console-print!) + +;;pension age calculator +(defonce pension-age (r/atom {:dob nil :pensiondate 0 :age 0})) + +(def today (js/Date.)) + + +(defn- before [date days] +;; "Return a new js/Date which is the given number of days before the given date" + (js/Date. (.getFullYear date) (.getMonth date) (- (.getDate date) days))) + +(defn date? [x] + (= (type x) js/Date)) + + +(defn days-between [x y] +;; "Return the number of days between the two js/Date instances" + (when (every? date? [x y]) + (let [ms-per-day (* 1000 60 60 25) + x-ms (.getTime x) + y-ms (.getTime y)] + (.round js/Math (.abs js/Math (/ (- x-ms y-ms) ms-per-day))))) + ) + + +(defn get-date! [date] + (if (date? date) + (.toLocaleDateString date "en" "%d-%b-%Y") + "unselected")) + +(defn calc-pensionage [] + (let [{:keys [dob pensiondate age]} @pension-age ] + (if(and (<(js/Date. "1950-04-06") dob) (> (js/Date. "1953-04-05") dob)) + ;;age to get state pension is 63 + ;;add 63 to dob + ((swap! pension-age assoc :age 63) + (swap! pension-age assoc :pensiondate (js/Date. (+ (.getFullYear dob) 63) (.getMonth dob) (.getDate dob))))) + (if(and (<(js/Date. "1953-04-06") dob ) (>(js/Date. "1953-12-05") dob)) + ;;age to get state pension is 65 + ;;add 65 to dob + ((swap! pension-age assoc :age 65) + (swap! pension-age assoc :pensiondate (js/Date. (+ (.getFullYear dob) 65) (.getMonth dob) (.getDate dob))))) + (if(and (<(js/Date. "1953-12-06") dob ) (>(js/Date. "1960-04-05") dob)) + ;;age to get state pension is 66 + ;;add 66 to dob + ((swap! pension-age assoc :age 66) + (swap! pension-age assoc :pensiondate (js/Date. (+ (.getFullYear dob) 66) (.getMonth dob) (.getDate dob)))) + ) + (if(and (<(js/Date. "1960-04-06") dob ) (>(js/Date. "1977-04-05") dob)) + ;;age to get state pension is 67 + ;;add 67 to dob + ((swap! pension-age assoc :age 67) + (swap! pension-age assoc :pensiondate (js/Date. (+ (.getFullYear dob) 67) (.getMonth dob) (.getDate dob)))) + ) + (if(<(js/Date. "1977-04-06") dob ) + ;;age to get state pension is 68 + ;;add 68 to dob + ((swap! pension-age assoc :age 68) + (swap! pension-age assoc :pensiondate (js/Date. (+ (.getFullYear dob) 68) (.getMonth dob) (.getDate dob)))) + ) + ) +) + + +;;calculator component +(defonce result-data (r/atom {:number 0 :result nil :operator nil})) + +(defn calc-result [] + (let [{:keys [number result operator]} @result-data] + (if (= operator "+") (swap! result-data assoc :result (+ (* 1 result) (* 1 number)))) + (if (= operator "-") (swap! result-data assoc :result (- result number ))) + (if (= operator "*") (swap! result-data assoc :result (* result number ))) + (if (= operator "/") (swap! result-data assoc :result (/ result number ))) + (swap! result-data assoc :number 0) + )) + +;;BMI Calculator components +(defonce bmi-data (r/atom {:height 180 :weight 80})) + +(defn calc-bmi [] + (let [{:keys [height weight bmi] :as data} @bmi-data + h (/ height 100)] + (if (nil? bmi) + (assoc data :bmi (/ weight (* h h))) + (assoc data :weight (* bmi h h))))) + +(defn slider [param value min max] + [:input {:type "range" :value value :min min :max max + :style {:width "100%"} + :on-change (fn [e] + (swap! bmi-data assoc param (.-target.value e)) + (when (not= param :bmi) + (swap! bmi-data assoc :bmi nil)))}]) + +;; ------------------------- +;; Views + +;;navigation view +;;navigation-view will be shared by three main components +(defn navigation-view [] + [:div + [:a {:href "/"} "Maths "] + [:a {:href "/BMI"} " BMI"] + [:a {:href "/Pensionage"} " PensionAge"] +] +) + + +(defn home-page [] + (let [{:keys [number result operator]} @result-data] + [:div [:h3 "Welcome to calculators"] + [navigation-view] + [:p] + [:input {:type "number" + :value number + :on-change (fn [e] + (swap! result-data assoc :number (.-target.value e)) + ) + }] + [:div + [:input {:type "button" + :value "+" + :on-click (fn [e] + (swap! result-data assoc :operator (.-target.value e)) + (if(nil? result) + ((swap! result-data assoc :result number) + (swap! result-data assoc :number 0))) + ) + }] + [:input {:type "button" + :value "-" + :on-click (fn [e] + (swap! result-data assoc :operator (.-target.value e)) + (if(nil? result) + ((swap! result-data assoc :result number) + (swap! result-data assoc :number 0))) + ) + }] + [:input {:type "button" + :value "/" + :on-click (fn [e] + (swap! result-data assoc :operator (.-target.value e)) + (if(nil? result) + ((swap! result-data assoc :result number) + (swap! result-data assoc :number 0))) + ) + }] + [:input {:type "button" + :value "*" + :on-click (fn [e] + (swap! result-data assoc :operator (.-target.value e)) + (if(nil? result) + ((swap! result-data assoc :result number) + (swap! result-data assoc :number 0))) + ) + }] + [:input {:type "button" + :value "=" + :on-click calc-result + }] + ] + [:p result] + + ])) + +(defn bmi-page [] + (let [{:keys [weight height bmi]} (calc-bmi) + [color diagnose] (cond + (< bmi 18.5) ["orange" "underweight"] + (< bmi 25) ["inherit" "normal"] + (< bmi 30) ["orange" "overweight"] + :else ["red" "obese"])] + [:div + [navigation-view] + [:h4 "BMI calculator"] + [:div + "Height: " (int height) "cm" + [slider :height height 100 220]] + [:div + "Weight: " (int weight) "kg" + [slider :weight weight 30 150]] + [:div + "BMI: " (int bmi) " " + [:span {:style {:color color}} diagnose] + [slider :bmi bmi 10 50]]])) + +(defn pension-page [] + (let [{:keys [dob pensiondate age]} @pension-age] + [:div + [navigation-view] + [:div [:h2 "State Pension Age Calculator"] + [:h4 "Enter Date Of Birth"] + [:input {:type "date" + :on-change (fn [e] (swap! pension-age assoc :dob (js/Date. (.-target.value e)))) + }] + [:input {:type "button" + :value "Pension Age" + :on-click calc-pensionage + }] + [:p "You will reach pension age at " age " as from " (get-date! pensiondate) ] + ] + ] + )) + +(defn current-page [] + [:div [(session/get :current-page)]]) + +;; ------------------------- +;; Routes + +(secretary/defroute "/" [] + (session/put! :current-page #'home-page)) + +(secretary/defroute "/BMI" [] + (session/put! :current-page #'bmi-page)) + +(secretary/defroute "/Pensionage" [] + (session/put! :current-page #'pension-page)) +;; ------------------------- +;; Initialize app + +(defn mount-root [] + (r/render [current-page] (.getElementById js/document "app"))) + + + (accountant/configure-navigation!) + (accountant/dispatch-current!) + (mount-root)