   {:name "ds.project-ordering.by-name"
    :created "ds.project-ordering.by-creation-date"})
 
-;; --- Lenses
-
-(def projects-by-id-ref
-  (as-> (l/key :projects-by-id) $
-    (l/derive $ s/state)))
+;; --- Refs
+
+(def projects-map-ref
+  (-> (l/key :projects-by-id)
+      (l/derive st/state)))
+
+(def dashboard-ref
+  (-> (l/in [:dashboard :projects])
+      (l/derive st/state)))
 
 (def project-ordering-ref
-  (as-> (l/in [:dashboard :project-order]) $
-    (l/derive $ s/state)))
+  (-> (l/key :project-order)
+      (l/derive dashboard-ref)))
 
 (def project-filtering-ref
-  (as-> (l/in [:dashboard :project-filter]) $
-    (l/derive $ s/state)))
-
-;; --- Sort Widget
-
-(defn sort-widget-render
-  []
-  (let [ordering (mx/react project-ordering-ref)
-        on-change #(rs/emit! (dp/set-project-ordering
-                              (keyword (.-value (.-target %)))))]
-    (html
-     [:div
-      [:span (tr "ds.project-ordering")]
-      [:select.input-select
-       {:on-change on-change
-        :value (name ordering)}
-       (for [option (keys +ordering-options+)
-             :let [option-id (get +ordering-options+ option)
-                   option-value (name option)
-                   option-text (tr option-id)]]
-         [:option
-          {:key option-id
-           :value option-value}
-          option-text])]])))
-
-(def ^:private sort-widget
-  (mx/component
-   {:render sort-widget-render
-    :name "sort-widget-render"
-    :mixins [mx/reactive mx/static]}))
-
-;; --- Filtering Widget
-
-(defn search-widget-render
-  []
-  (letfn [(on-term-change [event]
-            (-> (dom/get-target event)
-                (dom/get-value)
-                (dp/set-project-filtering)
-                (rs/emit!)))
-          (on-clear [event]
-            (rs/emit! (dp/clear-project-filtering)))]
-    (html
-     [:form.dashboard-search
-      [:input.input-text
-       {:type "text"
-        :on-change on-term-change
-        :auto-focus true
-        :placeholder (tr "ds.project-search.placeholder")
-        :value (mx/react project-filtering-ref)}]
-      [:div.clear-search
-       {:on-click on-clear}
-       i/close]])))
-
-(def ^:private search-widget
-  (mx/component
-   {:render search-widget-render
-    :name "search-widget"
-    :mixins [mx/reactive mx/static]}))
-
-;; --- Sort & Search Menu
-
-(defn menu-render
-  []
-  (let [projects (mx/react projects-by-id-ref)
-        pcount (count projects)]
-    (html
-     [:section.dashboard-bar
-      [:div.dashboard-info
-       [:span.dashboard-projects (tr "ds.num-projects" (t/c pcount))]
-       (sort-widget)
-       (search-widget)]])))
-
-(def menu
-  (mx/component
-   {:render menu-render
-    :name "menu"
-    :mixins [mx/reactive mx/static]}))
+  (-> (l/in [:project-filter])
+      (l/derive dashboard-ref)))
+
+;; --- Helpers
+
+(defn sort-projects-by
+  [ordering projs]
+  (case ordering
+    :name (sort-by :name projs)
+    :created (reverse (sort-by :created-at projs))
+    projs))
+
+(defn contains-term?
+  [phrase term]
+  (let [term (name term)]
+    (str/includes? (str/lower phrase) (str/trim (str/lower term)))))
+
+(defn filter-projects-by
+  [term projs]
+  (if (str/blank? term)
+    projs
+    (filter #(contains-term? (:name %) term) projs)))
+
+;; --- Menu (Filter & Sort)
+
+(mx/defc menu
+  {:mixins [mx/static]}
+  [state projects]
+  (let [ordering (:order state :name)
+        filtering (:filter state "")
+        count (count projects)]
+    (letfn [(on-term-change [event]
+              (let [term (-> (dom/get-target event)
+                             (dom/get-value))]
+                (rs/emit! (dp/update-opts :filter term))))
+            (on-ordering-change [event]
+              (let [value (dom/event->value event)
+                    value (read-string value)]
+                (rs/emit! (dp/update-opts :order value))))
+            (on-clear [event]
+              (rs/emit! (dp/update-opts :filter "")))]
+      [:section.dashboard-bar
+       [:div.dashboard-info
+
+        ;; Counter
+        [:span.dashboard-images (tr "ds.num-projects" (t/c count))]
+
+        ;; Sorting
+        [:div
+         [:span (tr "ds.project-ordering")]
+         [:select.input-select
+          {:on-change on-ordering-change
+           :value (pr-str ordering)}
+          (for [[key value] (seq +ordering-options+)
+                :let [ovalue (pr-str key)
+                      olabel (tr value)]]
+            [:option {:key ovalue :value ovalue} olabel])]]
+        ;; Search
+        [:form.dashboard-search
+         [:input.input-text
+          {:key :images-search-box
+           :type "text"
+           :on-change on-term-change
+           :auto-focus true
+           :placeholder (tr "ds.project-search.placeholder")
+           :value (or filtering "")}]
+         [:div.clear-search {:on-click on-clear} i/close]]]])))
 
 ;; --- Grid Item
 
-(defn grid-item-render
-  [own project]
+(mx/defc  grid-item
+  {:mixins [mx/static]}
+  [project]
   (letfn [(on-navigate [event]
             (rs/emit! (dp/go-to (:id project))))
           (delete []

     [:a.close {:href "#"
                :on-click #(do (dom/prevent-default %)
                               (udl/close!))}
      i/close]])))

(def new-project-lightbox
  (mx/component
   {:render new-project-lightbox-render
    :name "new-project-lightbox"
    :mixins [(rum/local +project-defaults+)]}))

(defmethod lbx/render-lightbox :new-project
  [_]

;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>

(ns uxbox.main.ui.dashboard.projects
  (:require [lentes.core :as l]
            [cuerdas.core :as str]
            [uxbox.main.state :as st]
            [uxbox.main.data.projects :as dp]
            [uxbox.main.data.lightbox :as udl]
            [uxbox.main.ui.icons :as i]
            [uxbox.main.ui.dashboard.header :refer (header)]
            [uxbox.main.ui.lightbox :as lbx]
            [uxbox.main.ui.messages :as uum]
            [uxbox.util.i18n :as t :refer (tr)]
            [uxbox.util.router :as r]
            [uxbox.util.rstore :as rs]
            [uxbox.util.data :refer (read-string)]
            [uxbox.util.dom :as dom]
            [uxbox.util.mixins :as mx :include-macros true]
            [uxbox.util.datetime :as dt]))

;; --- Helpers & Constants
