Commit 6f1247273f01aa4cd3d498b3c19fcea474f504ae
/new : basic time-picker built!
mixmix committed on 8/23/2018, 11:41:18 AMParent: c570701c242c9ea977861c585348b6ea930a6194
Files changed
package-lock.json | changed |
views/new.js | changed |
views/new.mcss | changed |
views/new.test.js | changed |
package-lock.json | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 131900 bytes New file size: 132068 bytes |
views/new.js | |||
---|---|---|---|
@@ -1,15 +1,20 @@ | |||
1 | -const { h, Struct, Array: MutantArray, when, computed } = require('mutant') | ||
1 … | +const { h, Value, Struct, Array: MutantArray, when, computed } = require('mutant') | ||
2 | 2 … | const Marama = require('marama') | |
3 | 3 … | ||
4 | 4 … | module.exports = function ScryNew (opts) { | |
5 … | + const { | ||
6 … | + // i18n | ||
7 … | + } = opts | ||
8 … | + | ||
5 | 9 … | const state = Struct({ | |
10 … | + pristine: true, | ||
6 | 11 … | monthIndex: new Date().getMonth(), | |
7 | 12 … | days: MutantArray([]), | |
8 | - pristine: true | ||
13 … | + times: MutantArray([]) | ||
9 | 14 … | }) | |
10 | 15 … | ||
11 | - const page = h('ScryNew', [ | ||
16 … | + return h('ScryNew', [ | ||
12 | 17 … | h('div.cal-picker', [ | |
13 | 18 … | h('div.month-picker', [ | |
14 | 19 … | h('button', { 'ev-click': () => setMonth(-1) }, '<'), | |
15 | 20 … | MonthTitle(state.monthIndex), | |
@@ -35,9 +40,17 @@ | |||
35 | 40 … | h('div.instruction', 'Select one or multiple dates') | |
36 | 41 … | ]), | |
37 | 42 … | h('div.time-picker', [ | |
38 | 43 … | h('label', computed(state.days, days => `Same times for all dates (${days.length})`)), | |
39 | - h('div.picker'), | ||
44 … | + h('div.picker', [ | ||
45 … | + computed(state.times, times => { | ||
46 … | + return times | ||
47 … | + .map(time => time.date) | ||
48 … | + // .sort((a, b) => a - b) | ||
49 … | + .map(TimeEntry) | ||
50 … | + }), | ||
51 … | + NewTimeEntry() | ||
52 … | + ]), | ||
40 | 53 … | h('div.timezone', [ | |
41 | 54 … | h('label', 'Timezone of your scry is'), | |
42 | 55 … | h('div.zone', [ | |
43 | 56 … | getTimezone(), | |
@@ -47,14 +60,58 @@ | |||
47 | 60 … | ]) | |
48 | 61 … | ) | |
49 | 62 … | ]) | |
50 | 63 … | ||
51 | - return page | ||
64 … | + // functions | ||
52 | 65 … | ||
53 | 66 … | function setMonth (d) { | |
54 | 67 … | state.monthIndex.set(state.monthIndex() + d) | |
55 | 68 … | } | |
56 | 69 … | ||
70 … | + function NewTimeEntry () { | ||
71 … | + var active = Value(false) | ||
72 … | + | ||
73 … | + // TODO extract and only run once | ||
74 … | + const options = Array(96).fill(0).map((_, i) => { | ||
75 … | + var time = new Date () | ||
76 … | + time.setHours(0) | ||
77 … | + time.setMinutes(15 * i) | ||
78 … | + return time | ||
79 … | + | ||
80 … | + }) | ||
81 … | + | ||
82 … | + return h('div.new-time-entry', [ | ||
83 … | + when(active, | ||
84 … | + h('div.dropdown', options.map(time => { | ||
85 … | + return h('div', | ||
86 … | + { | ||
87 … | + 'ev-click': () => { | ||
88 … | + state.times.push(Event(time)) | ||
89 … | + active.set(false) | ||
90 … | + } | ||
91 … | + }, | ||
92 … | + printTime(time) | ||
93 … | + ) | ||
94 … | + })) | ||
95 … | + ), | ||
96 … | + h('div.add', { 'ev-click': () => active.set(true) }, '+ Add more times') | ||
97 … | + ]) | ||
98 … | + } | ||
99 … | + | ||
100 … | + function TimeEntry (date) { | ||
101 … | + return h('div.time-entry', [ | ||
102 … | + h('div.time', printTime(date)), | ||
103 … | + h('div.close', { 'ev-click': () => removeTime(date) }, '×') | ||
104 … | + // h('i.fa.fa-close') | ||
105 … | + ]) | ||
106 … | + } | ||
107 … | + | ||
108 … | + function removeTime (d) { | ||
109 … | + var ev = state.times.find(time => time.date === d) | ||
110 … | + | ||
111 … | + if (ev) state.times.delete(ev) | ||
112 … | + } | ||
113 … | + | ||
57 | 114 … | function MonthTitle (monthIndex) { | |
58 | 115 … | const MONTHS = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] | |
59 | 116 … | ||
60 | 117 … | return computed(monthIndex, mi => { | |
@@ -74,20 +131,24 @@ | |||
74 | 131 … | ||
75 | 132 … | state.pristine.set(false) | |
76 | 133 … | ||
77 | 134 … | function addEmptyEvent () { | |
78 | - state.days.push({ | ||
79 | - date: gte, | ||
80 | - data: {attending: true} | ||
81 | - }) | ||
135 … | + state.days.push(Event(gte)) | ||
82 | 136 … | } | |
83 | 137 … | function clearDay () { | |
84 | 138 … | const filteredEvents = state.days().filter(e => !days.includes(e)) | |
85 | 139 … | state.days.set(filteredEvents) | |
86 | 140 … | } | |
87 | 141 … | } | |
88 | 142 … | } | |
89 | 143 … | ||
144 … | +function Event (date) { | ||
145 … | + return { | ||
146 … | + date, | ||
147 … | + data: {attending: true} | ||
148 … | + } | ||
149 … | +} | ||
150 … | + | ||
90 | 151 … | function getTimezone () { | |
91 | 152 … | try { | |
92 | 153 … | return Intl.DateTimeFormat().resolvedOptions().timeZone | |
93 | 154 … | } catch (e) { | |
@@ -97,4 +158,14 @@ | |||
97 | 158 … | ||
98 | 159 … | function getTimezoneOffset () { | |
99 | 160 … | return new Date().getTimezoneOffset() / 60 | |
100 | 161 … | } | |
162 … | + | ||
163 … | +function printTime (date) { | ||
164 … | + var hours = date.getHours().toString() | ||
165 … | + while (hours.length < 2) hours = `0${hours}` | ||
166 … | + | ||
167 … | + var minutes = date.getMinutes().toString() | ||
168 … | + while (minutes.length < 2) minutes = `0${minutes}` | ||
169 … | + | ||
170 … | + return `${hours}:${minutes}` | ||
171 … | +} |
views/new.mcss | ||
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | 1 … | ScryNew { |
2 | 2 … | --br: 5px |
3 | 3 … | --boundary: 1rem |
4 … | + --feature-color: hsla(295, 67%, 60%, 1) | |
4 | 5 … | |
5 | 6 … | font-family: sans, arial |
6 | 7 … | |
7 | 8 … | display: grid |
@@ -26,9 +27,9 @@ | ||
26 | 27 … | |
27 | 28 … | margin-bottom: 1rem |
28 | 29 … | |
29 | 30 … | button { |
30 | - color: hsla(295, 67%, 60%, 1) | |
31 … | + color: var(--feature-color) | |
31 | 32 … | font-size: .8rem |
32 | 33 … | |
33 | 34 … | background: none |
34 | 35 … | border: none |
@@ -64,13 +65,56 @@ | ||
64 | 65 … | margin: var(--boundary) var(--boundary) calc(var(--boundary) / 2) var(--boundary) |
65 | 66 … | } |
66 | 67 … | |
67 | 68 … | div.picker { |
69 … | + color: #666 | |
70 … | + background: #fff | |
71 … | + border-radius: var(--br) | |
68 | 72 … | margin: 0 var(--boundary) var(--boundary) |
69 | 73 … | |
70 | - min-height: 10rem | |
71 | - background: #fff | |
72 | - border-radius: var(--br) | |
74 … | + div.time-entry { | |
75 … | + padding: calc(var(--boundary) / 2) | |
76 … | + border-bottom: 1px solid hsla(0, 0%, 0%, .2) | |
77 … | + | |
78 … | + display: flex | |
79 … | + justify-content: space-between | |
80 … | + | |
81 … | + div.close { cursor: pointer } | |
82 … | + } | |
83 … | + | |
84 … | + div.new-time-entry { | |
85 … | + font-size: .9rem | |
86 … | + position: relative | |
87 … | + | |
88 … | + div.dropdown { | |
89 … | + position: absolute | |
90 … | + left: calc(var(--boundary) / 2) | |
91 … | + right: calc(var(--boundary) / 2) | |
92 … | + top: calc(var(--boundary) / 2) | |
93 … | + | |
94 … | + background: #fff | |
95 … | + max-height: 20vh | |
96 … | + overflow-y: scroll | |
97 … | + padding: calc(var(--boundary) / 2) | |
98 … | + | |
99 … | + div { | |
100 … | + padding: 2px | |
101 … | + :hover { | |
102 … | + background: var(--feature-color) | |
103 … | + color: #fff | |
104 … | + } | |
105 … | + } | |
106 … | + } | |
107 … | + | |
108 … | + div.add { | |
109 … | + color: var(--feature-color) | |
110 … | + padding: calc(var(--boundary) / 2) | |
111 … | + cursor: pointer | |
112 … | + | |
113 … | + display: flex | |
114 … | + justify-content: center | |
115 … | + } | |
116 … | + } | |
73 | 117 … | } |
74 | 118 … | |
75 | 119 … | div.timezone { |
76 | 120 … | padding: var(--boundary) |
@@ -148,9 +192,10 @@ | ||
148 | 192 … | } |
149 | 193 … | |
150 | 194 … | -future { |
151 | 195 … | background: none |
152 | - --color: deepskyblue | |
196 … | + --color: hsla(320, 100%, 60%, 1) | |
197 … | + /* deepskyblue */ | |
153 | 198 … | |
154 | 199 … | -events { |
155 | 200 … | border: 1px solid var(--color) |
156 | 201 … | color: var(--color) |
views/new.test.js | ||
---|---|---|
@@ -12,9 +12,15 @@ | ||
12 | 12 … | document.body.appendChild(newScry) |
13 | 13 … | document.head.appendChild( |
14 | 14 … | h('style', ` |
15 | 15 … | body { |
16 | - background: #de82e6; | |
16 … | + --gradient: linear-gradient(45deg, hsla(60, 100%, 56%, .5), hsla(280, 100%, 46%, 0.3)); | |
17 … | + --texture: left top 0 / 3px radial-gradient(white, #de82e6) repeat ; | |
18 … | + background: var(--texture), var(--gradient); | |
19 … | + background-blend-mode: darken; | |
20 … | + | |
21 … | + width: 100vh; | |
22 … | + height: 100vh; | |
17 | 23 … | padding: 2rem; |
18 | 24 … | } |
19 | 25 … | `) |
20 | 26 … | ) |
Built with git-ssb-web