206 lines
8.4 KiB
Clojure
206 lines
8.4 KiB
Clojure
(ns auto-ap.views
|
|
(:require-macros [cljs.core.async.macros :refer [go]])
|
|
(:require [re-frame.core :as re-frame]
|
|
[reagent.core :as reagent]
|
|
[auto-ap.subs :as subs]
|
|
[auto-ap.events :as events]
|
|
[cljs.reader :as edn]
|
|
[cljsjs.dropzone :as dz]
|
|
[auto-ap.routes :as routes]
|
|
[bidi.bidi :as bidi]
|
|
[cljs-http.client :as http]
|
|
[cljs.core.async :refer [<!]]))
|
|
|
|
(defn active-when= [active-page candidate]
|
|
(when (= active-page candidate) " active"))
|
|
|
|
(def dropzone
|
|
(with-meta
|
|
(fn []
|
|
[:form {:action "/pdf-upload"}
|
|
[:div.tile.notification
|
|
[:div.has-text-centered {:style {:padding "80px 0px" :width "100%"}}
|
|
[:span
|
|
[:span {:class "icon"}
|
|
[:i {:class "fa fa-cloud-download"}]]
|
|
"Drop any invoices you want to process here"]]]])
|
|
{:component-did-mount (fn [this]
|
|
(js/Dropzone. (reagent/dom-node this)
|
|
(clj->js {:init (fn []
|
|
(.on (js-this) "success" (fn [_ files]
|
|
(re-frame/dispatch [::events/received-invoices :pending (edn/read-string files)]))))
|
|
:paramName "file"
|
|
:url "/pdf-upload"
|
|
:previewsContainer "#dz-hidden"
|
|
:previewTemplate "<div class='dz-hidden-preview'></div>"})))}))
|
|
|
|
(defmulti active-page identity)
|
|
|
|
(defmethod active-page :index []
|
|
[:div {:class "inbox-messages"}
|
|
[:div.hero
|
|
[:div.hero-body
|
|
[:div.container
|
|
[:h1.title "Dashboard"]
|
|
[:h2.subtitle "To get started, "
|
|
[:a {:href (bidi/path-for routes/routes :import-invoices)} "Import some invoices"]]]]]])
|
|
|
|
(defmethod active-page :unpaid-invoices []
|
|
[(with-meta
|
|
(fn []
|
|
(let [invoices (re-frame/subscribe [::subs/unpaid-invoices])
|
|
status (re-frame/subscribe [::subs/status])]
|
|
[:div {:class "inbox-messages"}
|
|
[:h1.title "Unpaid invoices"]
|
|
(if (:loading @status)
|
|
[:div {:class "inbox-messages"}
|
|
[:h1.title
|
|
[:i.fa.fa-spin.fa-spinner]]]
|
|
[:table {:class "table", :style {:width "100%"}}
|
|
[:thead
|
|
[:tr
|
|
[:th "Customer"]
|
|
[:th "Invoice #"]
|
|
[:th "Date"]
|
|
[:th "Amount"]]]
|
|
[:tbody (for [{:keys [customer-identifier invoice-number date total id] :as i} @invoices]
|
|
^{:key (str customer-identifier "-" invoice-number "-" date "-" total "-" id)}
|
|
[:tr
|
|
[:td customer-identifier]
|
|
[:td invoice-number]
|
|
[:td date]
|
|
[:td total]])]])]))
|
|
{:component-will-mount #(re-frame/dispatch-sync [::events/view-unpaid-invoices]) })])
|
|
|
|
(defmethod active-page :paid-invoices []
|
|
[:div {:class "inbox-messages"}
|
|
[:h1.title "Paid invoices"]])
|
|
|
|
(defmethod active-page :invoices []
|
|
[(with-meta
|
|
(fn []
|
|
[:div {:class "inbox-messages"}
|
|
[:h1.title "All invoices"]])
|
|
{:component-did-mount (fn []
|
|
(go
|
|
(re-frame/dispatch [::events/received-invoices (:body (<! (http/get "/api/invoices")))])))})])
|
|
|
|
(defmethod active-page :import-invoices []
|
|
[(with-meta
|
|
(fn []
|
|
(let [invoices (re-frame/subscribe [::subs/pending-invoices])]
|
|
[:div {:class "inbox-messages"}
|
|
[:h1.title "Upload invoices"]
|
|
[dropzone]
|
|
|
|
[:div {:class "section"}]
|
|
[:div {:class "card found-invoices", :style {:display (if (seq @invoices) "block" "none")}}
|
|
[:div {:class "card-header"}
|
|
[:span {:class "card-header-title"} "Found Invoices"]]
|
|
[:div {:class "card-content"}
|
|
[:table {:class "table", :style {:width "100%"}}
|
|
[:thead
|
|
[:tr
|
|
[:th "Customer"]
|
|
[:th "Invoice #"]
|
|
[:th "Date"]
|
|
[:th "Amount"]]]
|
|
[:tbody (for [{:keys [customer-identifier invoice-number date total id] :as i} @invoices]
|
|
^{:key (str customer-identifier "-" invoice-number "-" date "-" total "-" id)}
|
|
[:tr
|
|
[:td customer-identifier]
|
|
[:td invoice-number]
|
|
[:td date]
|
|
[:td total]])]]]
|
|
[:div.card-footer
|
|
[:a.card-footer-item
|
|
{:on-click (fn [e]
|
|
(.preventDefault e)
|
|
(re-frame/dispatch [::events/approve-invoices]))}
|
|
"Approve all"]
|
|
[:a.card-footer-item
|
|
{:on-click (fn [e]
|
|
(.preventDefault e)
|
|
(re-frame/dispatch [::events/reject-invoices]))}
|
|
"Reject all"]
|
|
]]]))
|
|
{:component-will-mount (fn []
|
|
(go
|
|
(->> (<! (http/get "/api/invoices/pending"))
|
|
:body
|
|
(conj [::events/received-invoices :pending])
|
|
(re-frame/dispatch))))})])
|
|
|
|
(defn main-panel []
|
|
(let [name (re-frame/subscribe [::subs/name])
|
|
ap (re-frame/subscribe [::subs/active-page])]
|
|
[:div
|
|
[:nav {:class "navbar has-shadow"}
|
|
[:div {:class "container"}
|
|
[:div {:class "navbar-brand"}
|
|
[:a {:class "navbar-item", :href "../"}
|
|
[:h1 (str "Auto-ap - " @name)]]
|
|
[:div {:class "navbar-burger burger", :data-target "navMenu"}
|
|
[:span]
|
|
[:span]
|
|
[:span]]]
|
|
[:div {:id "navMenu", :class "navbar-menu"}
|
|
[:div {:class "navbar-end"}
|
|
[:div {:class "navbar-item has-dropdown is-active"}
|
|
[:a {:class "navbar-link login"} ]
|
|
[:div {:class "navbar-dropdown", :style {:display "none"}}
|
|
[:a {:class "navbar-item"} ]
|
|
[:a {:class "navbar-item"} ]
|
|
[:a {:class "navbar-item"} ]
|
|
[:hr {:class "navbar-divider"}]
|
|
[:div {:class "navbar-item"} ]]]]]]]
|
|
[:div {:class "columns", :id "mail-app"}
|
|
[:aside {:class "column is-narrow aside menu hero is-fullheight"}
|
|
[:div.main
|
|
[:p.menu-label "General"]
|
|
[:p.menu-item
|
|
[:a {:href (bidi/path-for routes/routes :index) , :class (str "item" (active-when= @ap :index))}
|
|
[:span {:class "icon"}
|
|
[:i {:class "fa fa-tachometer"}]]
|
|
[:span {:class "name"} "Dashboard"]]]
|
|
|
|
[:p.menu-label "Accounts Payable"]
|
|
[:ul.menu-list
|
|
[:li.menu-item
|
|
[:a {:href (bidi/path-for routes/routes :import-invoices) , :class (str "item" (active-when= @ap :import-invoices))}
|
|
[:span {:class "icon"}
|
|
[:i {:class "fa fa-star-o"}]]
|
|
|
|
[:span {:class "name"} "Upload Invoices"]]]
|
|
[:li.menu-item
|
|
[:a {:href (bidi/path-for routes/routes :unpaid-invoices), :class (str "item" (active-when= @ap :unpaid-invoices))}
|
|
[:span {:class "icon"}
|
|
[:i {:class "fa fa-envelope-o"}]]
|
|
[:span {:class "name"} "Unpaid Invoices"]]
|
|
]
|
|
[:li.menu-item
|
|
[:a {:href (bidi/path-for routes/routes :paid-invoices), :class (str "item" (active-when= @ap :paid-invoices))}
|
|
[:span {:class "icon"}
|
|
[:i {:class "fa fa-envelope-o"}]]
|
|
[:span {:class "name"} "Paid Invoices"]]
|
|
]
|
|
[:ul ]]]
|
|
|
|
[:div.left-nav
|
|
[:div {:class "compose has-text-centered"}
|
|
[:a {:class "button is-danger is-block is-bold"}
|
|
[:span {:class "compose"} "New Invoice"]]]]]
|
|
[:div {:class "column messages hero is-fullheight", :id "message-feed"}
|
|
[active-page @ap]]]
|
|
[:footer {:class "footer"}
|
|
[:div {:class "container"}
|
|
[:div {:class "content has-text-centered"}
|
|
[:p
|
|
[:strong "Auto-AP"]"by "
|
|
[:a {:href "https://github.com/"} "Integreat"]"."]
|
|
[:p
|
|
[:a {:class "icon", :href "https://github.com/dansup/bulma-templates"}
|
|
[:i {:class "fa fa-github"}]]]]]]
|
|
[:div#dz-hidden]]))
|
|
|