@monolith-forensics/monolith-ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -0
- package/package.json +19 -0
- package/src/Calendar/Calendar.js +329 -0
- package/src/Calendar/CalendarStyles.js +168 -0
- package/src/Calendar/calendarHelpers.js +194 -0
- package/src/CheckBox.js +49 -0
- package/src/DataGrid/DataGrid.js +729 -0
- package/src/DateBox.js +77 -0
- package/src/Form.js +116 -0
- package/src/Input.js +160 -0
- package/src/Menu.js +196 -0
- package/src/NumberBox.js +121 -0
- package/src/OptionButton.js +89 -0
- package/src/SelectBox.js +252 -0
- package/src/TagBox/TagBox.js +75 -0
- package/src/TagBox/TagBoxStyles.js +122 -0
- package/src/TextArea.js +85 -0
- package/src/TextAreaBox.js +43 -0
- package/src/TextBox.js +10 -0
- package/src/TimeBox.js +0 -0
- package/src/Timeline.js +153 -0
- package/src/index.js +0 -0
package/.gitattributes
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@monolith-forensics/monolith-ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "UI used for Monolith Apps",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/Monolith-Forensics/monolith-ui.git"
|
|
12
|
+
},
|
|
13
|
+
"author": "Matt Danner",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/Monolith-Forensics/monolith-ui/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/Monolith-Forensics/monolith-ui#readme"
|
|
19
|
+
}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import React, { Fragment, useEffect, useState } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import ArrowLeftIcon from "@mui/icons-material/ArrowLeft";
|
|
4
|
+
import ArrowRightIcon from "@mui/icons-material/ArrowRight";
|
|
5
|
+
import {
|
|
6
|
+
CalendarContainer,
|
|
7
|
+
CalendarHeader,
|
|
8
|
+
CalendarGrid,
|
|
9
|
+
CalendarMonth,
|
|
10
|
+
CalendarDay,
|
|
11
|
+
CalendarDate,
|
|
12
|
+
HighlightedCalendarDate,
|
|
13
|
+
TodayCalendarDate,
|
|
14
|
+
TimeContainer,
|
|
15
|
+
MainContainer,
|
|
16
|
+
TimePickerContainer,
|
|
17
|
+
TimeHourSelect,
|
|
18
|
+
TimeHeader,
|
|
19
|
+
TimeMinuteSelect,
|
|
20
|
+
TimeItem,
|
|
21
|
+
TimeItemActive,
|
|
22
|
+
} from "./CalendarStyles";
|
|
23
|
+
import calendar, {
|
|
24
|
+
isDate,
|
|
25
|
+
isSameDay,
|
|
26
|
+
isSameMonth,
|
|
27
|
+
getDateISO,
|
|
28
|
+
getNextMonth,
|
|
29
|
+
getPreviousMonth,
|
|
30
|
+
WEEK_DAYS,
|
|
31
|
+
CALENDAR_MONTHS,
|
|
32
|
+
HOURS24,
|
|
33
|
+
HOURS12,
|
|
34
|
+
MINUTES,
|
|
35
|
+
} from "./calendarHelpers";
|
|
36
|
+
import moment from "moment";
|
|
37
|
+
|
|
38
|
+
export default function Calendar({
|
|
39
|
+
date = new Date(),
|
|
40
|
+
onDateChanged = () => {},
|
|
41
|
+
hourFormat = "24",
|
|
42
|
+
}) {
|
|
43
|
+
const [dateState, setDateState] = useState({
|
|
44
|
+
current: new Date(),
|
|
45
|
+
month: 0,
|
|
46
|
+
year: 0,
|
|
47
|
+
hours: 0,
|
|
48
|
+
minutes: 0,
|
|
49
|
+
});
|
|
50
|
+
const [today, setToday] = useState(new Date());
|
|
51
|
+
let pressureTimer, pressureTimeout, dayTimeout;
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
addDateToState(date);
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
const addDateToState = (date) => {
|
|
58
|
+
const isDateObject = isDate(date);
|
|
59
|
+
const _date = isDateObject ? date : new Date();
|
|
60
|
+
setDateState({
|
|
61
|
+
current: isDateObject ? date : null,
|
|
62
|
+
month: +_date.getMonth() + 1,
|
|
63
|
+
year: _date.getFullYear(),
|
|
64
|
+
hours: _date.getHours(),
|
|
65
|
+
minutes: _date.getMinutes(),
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const getCalendarDates = () => {
|
|
70
|
+
const { current, month, year } = dateState;
|
|
71
|
+
const calendarMonth = month || +current?.getMonth() + 1;
|
|
72
|
+
const calendarYear = year || current?.getFullYear();
|
|
73
|
+
return calendar(calendarMonth, calendarYear);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
//new start
|
|
77
|
+
|
|
78
|
+
const renderMonthAndYear = () => {
|
|
79
|
+
const { month, year } = dateState;
|
|
80
|
+
|
|
81
|
+
// Resolve the month name from the CALENDAR_MONTHS object map
|
|
82
|
+
const monthname =
|
|
83
|
+
Object.keys(CALENDAR_MONTHS)[Math.max(0, Math.min(month - 1, 11))];
|
|
84
|
+
return (
|
|
85
|
+
<CalendarHeader>
|
|
86
|
+
<ArrowLeftIcon
|
|
87
|
+
onMouseDown={handlePrevious}
|
|
88
|
+
onMouseUp={clearPressureTimer}
|
|
89
|
+
title="Previous Month"
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<CalendarMonth>
|
|
93
|
+
{monthname} {year}
|
|
94
|
+
</CalendarMonth>
|
|
95
|
+
|
|
96
|
+
<ArrowRightIcon
|
|
97
|
+
onMouseDown={handleNext}
|
|
98
|
+
onMouseUp={clearPressureTimer}
|
|
99
|
+
title="Next Month"
|
|
100
|
+
/>
|
|
101
|
+
</CalendarHeader>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
// Render the label for day of the week
|
|
105
|
+
// This method is used as a map callback as seen in render()
|
|
106
|
+
const renderDayLabel = (day, index) => {
|
|
107
|
+
// Resolve the day of the week label from the WEEK_DAYS object map
|
|
108
|
+
const daylabel = WEEK_DAYS[day];
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<CalendarDay key={daylabel} index={index}>
|
|
112
|
+
{daylabel}
|
|
113
|
+
</CalendarDay>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
// Render a calendar date as returned from the calendar builder function
|
|
117
|
+
// This method is used as a map callback as seen in render()
|
|
118
|
+
const renderCalendarDate = (date, index) => {
|
|
119
|
+
const { current, month, year } = dateState;
|
|
120
|
+
const _date = new Date(date.join("-"));
|
|
121
|
+
// Check if calendar date is same day as today
|
|
122
|
+
const isToday = isSameDay(_date, today);
|
|
123
|
+
|
|
124
|
+
// Check if calendar date is same day as currently selected date
|
|
125
|
+
const isCurrent = current && isSameDay(_date, current);
|
|
126
|
+
|
|
127
|
+
// Check if calendar date is in the same month as the state month and year
|
|
128
|
+
const inMonth =
|
|
129
|
+
month && year && isSameMonth(_date, new Date([year, month, 1].join("-")));
|
|
130
|
+
// The click handler
|
|
131
|
+
const onClick = gotoDate(_date);
|
|
132
|
+
const props = { index, inMonth, onClick, title: _date.toDateString() };
|
|
133
|
+
// Conditionally render a styled date component
|
|
134
|
+
const DateComponent = isCurrent
|
|
135
|
+
? HighlightedCalendarDate
|
|
136
|
+
: isToday
|
|
137
|
+
? TodayCalendarDate
|
|
138
|
+
: CalendarDate;
|
|
139
|
+
return (
|
|
140
|
+
<DateComponent key={getDateISO(_date)} {...props}>
|
|
141
|
+
{_date.getDate()}
|
|
142
|
+
</DateComponent>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const renderHours = () => {
|
|
147
|
+
const { hours } = dateState;
|
|
148
|
+
const hoursArray = hourFormat === "24" ? HOURS24 : HOURS12;
|
|
149
|
+
return hoursArray.map((hour, index) => {
|
|
150
|
+
const HourComponent =
|
|
151
|
+
parseInt(hour.value) === hours ? TimeItemActive : TimeItem;
|
|
152
|
+
return (
|
|
153
|
+
<HourComponent
|
|
154
|
+
key={hour.value}
|
|
155
|
+
value={hour.value}
|
|
156
|
+
onClick={(e) => {
|
|
157
|
+
const newTime = moment(dateState.current)
|
|
158
|
+
.hours(hour.value)
|
|
159
|
+
.toDate();
|
|
160
|
+
setDateState({
|
|
161
|
+
...dateState,
|
|
162
|
+
hours: parseInt(hour.value),
|
|
163
|
+
current: newTime,
|
|
164
|
+
});
|
|
165
|
+
onDateChanged(newTime);
|
|
166
|
+
}}
|
|
167
|
+
>
|
|
168
|
+
{/* {`${hour.label}${
|
|
169
|
+
hourFormat === "24" ? "" : index < 11 ? " AM" : " PM"
|
|
170
|
+
}`} */}
|
|
171
|
+
{hour.label}
|
|
172
|
+
</HourComponent>
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const renderMinutes = () => {
|
|
178
|
+
const { minutes } = dateState;
|
|
179
|
+
return MINUTES.map((minute) => {
|
|
180
|
+
const MinuteComponent =
|
|
181
|
+
parseInt(minute) === minutes ? TimeItemActive : TimeItem;
|
|
182
|
+
return (
|
|
183
|
+
<MinuteComponent
|
|
184
|
+
key={minute}
|
|
185
|
+
value={minute}
|
|
186
|
+
onClick={(e) => {
|
|
187
|
+
const newTime = moment(dateState.current).minutes(minute).toDate();
|
|
188
|
+
setDateState({
|
|
189
|
+
...dateState,
|
|
190
|
+
minutes: parseInt(minute),
|
|
191
|
+
current: newTime,
|
|
192
|
+
});
|
|
193
|
+
onDateChanged(newTime);
|
|
194
|
+
}}
|
|
195
|
+
>
|
|
196
|
+
{minute}
|
|
197
|
+
</MinuteComponent>
|
|
198
|
+
);
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// new 2
|
|
203
|
+
const gotoDate = (date) => (evt) => {
|
|
204
|
+
evt && evt.preventDefault();
|
|
205
|
+
const { current } = dateState;
|
|
206
|
+
|
|
207
|
+
// Set Hours and Minutes
|
|
208
|
+
const newTime = moment(date)
|
|
209
|
+
.hours(dateState.hours)
|
|
210
|
+
.minutes(dateState.minutes)
|
|
211
|
+
.toDate();
|
|
212
|
+
|
|
213
|
+
!(current && isSameDay(newTime, current)) && addDateToState(newTime);
|
|
214
|
+
onDateChanged(newTime);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const gotoPreviousMonth = () => {
|
|
218
|
+
const { month, year } = dateState;
|
|
219
|
+
// this.setState(getPreviousMonth(month, year));
|
|
220
|
+
const previousMonth = getPreviousMonth(month, year);
|
|
221
|
+
setDateState({
|
|
222
|
+
month: previousMonth.month,
|
|
223
|
+
year: previousMonth.year,
|
|
224
|
+
current: dateState.current,
|
|
225
|
+
hours: dateState.hours,
|
|
226
|
+
minutes: dateState.minutes,
|
|
227
|
+
});
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const gotoNextMonth = () => {
|
|
231
|
+
const { month, year } = dateState;
|
|
232
|
+
//this.setState(getNextMonth(month, year));
|
|
233
|
+
const nextMonth = getNextMonth(month, year);
|
|
234
|
+
setDateState({
|
|
235
|
+
month: nextMonth.month,
|
|
236
|
+
year: nextMonth.year,
|
|
237
|
+
current: dateState.current,
|
|
238
|
+
hours: dateState.hours,
|
|
239
|
+
minutes: dateState.minutes,
|
|
240
|
+
});
|
|
241
|
+
};
|
|
242
|
+
const gotoPreviousYear = () => {
|
|
243
|
+
const { year } = dateState;
|
|
244
|
+
setDateState({
|
|
245
|
+
month: dateState.month,
|
|
246
|
+
year: year - 1,
|
|
247
|
+
current: dateState.current,
|
|
248
|
+
hours: dateState.hours,
|
|
249
|
+
minutes: dateState.minutes,
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
const gotoNextYear = () => {
|
|
253
|
+
const { year } = dateState;
|
|
254
|
+
setDateState({
|
|
255
|
+
month: dateState.month,
|
|
256
|
+
year: year + 1,
|
|
257
|
+
current: dateState.current,
|
|
258
|
+
hours: dateState.hours,
|
|
259
|
+
minutes: dateState.minutes,
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
const handlePressure = (fn) => {
|
|
263
|
+
if (typeof fn === "function") {
|
|
264
|
+
fn();
|
|
265
|
+
pressureTimeout = setTimeout(() => {
|
|
266
|
+
pressureTimer = setInterval(fn, 100);
|
|
267
|
+
}, 500);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
const clearPressureTimer = () => {
|
|
271
|
+
pressureTimer && clearInterval(pressureTimer);
|
|
272
|
+
pressureTimeout && clearTimeout(pressureTimeout);
|
|
273
|
+
};
|
|
274
|
+
const handlePrevious = (evt) => {
|
|
275
|
+
evt && evt.preventDefault();
|
|
276
|
+
const fn = evt.shiftKey ? gotoPreviousYear : gotoPreviousMonth;
|
|
277
|
+
fn();
|
|
278
|
+
// handlePressure(fn);
|
|
279
|
+
};
|
|
280
|
+
const handleNext = (evt) => {
|
|
281
|
+
evt && evt.preventDefault();
|
|
282
|
+
const fn = evt.shiftKey ? gotoNextYear : gotoNextMonth;
|
|
283
|
+
fn();
|
|
284
|
+
// handlePressure(fn);
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
// lifecycle methods
|
|
288
|
+
useEffect(() => {
|
|
289
|
+
const now = new Date();
|
|
290
|
+
const tomorrow = new Date().setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000;
|
|
291
|
+
const ms = tomorrow - now;
|
|
292
|
+
dayTimeout = setTimeout(() => {
|
|
293
|
+
setToday(new Date());
|
|
294
|
+
clearDayTimeout();
|
|
295
|
+
}, ms);
|
|
296
|
+
return () => {
|
|
297
|
+
clearPressureTimer();
|
|
298
|
+
clearDayTimeout();
|
|
299
|
+
};
|
|
300
|
+
}, []);
|
|
301
|
+
|
|
302
|
+
const clearDayTimeout = () => {
|
|
303
|
+
dayTimeout && clearTimeout(dayTimeout);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
return (
|
|
307
|
+
<MainContainer>
|
|
308
|
+
<CalendarContainer>
|
|
309
|
+
{renderMonthAndYear()}
|
|
310
|
+
<CalendarGrid>
|
|
311
|
+
<Fragment>{Object.keys(WEEK_DAYS).map(renderDayLabel)}</Fragment>
|
|
312
|
+
<Fragment>{getCalendarDates().map(renderCalendarDate)}</Fragment>
|
|
313
|
+
</CalendarGrid>
|
|
314
|
+
</CalendarContainer>
|
|
315
|
+
<TimeContainer>
|
|
316
|
+
<TimeHeader>Select Time</TimeHeader>
|
|
317
|
+
<TimePickerContainer>
|
|
318
|
+
<TimeHourSelect>{renderHours()}</TimeHourSelect>
|
|
319
|
+
<TimeMinuteSelect>{renderMinutes()}</TimeMinuteSelect>
|
|
320
|
+
</TimePickerContainer>
|
|
321
|
+
</TimeContainer>
|
|
322
|
+
</MainContainer>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
Calendar.propTypes = {
|
|
327
|
+
date: PropTypes.instanceOf(Date),
|
|
328
|
+
onDateChanged: PropTypes.func,
|
|
329
|
+
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import styled from "@emotion/styled";
|
|
2
|
+
|
|
3
|
+
export const MainContainer = styled.div`
|
|
4
|
+
display: flex;
|
|
5
|
+
`;
|
|
6
|
+
export const CalendarContainer = styled.div`
|
|
7
|
+
font-size: 5px;
|
|
8
|
+
width: 275px;
|
|
9
|
+
border: 1px solid ${(props) => props.theme.palette.divider};
|
|
10
|
+
border-radius: 4px;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
`;
|
|
13
|
+
export const CalendarHeader = styled.div`
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: space-between;
|
|
17
|
+
`;
|
|
18
|
+
export const CalendarGrid = styled.div`
|
|
19
|
+
display: grid;
|
|
20
|
+
grid-template: repeat(7, auto) / repeat(7, auto);
|
|
21
|
+
`;
|
|
22
|
+
export const CalendarMonth = styled.div`
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
font-size: 12px;
|
|
25
|
+
color: ${(props) => props.theme.palette.text.primary};
|
|
26
|
+
text-align: center;
|
|
27
|
+
padding: 0.5em 0.25em;
|
|
28
|
+
word-spacing: 5px;
|
|
29
|
+
user-select: none;
|
|
30
|
+
`;
|
|
31
|
+
export const CalendarCell = styled.div`
|
|
32
|
+
text-align: center;
|
|
33
|
+
align-self: center;
|
|
34
|
+
letter-spacing: 0.1rem;
|
|
35
|
+
padding: 10px;
|
|
36
|
+
user-select: none;
|
|
37
|
+
border-radius: 5px;
|
|
38
|
+
border: 1px solid transparent;
|
|
39
|
+
grid-column: ${(props) => (props.index % 7) + 1} / span 1;
|
|
40
|
+
`;
|
|
41
|
+
export const CalendarDay = styled(CalendarCell)`
|
|
42
|
+
font-weight: bold;
|
|
43
|
+
font-size: 10px;
|
|
44
|
+
border-radius: 0px;
|
|
45
|
+
color: ${(props) => props.theme.palette.text.secondary};
|
|
46
|
+
// border-top: 1px solid ${(props) => props.theme.palette.divider};
|
|
47
|
+
// border-bottom: 1px solid ${(props) => props.theme.palette.divider};
|
|
48
|
+
border-right: ${(props) =>
|
|
49
|
+
(props.index % 7) + 1 === 7
|
|
50
|
+
? `none`
|
|
51
|
+
: `2px solid ${(props) => props.theme.palette.divider}`};
|
|
52
|
+
`;
|
|
53
|
+
export const CalendarDate = styled(CalendarCell)`
|
|
54
|
+
font-weight: ${(props) => (props.inMonth ? 500 : 300)};
|
|
55
|
+
font-size: 10px;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
border-bottom: ${(props) =>
|
|
58
|
+
(props.index + 1) / 7 <= 5
|
|
59
|
+
? `1px solid ${(props) => props.theme.palette.divider}`
|
|
60
|
+
: `1px solid transparent`};
|
|
61
|
+
border-right: ${(props) =>
|
|
62
|
+
(props.index % 7) + 1 === 7
|
|
63
|
+
? `1px solid transparent`
|
|
64
|
+
: `1px solid ${(props) => props.theme.palette.divider}`};
|
|
65
|
+
border-left: 1px solid transparent;
|
|
66
|
+
border-top: 1px solid transparent;
|
|
67
|
+
color: ${(props) =>
|
|
68
|
+
props.inMonth
|
|
69
|
+
? props.theme.palette.text.primary
|
|
70
|
+
: props.theme.palette.text.secondary};
|
|
71
|
+
grid-row: ${(props) => Math.floor(props.index / 7) + 2} / span 1;
|
|
72
|
+
transition: all 0.2s ease-out;
|
|
73
|
+
border-radius: 5px;
|
|
74
|
+
:hover {
|
|
75
|
+
// color: ${(props) => props.theme.palette.primary.main};
|
|
76
|
+
background: ${(props) => props.theme.palette.action.hover};
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
export const HighlightedCalendarDate = styled(CalendarDate)`
|
|
80
|
+
// color: ${(props) => props.theme.palette.primary.main} !important;
|
|
81
|
+
color: white !important;
|
|
82
|
+
background: ${(props) => props.theme.palette.primary.main} !important;
|
|
83
|
+
border: 1px solid ${(props) => props.theme.palette.primary.main} !important;
|
|
84
|
+
position: relative;
|
|
85
|
+
::before {
|
|
86
|
+
content: "";
|
|
87
|
+
position: absolute;
|
|
88
|
+
top: -1px;
|
|
89
|
+
left: -1px;
|
|
90
|
+
width: calc(100% + 2px);
|
|
91
|
+
height: calc(100% + 2px);
|
|
92
|
+
// border: 2px solid #06c;
|
|
93
|
+
}
|
|
94
|
+
`;
|
|
95
|
+
export const TodayCalendarDate = styled(HighlightedCalendarDate)`
|
|
96
|
+
color: ${(props) => props.theme.palette.text.primary} !important;
|
|
97
|
+
background: transparent !important;
|
|
98
|
+
::after {
|
|
99
|
+
content: "";
|
|
100
|
+
position: absolute;
|
|
101
|
+
right: 0;
|
|
102
|
+
bottom: 0;
|
|
103
|
+
border-bottom: 0.75em solid #06c;
|
|
104
|
+
border-left: 0.75em solid transparent;
|
|
105
|
+
border-top: 0.75em solid transparent;
|
|
106
|
+
}
|
|
107
|
+
:hover {
|
|
108
|
+
color: ${(props) => props.theme.palette.text.primary} !important;
|
|
109
|
+
background: ${(props) => props.theme.palette.action.hover} !important;
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
export const TimeContainer = styled.div`
|
|
113
|
+
font-size: 12px;
|
|
114
|
+
width: 150px;
|
|
115
|
+
height: 100%;
|
|
116
|
+
border: 1px solid ${(props) => props.theme.palette.divider};
|
|
117
|
+
border-left: none;
|
|
118
|
+
border-radius: 4px;
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
`;
|
|
121
|
+
export const TimePickerContainer = styled.div`
|
|
122
|
+
display: flex;
|
|
123
|
+
height: 100%;
|
|
124
|
+
`;
|
|
125
|
+
export const TimeHeader = styled.div`
|
|
126
|
+
font-weight: 500;
|
|
127
|
+
font-size: 12px;
|
|
128
|
+
color: ${(props) => props.theme.palette.text.primary};
|
|
129
|
+
border-bottom: 1px solid ${(props) => props.theme.palette.divider};
|
|
130
|
+
text-align: center;
|
|
131
|
+
padding: 5px;
|
|
132
|
+
line-height: 2.3;
|
|
133
|
+
height: 40px;
|
|
134
|
+
// word-spacing: 5px;
|
|
135
|
+
user-select: none;
|
|
136
|
+
`;
|
|
137
|
+
export const TimeHourSelect = styled.div`
|
|
138
|
+
border-right: 1px solid ${(props) => props.theme.palette.divider};
|
|
139
|
+
width: 50%;
|
|
140
|
+
height: 250px;
|
|
141
|
+
overflow-y: auto;
|
|
142
|
+
`;
|
|
143
|
+
export const TimeMinuteSelect = styled.div`
|
|
144
|
+
width: 50%;
|
|
145
|
+
height: 250px;
|
|
146
|
+
overflow-y: auto;
|
|
147
|
+
`;
|
|
148
|
+
export const TimeItem = styled.div`
|
|
149
|
+
font-weight: 500;
|
|
150
|
+
font-size: 10px;
|
|
151
|
+
color: ${(props) => props.theme.palette.text.primary};
|
|
152
|
+
text-align: center;
|
|
153
|
+
padding: 5px;
|
|
154
|
+
// word-spacing: 5px;
|
|
155
|
+
user-select: none;
|
|
156
|
+
cursor: pointer;
|
|
157
|
+
transition: all 0.2s ease-out;
|
|
158
|
+
:hover {
|
|
159
|
+
background: ${(props) => props.theme.palette.action.hover};
|
|
160
|
+
}
|
|
161
|
+
`;
|
|
162
|
+
export const TimeItemActive = styled(TimeItem)`
|
|
163
|
+
background: ${(props) => props.theme.palette.primary.main};
|
|
164
|
+
color: white;
|
|
165
|
+
&:hover {
|
|
166
|
+
background: ${(props) => props.theme.palette.primary.main};
|
|
167
|
+
}
|
|
168
|
+
`;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// (int) The current year
|
|
2
|
+
export const THIS_YEAR = +new Date().getFullYear();
|
|
3
|
+
|
|
4
|
+
// (int) The current month starting from 1 - 12
|
|
5
|
+
// 1 => January, 12 => December
|
|
6
|
+
export const THIS_MONTH = +new Date().getMonth() + 1;
|
|
7
|
+
// Week days names and shortnames
|
|
8
|
+
|
|
9
|
+
export const HOURS24 = [...new Array(24)].map((n, index) => {
|
|
10
|
+
return {
|
|
11
|
+
value: index,
|
|
12
|
+
label: index < 10 ? `0${index}` : `${index}`,
|
|
13
|
+
};
|
|
14
|
+
// return index < 10 ? `0${index}` : `${index}`;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const HOURS12 = [
|
|
18
|
+
...[...new Array(12)].map((n, index) => {
|
|
19
|
+
return {
|
|
20
|
+
value: index,
|
|
21
|
+
label: index < 10 ? `0${index} AM` : `${index} AM`,
|
|
22
|
+
};
|
|
23
|
+
}),
|
|
24
|
+
...[...new Array(12)].map((n, index) => {
|
|
25
|
+
return {
|
|
26
|
+
value: index + 12,
|
|
27
|
+
label: index < 10 ? `0${index} PM` : `${index} PM`,
|
|
28
|
+
};
|
|
29
|
+
}),
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
export const MINUTES = new Array(60).fill(0).map((n, index) => {
|
|
33
|
+
return index < 10 ? `0${index}` : index;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const WEEK_DAYS = {
|
|
37
|
+
Sunday: "Su",
|
|
38
|
+
Monday: "Mo",
|
|
39
|
+
Tuesday: "Tu",
|
|
40
|
+
Wednesday: "We",
|
|
41
|
+
Thursday: "Th",
|
|
42
|
+
Friday: "Fr",
|
|
43
|
+
Saturday: "Sa",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Calendar months names and short names
|
|
47
|
+
export const CALENDAR_MONTHS = {
|
|
48
|
+
January: "Jan",
|
|
49
|
+
February: "Feb",
|
|
50
|
+
March: "Mar",
|
|
51
|
+
April: "Apr",
|
|
52
|
+
May: "May",
|
|
53
|
+
June: "Jun",
|
|
54
|
+
July: "Jul",
|
|
55
|
+
August: "Aug",
|
|
56
|
+
September: "Sep",
|
|
57
|
+
October: "Oct",
|
|
58
|
+
November: "Nov",
|
|
59
|
+
December: "Dec",
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Weeks displayed on calendar
|
|
63
|
+
export const CALENDAR_WEEKS = 6;
|
|
64
|
+
|
|
65
|
+
// Pads a string value with leading zeroes(0) until length is reached
|
|
66
|
+
// For example: zeroPad(5, 2) => "05"
|
|
67
|
+
export const zeroPad = (value, length) => {
|
|
68
|
+
return `${value}`.padStart(length, "0");
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// (int) Number days in a month for a given year from 28 - 31
|
|
72
|
+
export const getMonthDays = (month = THIS_MONTH, year = THIS_YEAR) => {
|
|
73
|
+
const months30 = [4, 6, 9, 11];
|
|
74
|
+
const leapYear = year % 4 === 0;
|
|
75
|
+
return month === 2
|
|
76
|
+
? leapYear
|
|
77
|
+
? 29
|
|
78
|
+
: 28
|
|
79
|
+
: months30.includes(month)
|
|
80
|
+
? 30
|
|
81
|
+
: 31;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// (int) First day of the month for a given year from 1 - 7
|
|
85
|
+
// 1 => Sunday, 7 => Saturday
|
|
86
|
+
export const getMonthFirstDay = (month = THIS_MONTH, year = THIS_YEAR) => {
|
|
87
|
+
return +new Date(`${year}-${zeroPad(month, 2)}-01`).getDay() + 1;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// (bool) Checks if a value is a date - this is just a simple check
|
|
91
|
+
export const isDate = (date) => {
|
|
92
|
+
const isDate = Object.prototype.toString.call(date) === "[object Date]";
|
|
93
|
+
const isValidDate = date && !Number.isNaN(date.valueOf());
|
|
94
|
+
|
|
95
|
+
return isDate && isValidDate;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// (bool) Checks if two date values are of the same month and year
|
|
99
|
+
export const isSameMonth = (date, basedate = new Date()) => {
|
|
100
|
+
if (!(isDate(date) && isDate(basedate))) return false;
|
|
101
|
+
const basedateMonth = +basedate.getMonth() + 1;
|
|
102
|
+
const basedateYear = basedate.getFullYear();
|
|
103
|
+
const dateMonth = +date.getMonth() + 1;
|
|
104
|
+
const dateYear = date.getFullYear();
|
|
105
|
+
return +basedateMonth === +dateMonth && +basedateYear === +dateYear;
|
|
106
|
+
};
|
|
107
|
+
// (bool) Checks if two date values are the same day
|
|
108
|
+
export const isSameDay = (date, basedate = new Date()) => {
|
|
109
|
+
if (!(isDate(date) && isDate(basedate))) return false;
|
|
110
|
+
const basedateDate = basedate.getDate();
|
|
111
|
+
const basedateMonth = +basedate.getMonth() + 1;
|
|
112
|
+
const basedateYear = basedate.getFullYear();
|
|
113
|
+
const dateDate = date.getDate();
|
|
114
|
+
const dateMonth = +date.getMonth() + 1;
|
|
115
|
+
const dateYear = date.getFullYear();
|
|
116
|
+
return (
|
|
117
|
+
+basedateDate === +dateDate &&
|
|
118
|
+
+basedateMonth === +dateMonth &&
|
|
119
|
+
+basedateYear === +dateYear
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
// (string) Formats the given date as YYYY-MM-DD
|
|
123
|
+
// Months and Days are zero padded
|
|
124
|
+
export const getDateISO = (date = new Date()) => {
|
|
125
|
+
if (!isDate(date)) return null;
|
|
126
|
+
return [
|
|
127
|
+
date.getFullYear(),
|
|
128
|
+
zeroPad(+date.getMonth() + 1, 2),
|
|
129
|
+
zeroPad(+date.getDate(), 2),
|
|
130
|
+
].join("-");
|
|
131
|
+
};
|
|
132
|
+
// ({month, year}) Gets the month and year before the given month and year
|
|
133
|
+
// For example: getPreviousMonth(1, 2000) => {month: 12, year: 1999}
|
|
134
|
+
// while: getPreviousMonth(12, 2000) => {month: 11, year: 2000}
|
|
135
|
+
export const getPreviousMonth = (month, year) => {
|
|
136
|
+
const prevMonth = month > 1 ? month - 1 : 12;
|
|
137
|
+
const prevMonthYear = month > 1 ? year : year - 1;
|
|
138
|
+
return { month: prevMonth, year: prevMonthYear };
|
|
139
|
+
};
|
|
140
|
+
// ({month, year}) Gets the month and year after the given month and year
|
|
141
|
+
// For example: getNextMonth(1, 2000) => {month: 2, year: 2000}
|
|
142
|
+
// while: getNextMonth(12, 2000) => {month: 1, year: 2001}
|
|
143
|
+
export const getNextMonth = (month, year) => {
|
|
144
|
+
const nextMonth = month < 12 ? month + 1 : 1;
|
|
145
|
+
const nextMonthYear = month < 12 ? year : year + 1;
|
|
146
|
+
return { month: nextMonth, year: nextMonthYear };
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Calendar builder for a month in the specified year
|
|
150
|
+
// Returns an array of the calendar dates.
|
|
151
|
+
// Each calendar date is represented as an array => [YYYY, MM, DD]
|
|
152
|
+
const calendarBuilder = (month = THIS_MONTH, year = THIS_YEAR) => {
|
|
153
|
+
// Get number of days in the month and the month's first day
|
|
154
|
+
|
|
155
|
+
const monthDays = getMonthDays(month, year);
|
|
156
|
+
const monthFirstDay = getMonthFirstDay(month, year);
|
|
157
|
+
// Get number of days to be displayed from previous and next months
|
|
158
|
+
// These ensure a total of 42 days (6 weeks) displayed on the calendar
|
|
159
|
+
|
|
160
|
+
const daysFromPrevMonth = monthFirstDay - 1;
|
|
161
|
+
const daysFromNextMonth =
|
|
162
|
+
CALENDAR_WEEKS * 7 - (daysFromPrevMonth + monthDays);
|
|
163
|
+
// Get the previous and next months and years
|
|
164
|
+
|
|
165
|
+
const { month: prevMonth, year: prevMonthYear } = getPreviousMonth(
|
|
166
|
+
month,
|
|
167
|
+
year
|
|
168
|
+
);
|
|
169
|
+
const { month: nextMonth, year: nextMonthYear } = getNextMonth(month, year);
|
|
170
|
+
// Get number of days in previous month
|
|
171
|
+
const prevMonthDays = getMonthDays(prevMonth, prevMonthYear);
|
|
172
|
+
// Builds dates to be displayed from previous month
|
|
173
|
+
|
|
174
|
+
const prevMonthDates = [...new Array(daysFromPrevMonth)].map((n, index) => {
|
|
175
|
+
const day = index + 1 + (prevMonthDays - daysFromPrevMonth);
|
|
176
|
+
return [prevMonthYear, zeroPad(prevMonth, 2), zeroPad(day, 2)];
|
|
177
|
+
});
|
|
178
|
+
// Builds dates to be displayed from current month
|
|
179
|
+
|
|
180
|
+
const thisMonthDates = [...new Array(monthDays)].map((n, index) => {
|
|
181
|
+
const day = index + 1;
|
|
182
|
+
return [year, zeroPad(month, 2), zeroPad(day, 2)];
|
|
183
|
+
});
|
|
184
|
+
// Builds dates to be displayed from next month
|
|
185
|
+
|
|
186
|
+
const nextMonthDates = [...new Array(daysFromNextMonth)].map((n, index) => {
|
|
187
|
+
const day = index + 1;
|
|
188
|
+
return [nextMonthYear, zeroPad(nextMonth, 2), zeroPad(day, 2)];
|
|
189
|
+
});
|
|
190
|
+
// Combines all dates from previous, current and next months
|
|
191
|
+
return [...prevMonthDates, ...thisMonthDates, ...nextMonthDates];
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export default calendarBuilder;
|