(ns auto-ap.views.components.vendor-dialog (:require [re-frame.core :as re-frame] [auto-ap.views.utils :refer [dispatch-event horizontal-field bind-field]] [auto-ap.views.components.modal :refer [action-modal]] [auto-ap.views.components.address :refer [address-field]] [auto-ap.views.components.typeahead :refer [typeahead]] [clj-fuzzy.metrics :refer [jaccard jaro-winkler]] [clojure.spec.alpha :as s] [clojure.string :as str] [auto-ap.entities.vendors :as entity] [auto-ap.entities.contact :as contact] [auto-ap.subs :as subs])) (defn ngrams [text len] (mapv #(.toLowerCase (str/join "" %)) (partition len 1 text))) (defn partial-matches-vendor? [vendor vendors] (when (> (count (:name vendor)) 5) (let [text (.toLowerCase (:name vendor))] (->> vendors (filter #(not= (:id %) (:id vendor))) (map :name) (mapcat (fn [v] (mapv (fn [n] [v (jaro-winkler text n ) n text]) (ngrams v (count text))))) #_(sort-by second) (filter #(> (second %) 0.9)) #_(map (fn [x] (doto x println))) (map first) first)))) (defn vendor-dialog [{:keys [vendor save-event change-event id] {:keys [name]} :vendor}] (let [clients-by-id @(re-frame/subscribe [::subs/clients-by-id]) all-vendors @(re-frame/subscribe [::subs/vendors]) chooseable-expense-accounts @(re-frame/subscribe [::subs/chooseable-expense-accounts])] [action-modal {:id id :title [:span (if (:id vendor) (str "Edit " (or name "")) (str "Add " (or name ""))) (when (:error vendor) [:span.icon.has-text-danger [:i.fa.fa-exclamation-triangle]])] :warning (when-let [vendor (partial-matches-vendor? vendor all-vendors)] (str "Are you sure you don't mean " vendor "?")) :action-text "Save" :save-event save-event :can-submit? (s/valid? ::entity/vendor vendor)} [horizontal-field [:label.label "Name"] [:div.control [bind-field [:input.input {:type "text" :auto-focus true :field :name :spec ::entity/name :event change-event :subscription vendor}]]]] [horizontal-field [:label.label "Print Checks As"] [:div.control [bind-field [:input.input {:type "text" :field :print-as :spec ::entity/print-as :event change-event :subscription vendor}]]]] [horizontal-field [:label.label "Hidden"] [:div.control [bind-field [:input {:type "checkbox" :field :hidden :spec ::entity/hidden :event change-event :subscription vendor}]]]] [:h2.subtitle "Expense Accounts"] [horizontal-field [:label.label "Default"] [bind-field [typeahead {:matches (map (fn [x] [(:id x) (str (:numeric-code x) " - " (:name x))]) chooseable-expense-accounts) :type "typeahead" :field [:default-account-id] :event change-event :subscription vendor}]]] [:h2.subtitle "Address"] [address-field {:field [:address] :event change-event :subscription vendor}] [:h2.subtitle "Contact"] [horizontal-field [:label.label "Primary"] [:div.control.has-icons-left [bind-field [:input.input.is-expanded {:type "text" :field [:primary-contact :name] :spec ::contact/name :event change-event :subscription vendor}]] [:span.icon.is-small.is-left [:i.fa.fa-user]]] [:div.control.has-icons-left [:span.icon.is-small.is-left [:i.fa.fa-envelope]] [bind-field [:input.input {:type "email" :field [:primary-contact :email] :spec ::contact/email :event change-event :subscription vendor}]]] [:div.control.has-icons-left [bind-field [:input.input {:type "phone" :field [:primary-contact :phone] :spec ::contact/phone :event change-event :subscription vendor}]] [:span.icon.is-small.is-left [:i.fa.fa-phone]]]] [horizontal-field [:label.label "Secondary"] [:div.control.has-icons-left [bind-field [:input.input.is-expanded {:type "text" :field [:secondary-contact :name] :spec ::contact/name :event change-event :subscription vendor}]] [:span.icon.is-small.is-left [:i.fa.fa-user]]] [:div.control.has-icons-left [:span.icon.is-small.is-left [:i.fa.fa-envelope]] [bind-field [:input.input {:type "email" :field [:secondary-contact :email] :spec ::contact/email :event change-event :subscription vendor}]]] [:div.control.has-icons-left [bind-field [:input.input {:type "phone" :field [:secondary-contact :phone] :spec ::contact/phone :event change-event :subscription vendor}]] [:span.icon.is-small.is-left [:i.fa.fa-phone]]]] [horizontal-field [:label.label "Invoice Reminders"] [:div.control [:label.radio [bind-field [:input {:type "radio" :name "schedule" :value "Weekly" :field :invoice-reminder-schedule :spec ::entity/invoice-reminder-schedule :event change-event :subscription vendor}]] " Send weekly"] [:label.radio [bind-field [:input {:type "radio" :name "schedule" :value "Never" :field :invoice-reminder-schedule :spec ::entity/invoice-reminder-schedule :event change-event :subscription vendor}]] " Never"]]] (when (:saving? vendor) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])]))