-
Notifications
You must be signed in to change notification settings - Fork 985
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#16377] feat: add calendar component in quo2 preview
- Loading branch information
1 parent
ac3b397
commit 9fb675d
Showing
34 changed files
with
937 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
(ns quo2.components.calendar.calendar.component-spec | ||
(:require [quo2.components.calendar.calendar.view :as calendar] | ||
[test-helpers.component :as h] | ||
[cljs-time.core :as time])) | ||
|
||
(def start-date (time/date-time (time/year (time/now)) (time/month (time/now)) 5)) | ||
(def end-date (time/date-time (time/plus start-date (time/days 2)))) | ||
|
||
(h/describe "calendar component" | ||
(h/test "default render of calendar component" | ||
(h/render | ||
[calendar/view | ||
{:start-date start-date | ||
:end-date end-date}]) | ||
(-> (h/expect (h/query-by-translation-text "Mo")) | ||
(h/is-truthy))) | ||
|
||
(h/test "should call on-change with selected date on first click" | ||
(let [on-change (h/mock-fn)] | ||
(h/render | ||
[calendar/view | ||
{:start-date nil | ||
:end-date nil | ||
:on-change on-change}]) | ||
(h/fire-event :press (h/query-by-text (str (time/day start-date)))) | ||
(h/was-called-with on-change {:start-date start-date :end-date nil}))) | ||
|
||
(h/test "should call on-change with start and end date on second click" | ||
(let [on-change (h/mock-fn)] | ||
(h/render | ||
[calendar/view | ||
{:start-date start-date :end-date nil :on-change on-change}]) | ||
(h/fire-event :press (h/query-by-text (str (time/day end-date)))) | ||
(h/was-called-with on-change {:start-date start-date :end-date end-date}))) | ||
|
||
(h/test "should reset the dates on third click" | ||
(let [on-change (h/mock-fn)] | ||
(h/render | ||
[calendar/view | ||
{:start-date start-date | ||
:end-date end-date | ||
:on-change on-change}]) | ||
(h/fire-event :press (h/query-by-text (str (time/day start-date)))) | ||
(h/was-called-with on-change {:start-date start-date :end-date nil}))) | ||
|
||
(h/test "should reset dates when start date is clicked again" | ||
(let [on-change (h/mock-fn)] | ||
(h/render | ||
[calendar/view | ||
{:start-date start-date | ||
:end-date nil | ||
:on-change on-change}]) | ||
(h/fire-event :press (h/query-by-text (str (time/day start-date)))) | ||
(h/was-called-with on-change {:start-date nil :end-date nil}))) | ||
|
||
(h/test "should assign start and end date correctly when upper range selected first" | ||
(let [on-change (h/mock-fn)] | ||
(h/render | ||
[calendar/view | ||
{:start-date end-date | ||
:end-date nil | ||
:on-change on-change}]) | ||
(h/fire-event :press (h/query-by-text (str (time/day start-date)))) | ||
(h/was-called-with on-change {:start-date start-date :end-date end-date})))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
(ns quo2.components.calendar.calendar.days-grid.style) | ||
|
||
(def container-days | ||
{:flex-grow 1 | ||
:margin-top 4 | ||
:margin-horizontal 8 | ||
:overflow :hidden}) |
65 changes: 65 additions & 0 deletions
65
src/quo2/components/calendar/calendar/days_grid/utils.cljs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
(ns quo2.components.calendar.calendar.days-grid.utils | ||
(:require | ||
[utils.number :as utils.number] | ||
[cljs-time.core :as time])) | ||
|
||
(defn- day-of-week | ||
[date] | ||
(let [day (time/day-of-week date)] | ||
(mod day 7))) | ||
|
||
(defn- add-days | ||
[date days] | ||
(time/plus date (time/days days))) | ||
|
||
(defn day-grid | ||
[year month] | ||
(let [year (utils.number/parse-int year) | ||
month (utils.number/parse-int month) | ||
first-day (time/date-time year month 1) | ||
start-day (add-days first-day (- 0 (day-of-week first-day))) | ||
end-day (add-days start-day 34)] | ||
(loop [days [] | ||
current-day start-day] | ||
(if (time/after? current-day end-day) | ||
days | ||
(recur (conj days current-day) (add-days current-day 1)))))) | ||
|
||
(defn get-day-state | ||
[day today year month start-date end-date] | ||
(cond | ||
(and start-date (time/equal? day start-date)) :selected | ||
(and end-date (time/equal? day end-date)) :selected | ||
(and (= (time/year day) (time/year today)) | ||
(= (time/month day) (time/month today)) | ||
(= (time/day day) (time/day today))) :today | ||
(and (= (time/year day) year) (= (time/month day) month)) :default | ||
:else :disabled)) | ||
|
||
(defn update-range | ||
[day start-date end-date] | ||
(let [new-state (cond | ||
(and start-date end-date) {:start-date day :end-date nil} | ||
(and start-date (time/equal? day start-date)) {:start-date nil :end-date nil} | ||
(and end-date (time/equal? day end-date)) {:start-date nil :end-date nil} | ||
(nil? start-date) {:start-date day :end-date nil} | ||
(nil? end-date) {:start-date start-date :end-date day} | ||
:else {:start-date start-date | ||
:end-date end-date})] | ||
(if (and (:start-date new-state) | ||
(:end-date new-state) | ||
(time/after? (:start-date new-state) (:end-date new-state))) | ||
{:start-date (:end-date new-state) :end-date (:start-date new-state)} | ||
new-state))) | ||
|
||
(defn in-range? | ||
[day start-date end-date] | ||
(and start-date end-date (time/after? day start-date) (time/before? day end-date))) | ||
|
||
(defn get-in-range-pos | ||
[day start-date end-date] | ||
(cond | ||
(or (nil? start-date) (nil? end-date)) nil | ||
(and start-date (time/equal? day start-date)) :start | ||
(and end-date (time/equal? day end-date)) :end | ||
(in-range? day start-date end-date) :middle)) |
51 changes: 51 additions & 0 deletions
51
src/quo2/components/calendar/calendar/days_grid/utils_test.cljs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
(ns quo2.components.calendar.calendar.days-grid.utils-test | ||
(:require [cljs.test :refer-macros [deftest is testing]] | ||
[quo2.components.calendar.calendar.days-grid.utils :as utils] | ||
[cljs-time.core :as time])) | ||
|
||
(deftest day-grid-test | ||
(let [day-grid-result (utils/day-grid "2023" "7")] | ||
(testing "it returns correct days grid" | ||
(is (= 35 (count day-grid-result))) | ||
(is (time/equal? (time/date-time 2023 6 25) (first day-grid-result))) | ||
(is (time/equal? (time/date-time 2023 7 29) (last day-grid-result)))))) | ||
|
||
(deftest get-day-state-test | ||
(let [today (time/date-time 2023 7 27) | ||
year 2023 | ||
month 7 | ||
start-date (time/date-time 2023 7 20) | ||
end-date (time/date-time 2023 7 30)] | ||
(testing "it returns :today when day equals today" | ||
(is (= :today (utils/get-day-state today today year month start-date end-date)))) | ||
(testing "it returns :selected when day equals start-date and not today" | ||
(is | ||
(= :selected (utils/get-day-state start-date today year month start-date end-date)))) | ||
(testing "it returns :selected when day equals end-date and not today" | ||
(is | ||
(= :selected (utils/get-day-state end-date today year month start-date end-date)))))) | ||
|
||
(deftest update-range-test | ||
(let [start-date (time/date-time 2023 7 20) | ||
end-date (time/date-time 2023 7 30) | ||
day (time/date-time 2023 7 27)] | ||
(testing "it returns updated range" | ||
(is | ||
(= {:start-date day :end-date nil} (utils/update-range day start-date end-date)))))) | ||
|
||
(deftest in-range-test | ||
(let [start-date (time/date-time 2023 7 20) | ||
end-date (time/date-time 2023 7 30) | ||
day (time/date-time 2023 7 27)] | ||
(testing "it returns true when day is within range" | ||
(is (utils/in-range? day start-date end-date)) | ||
(is (not (utils/in-range? (time/date-time 2023 7 19) start-date end-date)))))) | ||
|
||
(deftest get-in-range-pos-test | ||
(let [start-date (time/date-time 2023 7 20) | ||
end-date (time/date-time 2023 7 30) | ||
day (time/date-time 2023 7 27)] | ||
(testing "it returns correct position within range" | ||
(is (= :start (utils/get-in-range-pos start-date start-date end-date))) | ||
(is (= :end (utils/get-in-range-pos end-date start-date end-date))) | ||
(is (= :middle (utils/get-in-range-pos day start-date end-date)))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
(ns quo2.components.calendar.calendar.days-grid.view | ||
(:require [react-native.core :as rn] | ||
[cljs-time.core :as time] | ||
[quo2.components.calendar.calendar.days-grid.utils :as utils] | ||
[quo2.components.calendar.calendar-day.view :as calendar-day] | ||
[quo2.components.calendar.calendar.days-grid.style :as style])) | ||
|
||
(defn- day-view | ||
[day _ _ {:keys [year month selection-range on-press customization-color]}] | ||
(let [today (time/now) | ||
start-date (:start-date selection-range) | ||
end-date (:end-date selection-range) | ||
state (utils/get-day-state day today year month start-date end-date) | ||
in-range (utils/get-in-range-pos day start-date end-date) | ||
on-press #(on-press (time/date-time day))] | ||
[calendar-day/view | ||
{:customization-color customization-color | ||
:state state | ||
:in-range in-range | ||
:on-press on-press} | ||
(str (time/day day))])) | ||
|
||
(defn view | ||
[{:keys [year month on-change start-date end-date customization-color]}] | ||
(let [on-day-press (fn [day] | ||
(let [new-selection (utils/update-range day start-date end-date)] | ||
(on-change new-selection)))] | ||
[rn/view | ||
{:style style/container-days} | ||
[rn/flat-list | ||
{:data (utils/day-grid year month) | ||
:key-fn str | ||
:num-columns 7 | ||
:content-container-style {:margin-horizontal -2} | ||
:render-fn day-view | ||
:render-data {:customization-color customization-color | ||
:year year | ||
:month month | ||
:on-press on-day-press | ||
:selection-range {:start-date start-date | ||
:end-date end-date}}}]])) |
25 changes: 25 additions & 0 deletions
25
src/quo2/components/calendar/calendar/month_picker/component_spec.cljs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
(ns quo2.components.calendar.calendar.month-picker.component-spec | ||
(:require [quo2.components.calendar.calendar.month-picker.view :as month-picker] | ||
[test-helpers.component :as h])) | ||
|
||
(h/describe "month-picker component" | ||
(h/test "default render of month-picker component" | ||
(h/render | ||
[month-picker/view | ||
{:year "2023" :month "7"}]) | ||
(-> (h/expect (h/query-by-translation-text "July 2023")) | ||
(h/is-truthy))) | ||
|
||
(h/test "should call on-change with next month when right button pressed" | ||
(let [on-change (h/mock-fn)] | ||
(h/render | ||
[month-picker/view {:year "2023" :month "7" :on-change on-change}]) | ||
(h/fire-event :press (h/query-by-label-text :next-month-button)) | ||
(h/was-called on-change))) | ||
|
||
(h/test "should call on-change with previous month when left button pressed" | ||
(let [on-change (h/mock-fn)] | ||
(h/render | ||
[month-picker/view {:year "2023" :month "1" :on-change on-change}]) | ||
(h/fire-event :press (h/query-by-label-text :previous-month-button)) | ||
(h/was-called on-change)))) |
14 changes: 14 additions & 0 deletions
14
src/quo2/components/calendar/calendar/month_picker/style.cljs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
(ns quo2.components.calendar.calendar.month-picker.style | ||
(:require [quo2.foundations.colors :as colors])) | ||
|
||
(def container | ||
{:align-items :center | ||
:flex-direction :row | ||
:flex-grow 1 | ||
:padding-horizontal 12 | ||
:padding-vertical 9 | ||
:justify-content :space-between}) | ||
|
||
(defn text | ||
[theme] | ||
{:color (colors/theme-colors colors/neutral-100 colors/white theme)}) |
22 changes: 22 additions & 0 deletions
22
src/quo2/components/calendar/calendar/month_picker/utils.cljs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
(ns quo2.components.calendar.calendar.month-picker.utils | ||
(:require [utils.datetime :as datetime])) | ||
|
||
(defn format-month-year | ||
[year month] | ||
(let [month (cond | ||
(or (nil? month) (zero? month)) 1 | ||
(> month 12) 12 | ||
:else month)] | ||
(str (datetime/format-long-month month) " " year))) | ||
|
||
(defn next-month | ||
[year month] | ||
(let [new-month (if (= month 12) 1 (inc month)) | ||
new-year (if (= month 12) (inc year) year)] | ||
{:year (str new-year) :month (str new-month)})) | ||
|
||
(defn previous-month | ||
[year month] | ||
(let [new-month (if (= month 1) 12 (dec month)) | ||
new-year (if (= month 1) (dec year) year)] | ||
{:year (str new-year) :month (str new-month)})) |
20 changes: 20 additions & 0 deletions
20
src/quo2/components/calendar/calendar/month_picker/utils_test.cljs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
(ns quo2.components.calendar.calendar.month-picker.utils-test | ||
(:require [cljs.test :refer-macros [deftest is testing]] | ||
[quo2.components.calendar.calendar.month-picker.utils :as utils])) | ||
|
||
(deftest format-month-year-test | ||
(testing "returns correct format for given year and month" | ||
(is (= (utils/format-month-year 2023 1) "January 2023")) | ||
(is (= (utils/format-month-year 2023 12) "December 2023")) | ||
(is (= (utils/format-month-year 2023 0) "January 2023")) | ||
(is (= (utils/format-month-year 2023 13) "December 2023")))) | ||
|
||
(deftest next-month-test | ||
(testing "returns the next month and year" | ||
(is (= (utils/next-month 2023 1) {:year "2023" :month "2"})) | ||
(is (= (utils/next-month 2023 12) {:year "2024" :month "1"})))) | ||
|
||
(deftest previous-month-test | ||
(testing "returns the previous month and year" | ||
(is (= (utils/previous-month 2023 1) {:year "2022" :month "12"})) | ||
(is (= (utils/previous-month 2023 12) {:year "2023" :month "11"})))) |
36 changes: 36 additions & 0 deletions
36
src/quo2/components/calendar/calendar/month_picker/view.cljs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
(ns quo2.components.calendar.calendar.month-picker.view | ||
(:require [react-native.core :as rn] | ||
[utils.number :as utils.number] | ||
[quo2.theme :as theme] | ||
[quo2.components.buttons.button.view :as button] | ||
[quo2.components.markdown.text :as text] | ||
[quo2.components.calendar.calendar.month-picker.style :as style] | ||
[quo2.components.calendar.calendar.month-picker.utils :as utils])) | ||
|
||
(defn- view-internal | ||
[{:keys [year month on-change theme]}] | ||
(let [year (utils.number/parse-int year) | ||
month (utils.number/parse-int month)] | ||
[rn/view | ||
{:style style/container} | ||
[button/button | ||
{:icon true | ||
:type :outline | ||
:accessibility-label :previous-month-button | ||
:size 24 | ||
:on-press #(on-change (utils/previous-month year month))} | ||
:i/chevron-left] | ||
[text/text | ||
{:weight :semi-bold | ||
:size :paragraph-1 | ||
:style (style/text theme)} | ||
(utils/format-month-year year month)] | ||
[button/button | ||
{:icon true | ||
:accessibility-label :next-month-button | ||
:size 24 | ||
:type :outline | ||
:on-press #(on-change (utils/next-month year month))} | ||
:i/chevron-right]])) | ||
|
||
(def view (theme/with-theme view-internal)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
(ns quo2.components.calendar.calendar.style | ||
(:require [quo2.foundations.colors :as colors])) | ||
|
||
(defn container | ||
[theme] | ||
{:flex-direction :row | ||
:height 270 | ||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme) | ||
:border-radius 12 | ||
:border-width 1 | ||
:background-color (colors/theme-colors colors/white colors/neutral-80-opa-40 theme)}) | ||
|
||
(def container-main | ||
{:flex-grow 1}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
(ns quo2.components.calendar.calendar.utils | ||
(:require [utils.datetime :as datetime] | ||
[utils.number :as utils.number] | ||
[clojure.string :as string])) | ||
|
||
(defn generate-years | ||
[current-year] | ||
(let [current-year current-year] | ||
(reverse (vec (range (- current-year 100) (+ current-year 1)))))) | ||
|
||
(defn current-year | ||
[] | ||
(-> (datetime/now) | ||
datetime/timestamp->year-month-day-date | ||
(string/split #"-") | ||
first | ||
utils.number/parse-int)) | ||
|
||
(defn current-month | ||
[] | ||
(-> (datetime/now) | ||
datetime/timestamp->year-month-day-date | ||
(string/split #"-") | ||
second | ||
utils.number/parse-int)) |
Oops, something went wrong.