Group prices by hour with expandable quarter details and blue borders
Each hour shows as an open-by-default card with the average price and indented quarter-hour rows. Added @source directive to Tailwind v4 input so .clj files are scanned for utility classes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1,2 @@
|
||||
@import "tailwindcss";
|
||||
@source "../../src/**/*.clj";
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
|
||||
(def ^:private hour-fmt (DateTimeFormatter/ofPattern "HH:00"))
|
||||
|
||||
(defn- format-hour [time-dk]
|
||||
(let [ldt (cond
|
||||
(defn- ->ldt [time-dk]
|
||||
(cond
|
||||
(instance? LocalDateTime time-dk) time-dk
|
||||
(instance? java.sql.Timestamp time-dk)
|
||||
(.toLocalDateTime ^java.sql.Timestamp time-dk)
|
||||
:else (LocalDateTime/parse (str time-dk)))]
|
||||
(.format ldt hour-fmt)))
|
||||
:else (LocalDateTime/parse (str time-dk))))
|
||||
|
||||
(defn- format-hour [time-dk]
|
||||
(.format (->ldt time-dk) hour-fmt))
|
||||
|
||||
(defn- dkk-mwh->ore-kwh
|
||||
"Convert DKK/MWh to øre/kWh (divide by 10)."
|
||||
@@ -28,24 +30,43 @@
|
||||
(when price-dkk
|
||||
(/ (double price-dkk) 10.0)))
|
||||
|
||||
(defn- format-ore [price-dkk]
|
||||
(if-let [ore (dkk-mwh->ore-kwh price-dkk)]
|
||||
(format "%.1f" ore)
|
||||
"-"))
|
||||
|
||||
(defn- group-by-hour [prices]
|
||||
(->> prices
|
||||
(group-by #(.getHour (->ldt (:time_dk %))))
|
||||
(sort-by key)))
|
||||
|
||||
(defn- avg-ore [quarters]
|
||||
(let [vals (keep :price_dkk quarters)]
|
||||
(when (seq vals)
|
||||
(/ (reduce + 0.0 (map double vals)) (count vals) 10.0))))
|
||||
|
||||
(defn- hour-block [hour quarters]
|
||||
(let [sorted (sort-by #(.getMinute (->ldt (:time_dk %))) quarters)
|
||||
avg (avg-ore quarters)]
|
||||
[:details {:class "border-2 border-blue-400 rounded-lg mb-2" :open true}
|
||||
[:summary {:class "flex justify-between py-2 px-3 cursor-pointer hover:bg-gray-50
|
||||
font-medium text-gray-900"}
|
||||
[:span (format "%02d:00" hour)]
|
||||
[:span {:class "font-mono"}
|
||||
(if avg (format "%.1f" avg) "-")]]
|
||||
[:div {:class "border-t-2 border-blue-400 px-3 pb-2"}
|
||||
(for [q sorted]
|
||||
[:div {:class "flex justify-between py-1 ml-4 text-gray-500"}
|
||||
[:span (format "%02d:%02d" hour (.getMinute (->ldt (:time_dk q))))]
|
||||
[:span {:class "font-mono"} (format-ore (:price_dkk q))]])]]))
|
||||
|
||||
(defn- price-table [title prices]
|
||||
[:div {:class "mt-6"}
|
||||
[:h2 {:class "text-lg font-semibold text-gray-900"} title]
|
||||
[:h2 {:class "text-lg font-semibold text-gray-900 mb-2"} title]
|
||||
(if (seq prices)
|
||||
[:table {:class "mt-2 w-full text-sm"}
|
||||
[:thead
|
||||
[:tr {:class "border-b border-gray-200 text-left text-gray-500"}
|
||||
[:th {:class "py-2 pr-4"} "Time"]
|
||||
[:th {:class "py-2 text-right"} "øre/kWh"]]]
|
||||
[:tbody
|
||||
(for [p prices]
|
||||
[:tr {:class "border-b border-gray-100"}
|
||||
[:td {:class "py-2 pr-4 text-gray-700"}
|
||||
(format-hour (:time_dk p))]
|
||||
[:td {:class "py-2 text-right font-mono text-gray-900"}
|
||||
(if-let [ore (dkk-mwh->ore-kwh (:price_dkk p))]
|
||||
(format "%.1f" ore)
|
||||
"-")]])]]
|
||||
[:div
|
||||
(for [[hour quarters] (group-by-hour prices)]
|
||||
(hour-block hour quarters))]
|
||||
[:p {:class "mt-2 text-sm text-gray-400"} "Not available yet"])])
|
||||
|
||||
(defn- price-tables [query-fn]
|
||||
@@ -60,7 +81,7 @@
|
||||
[:h1 {:class "text-2xl font-bold text-gray-900"}
|
||||
"Electricity Prices"]
|
||||
[:p {:class "mt-1 text-sm text-gray-500"}
|
||||
"Day-ahead spot prices for DK1 in øre/kWh"]
|
||||
"Day-ahead spot prices for DK1 (øre/kWh)"]
|
||||
[:button {:class "mt-4 rounded-lg bg-blue-600 px-4 py-2 text-white font-medium
|
||||
active:bg-blue-700 transition-colors"
|
||||
:hx-post "/prices/fetch"
|
||||
|
||||
Reference in New Issue
Block a user