diff options
-rw-r--r-- | src/frontend/tubo/components/navigation.cljs | 131 | ||||
-rw-r--r-- | src/frontend/tubo/views.cljs | 124 |
2 files changed, 136 insertions, 119 deletions
diff --git a/src/frontend/tubo/components/navigation.cljs b/src/frontend/tubo/components/navigation.cljs index 0b98ed2..c1767ce 100644 --- a/src/frontend/tubo/components/navigation.cljs +++ b/src/frontend/tubo/components/navigation.cljs @@ -1,7 +1,9 @@ (ns tubo.components.navigation (:require [reagent.core :as r] + [reitit.frontend.easy :as rfe] [re-frame.core :as rf] + [tubo.components.layout :as layout] [tubo.events :as events] [tubo.routes :as routes])) @@ -58,3 +60,132 @@ (.focus @!input)) :class (when (empty? @!query) "invisible")} [:i.fa-solid.fa-circle-xmark]]]])))) + +(defn services-dropdown [services service-id service-color] + [:div.relative.flex.flex-col.items-center-justify-center.text-white.px-2 + {:style {:background service-color}} + [:div.w-full.box-border.z-10.lg:z-0 + [:select.border-none.focus:ring-transparent.bg-blend-color-dodge.font-bold.font-nunito.w-full + {:on-change #(rf/dispatch [::events/change-service-kiosk (js/parseInt (.. % -target -value))]) + :value service-id + :style {:background "transparent"}} + (when services + (for [service services] + [:option.text-white.bg-neutral-900.border-none + {:value (:id service) :key (:id service)} + (-> service :info :name)]))]] + [:div.flex.items-center.justify-end.absolute.min-h-full.top-0.right-4.lg:right-0.z-0 + [:i.fa-solid.fa-caret-down]]]) + +(defn kiosk-active? + [{:keys [kiosk kiosk-id service-id default-service default-kiosk path]}] + (or (and (= kiosk-id kiosk)) + (and (= path "/kiosk") + (not kiosk-id) + (not= (js/parseInt service-id) + (:service-id default-service)) + (= default-kiosk kiosk)) + (and (or (= path "/") (= path "/kiosk")) + (not kiosk-id) + (= (:default-kiosk default-service) kiosk)))) + +(defn kiosks-menu + [{:keys [kiosks service-id] :as kiosk-args}] + [:ul.flex.items-center.px-4.text-white + (for [kiosk kiosks] + [:li.px-3 {:key kiosk} + [:a {:href (rfe/href ::routes/kiosk nil {:serviceId service-id + :kioskId kiosk}) + :class (when (kiosk-active? (assoc kiosk-args :kiosk kiosk)) + "font-bold")} + kiosk]])]) + +(defn mobile-nav-item [route icon label & {:keys [new-tab? active?]}] + [:li.px-5.py-2 + [:a.flex {:href route :target (when new-tab? "_blank")} + [:div.w-6.flex.justify-center.items-center.mr-4 + [:i.text-neutral-600.dark:text-neutral-300 {:class icon}]] + [:span {:class (when active? "font-bold")} label]]]) + +(defn mobile-nav + [show-mobile-nav? service-color services available-kiosks {:keys [service-id] :as kiosk-args}] + [:<> + [layout/focus-overlay #(rf/dispatch [::events/toggle-mobile-nav]) show-mobile-nav?] + [:div.fixed.overflow-x-hidden.min-h-screen.w-60.top-0.ease-in-out.delay-75.bg-white.dark:bg-neutral-900 + {:class (str "transition-[right] " (if show-mobile-nav? "right-0" "right-[-245px]"))} + [:div.flex.justify-center.py-8.items-center.text-white {:style {:background service-color}} + [layout/logo] + [:h3.text-3xl.font-bold.px-4.font-roboto "Tubo"]] + [services-dropdown services service-id service-color] + [:div.relative.py-4 + [:ul.flex.font-roboto.flex-col + (for [kiosk available-kiosks] + ^{:key kiosk} + [mobile-nav-item + (rfe/href ::routes/kiosk nil + {:serviceId service-id + :kioskId kiosk}) + "fa-solid fa-fire" kiosk + :active? (kiosk-active? (assoc kiosk-args :kiosk kiosk))])]] + [:div.relative.dark:border-neutral-800.border-gray-300.pt-4 + {:class "border-t-[1px]"} + [:ul.flex.flex-col.font-roboto + [mobile-nav-item (rfe/href ::routes/playlists) "fa-solid fa-bookmark" "Bookmarks"] + [mobile-nav-item (rfe/href ::routes/settings) "fa-solid fa-cog" "Settings"] + [mobile-nav-item "https://github.com/migalmoreno/tubo" + "fa-brands fa-github" "Source" :new-tab? true]]]]]) + +(defn navbar + [{{:keys [serviceId kioskId]} :query-params path :path}] + (let [service-id @(rf/subscribe [:service-id]) + service-color @(rf/subscribe [:service-color]) + services @(rf/subscribe [:services]) + {:keys [theme default-service]} @(rf/subscribe [:settings]) + id (js/parseInt (or serviceId service-id)) + show-mobile-nav? @(rf/subscribe [:show-mobile-nav]) + show-search-form? @(rf/subscribe [:show-search-form]) + {:keys [available-kiosks default-kiosk]} @(rf/subscribe [:kiosks])] + [:nav.sticky.flex.items-center.px-2.h-14.top-0.z-50.font-nunito + {:style {:background service-color}} + [:div.flex.flex-auto.items-center + [:div.ml-4 + [:a.font-bold + {:href (rfe/href ::routes/home)} + [layout/logo]]] + [search-form] + [:div {:class (when show-search-form? "hidden")} + [navigation-buttons service-color]] + [:div.flex.flex-auto.justify-end.lg:justify-between + {:class (when show-search-form? "hidden")} + [:div.hidden.lg:flex + [services-dropdown services service-id service-color] + [kiosks-menu + {:kiosks available-kiosks + :service-id service-id + :kiosk-id kioskId + :default-service default-service + :default-kiosk default-kiosk + :path path}]] + [:div.flex.items-center.text-white.justify-end + (when-not show-search-form? + [:button.mx-3 + {:on-click #(rf/dispatch [::events/toggle-search-form])} + [:i.fa-solid.fa-search]]) + [:a.mx-3.hidden.lg:block + {:href (rfe/href ::routes/settings)} + [:i.fa-solid.fa-cog]] + [:a.mx-3.hidden.lg:block + {:href (rfe/href ::routes/playlists)} + [:i.fa-solid.fa-bookmark]] + [:a.mx-3.hidden.lg:block + {:href "https://github.com/migalmoreno/tubo" :target "_blank"} + [:i.fa-brands.fa-github]] + [:button.mx-3.lg:hidden + {:on-click #(rf/dispatch [::events/toggle-mobile-nav])} + [:i.fa-solid.fa-bars]]] + [mobile-nav show-mobile-nav? service-color services available-kiosks + {:kiosk-id kioskId + :service-id service-id + :default-service default-service + :default-kiosk default-kiosk + :path path}]]]])) diff --git a/src/frontend/tubo/views.cljs b/src/frontend/tubo/views.cljs index a623237..0618b51 100644 --- a/src/frontend/tubo/views.cljs +++ b/src/frontend/tubo/views.cljs @@ -1,134 +1,20 @@ (ns tubo.views (:require - [reitit.frontend.easy :as rfe] [re-frame.core :as rf] - [reagent.core :as r] [tubo.components.audio-player :as player] - [tubo.components.layout :as layout] [tubo.components.navigation :as navigation] [tubo.components.play-queue :as queue] - [tubo.events :as events] - [tubo.routes :as routes])) - -(defonce services (rf/dispatch [::events/get-services])) -(defonce kiosks (rf/dispatch [::events/get-kiosks 0])) - -(defn services-dropdown [services service-id service-color] - [:div.relative.flex.flex-col.items-center-justify-center.text-white.px-2 - {:style {:background service-color}} - [:div.w-full.box-border.z-10.lg:z-0 - [:select.border-none.focus:ring-transparent.bg-blend-color-dodge.font-bold.font-nunito.w-full - {:on-change #(rf/dispatch [::events/change-service-kiosk (js/parseInt (.. % -target -value))]) - :value service-id - :style {:background "transparent"}} - (when services - (for [service services] - [:option.text-white.bg-neutral-900.border-none - {:value (:id service) :key (:id service)} - (-> service :info :name)]))]] - [:div.flex.items-center.justify-end.absolute.min-h-full.top-0.right-4.lg:right-0.z-0 - [:i.fa-solid.fa-caret-down]]]) - -(defn mobile-nav-item [route icon label & {:keys [new-tab?]}] - [:li.px-5.py-2 - [:a.flex {:href route :target (when new-tab? "_blank")} - [:div.w-6.flex.justify-center.items-center.mr-4 - [:i.text-neutral-600.dark:text-neutral-300 {:class icon}]] - [:span label]]]) - -(defn mobile-nav - [show-mobile-nav? service-id service-color services available-kiosks] - [:<> - [layout/focus-overlay #(rf/dispatch [::events/toggle-mobile-nav]) show-mobile-nav?] - [:div.fixed.overflow-x-hidden.min-h-screen.w-60.top-0.ease-in-out.delay-75.bg-white.dark:bg-neutral-900 - {:class (str "transition-[right] " (if show-mobile-nav? "right-0" "right-[-245px]"))} - [:div.flex.justify-center.py-8.items-center.text-white {:style {:background service-color}} - [layout/logo] - [:h3.text-3xl.font-bold.px-4.font-roboto "Tubo"]] - [services-dropdown services service-id service-color] - [:div.relative.py-4 - [:ul.flex.font-roboto.flex-col - (for [kiosk available-kiosks] - ^{:key kiosk} [mobile-nav-item - (rfe/href ::routes/kiosk nil - {:serviceId service-id - :kioskId kiosk}) - "fa-solid fa-fire" kiosk])]] - [:div.relative.dark:border-neutral-800.border-gray-300.pt-4 - {:class "border-t-[1px]"} - [:ul.flex.flex-col.font-roboto - [mobile-nav-item (rfe/href ::routes/bookmarks) "fa-solid fa-bookmark" "Bookmarks"] - [mobile-nav-item (rfe/href ::routes/settings) "fa-solid fa-cog" "Settings"] - [mobile-nav-item "https://github.com/migalmoreno/tubo" "fa-brands fa-github" "Source" :new-tab? true]]]]]) - -(defn navbar - [{{:keys [serviceId]} :query-params}] - (let [service-id @(rf/subscribe [:service-id]) - service-color @(rf/subscribe [:service-color]) - services @(rf/subscribe [:services]) - {:keys [current-theme]} @(rf/subscribe [:settings]) - id (js/parseInt (or serviceId service-id)) - show-mobile-nav? @(rf/subscribe [:show-mobile-nav]) - show-search-form? @(rf/subscribe [:show-search-form]) - {:keys [available-kiosks default-kiosk]} @(rf/subscribe [:kiosks])] - [:nav.sticky.flex.items-center.px-2.h-14.top-0.z-50.font-nunito - {:style {:background service-color}} - [:div.flex.flex-auto.items-center - [:div.ml-4 - [:a.font-bold - {:href (rfe/href ::routes/home)} - [layout/logo]]] - [navigation/search-form] - [:div {:class (when show-search-form? "hidden")} - [navigation/navigation-buttons service-color]] - [:div.flex.flex-auto.justify-end.lg:justify-between - {:class (when show-search-form? "hidden")} - [:div.hidden.lg:flex - [services-dropdown services service-id service-color] - [:ul.flex.items-center.px-4.text-white - (for [kiosk available-kiosks] - [:li.px-3 {:key kiosk} - [:a {:href (rfe/href ::routes/kiosk nil {:serviceId service-id - :kioskId kiosk})} - kiosk]])]] - [:div.flex.items-center.text-white.justify-end - (when-not show-search-form? - [:button.mx-3 - {:on-click (fn [] - (rf/dispatch [::events/toggle-search-form]))} - [:i.fa-solid.fa-search]]) - [:a.mx-3.hidden.lg:block - {:href (rfe/href ::routes/settings)} - [:i.fa-solid.fa-cog]] - [:a.mx-3.hidden.lg:block - {:href (rfe/href ::routes/bookmarks)} - [:i.fa-solid.fa-bookmark]] - [:button.mx-3.lg:hidden - {:on-click #(rf/dispatch [::events/toggle-mobile-nav])} - [:i.fa-solid.fa-bars]]] - [mobile-nav show-mobile-nav? service-id service-color services available-kiosks]]]])) - -(defn footer - [] - [:footer - [:div.bg-neutral-300.dark:bg-black.dark:text-gray-300.p-5.text-center.w-full - [:div.flex.flex-col.justify-center.items-center - [:div.flex.items-center.justify-center - [:div.items-center.font-nunito - [:a {:href "https://github.com/migalmoreno/tubo" :target "_blank"} - [:i.fa-brands.fa-github] - [:span.ml-2.font-bold "Source"]]]]]]]) + [tubo.events :as events])) (defn app [] - (let [current-match @(rf/subscribe [:current-match]) - {:keys [current-theme]} @(rf/subscribe [:settings])] - [:div {:class (when (= current-theme "dark") "dark")} + (let [current-match @(rf/subscribe [:current-match]) + {:keys [theme]} @(rf/subscribe [:settings])] + [:div {:class (when (= theme "dark") "dark")} [:div.min-h-screen.flex.flex-col.h-full.dark:text-white.dark:bg-neutral-900.relative - [navbar current-match] + [navigation/navbar current-match] [:div.flex.flex-col.flex-auto.justify-between.relative.font-nunito (when-let [view (-> current-match :data :view)] [view current-match]) - [footer] [queue/queue] [player/player]]]])) |