107 lines
4.2 KiB
Clojure
107 lines
4.2 KiB
Clojure
(ns auto-ap.views.pages.home
|
|
(:require [auto-ap.views.components.layouts :refer [side-bar-layout]]
|
|
[re-frame.core :as re-frame]
|
|
[auto-ap.subs :as subs]
|
|
[reagent.core :as r]))
|
|
|
|
|
|
(def pie-chart (r/adapt-react-class js/Recharts.PieChart))
|
|
(def pie (r/adapt-react-class js/Recharts.Pie))
|
|
(def bar-chart (r/adapt-react-class js/Recharts.BarChart))
|
|
(def x-axis (r/adapt-react-class js/Recharts.XAxis))
|
|
(def y-axis (r/adapt-react-class js/Recharts.YAxis))
|
|
(def bar (r/adapt-react-class js/Recharts.Bar))
|
|
(def legend (r/adapt-react-class js/Recharts.Legend))
|
|
(def cell (r/adapt-react-class js/Recharts.Cell))
|
|
(def tool-tip (r/adapt-react-class js/Recharts.Tooltip))
|
|
|
|
(def colors ["hsl(171, 100%, 41%)" "hsl(217, 71%, 53%)" "hsl(141, 71%, 48%)" "hsl(48, 100%, 67%)" "hsl(348, 100%, 61%)" "hsl(217, 71%, 53%)"])
|
|
(def light-colors ["hsl(171, 60%, 80%)" "hsl(217, 71%, 53%)" "hsl(141, 71%, 48%)" "hsl(48, 100%, 67%)" "hsl(348, 100%, 61%)" "hsl(217, 71%, 53%)"])
|
|
|
|
(defn make-pie-chart
|
|
[{:keys [width height data]}]
|
|
[pie-chart {:width width
|
|
:height height}
|
|
[pie {:fill "#82ca9d"
|
|
:data data
|
|
:dataKey "value"
|
|
:inner-radius 20}
|
|
(map (fn [x y]
|
|
^{:key y}
|
|
[cell {:key y :fill (colors y)}]) data (range))
|
|
]
|
|
[tool-tip]
|
|
[legend]])
|
|
|
|
(defn make-bar-chart [{:keys [width height data]}]
|
|
[bar-chart {:width width :height height :data data :fill "#FFFFFF"}
|
|
[tool-tip]
|
|
[bar {:dataKey "paid" :fill (get colors 0) :stackId "a" :name "Paid"}]
|
|
[bar {:dataKey "unpaid" :fill (get light-colors 0) :stackId "a" :name "Unpaid"}]
|
|
|
|
[x-axis {:dataKey "name"}]
|
|
[y-axis]
|
|
[legend]]
|
|
)
|
|
|
|
(re-frame/reg-event-db
|
|
::received
|
|
(fn [db [_ {:keys [expense-account-stats invoice-stats]}]]
|
|
(let [expense-account-stats (->> expense-account-stats
|
|
(map #(update % :total (fn [t] (js/parseFloat t))))
|
|
(sort-by :total)
|
|
(reverse)
|
|
(take 5))
|
|
top-5 (vec (take 5 expense-account-stats))
|
|
rest (drop 5 expense-account-stats)
|
|
other {:account {:id 0 :name "Other"} :total (reduce + 0 (map :total rest))}]
|
|
(cond-> db
|
|
(seq top-5)
|
|
(assoc ::top-expense-categories (conj top-5 other))
|
|
|
|
(seq invoice-stats)
|
|
(assoc ::invoice-stats invoice-stats)))))
|
|
|
|
(re-frame/reg-sub
|
|
::invoice-stats
|
|
(fn [db]
|
|
(println (::invoice-stats db))
|
|
(::invoice-stats db)))
|
|
|
|
(re-frame/reg-sub
|
|
::top-expense-categories
|
|
(fn [db]
|
|
(::top-expense-categories db)))
|
|
|
|
(re-frame/reg-event-fx
|
|
::mounted
|
|
(fn [{:keys [db]} _]
|
|
{:db (assoc db ::top-expense-categories nil)
|
|
:graphql {:token (-> db :user)
|
|
:query-obj {:venia/queries [[:expense_account_stats
|
|
{:client-id (:id @(re-frame/subscribe [::subs/client]))}
|
|
[[:account [:id :name]] :total]]
|
|
[:invoice_stats
|
|
{:client-id (:id @(re-frame/subscribe [::subs/client]))}
|
|
[:name :paid :unpaid]]]}
|
|
:on-success [::received]}}))
|
|
|
|
(defn home-content []
|
|
(let [client-id (-> @(re-frame/subscribe [::subs/client]) :id)]
|
|
^{:key client-id}
|
|
[side-bar-layout {:side-bar [:div]
|
|
:main [:div [:h1.title "Home"]
|
|
[:h1.title.is-4 "Top expense categories"]
|
|
(let [expense-categories @(re-frame/subscribe [::top-expense-categories])]
|
|
(make-pie-chart {:width 800 :height 500 :data (clj->js
|
|
(map (fn [x] {:name (:name (:account x)) :value (:total x)}) expense-categories))}))
|
|
[:h1.title.is-4 "Upcoming Bills"]
|
|
(make-bar-chart {:width 800 :height 500 :data (clj->js
|
|
@(re-frame/subscribe [::invoice-stats]))})]}]))
|
|
|
|
|
|
(defn home-page []
|
|
(let [client-id (-> @(re-frame/subscribe [::subs/client]) :id)]
|
|
(re-frame/dispatch [::mounted])
|
|
^{:key client-id} [home-content]))
|