-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathuse-weekview.ts
116 lines (106 loc) · 2.99 KB
/
use-weekview.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { useState } from "react";
import {
addDays,
eachDayOfInterval,
eachMinuteOfInterval,
endOfDay,
startOfDay,
startOfWeek,
isToday,
format,
Day,
Locale,
isSameMonth,
isSameYear,
} from "date-fns";
export default function useWeekView({
initialDate,
minuteStep = 30,
weekStartsOn = 1,
locale,
disabledCell,
disabledDay,
disabledWeek,
}:
| {
initialDate?: Date;
minuteStep?: number;
weekStartsOn?: Day;
locale?: Locale;
disabledCell?: (date: Date) => boolean;
disabledDay?: (date: Date) => boolean;
disabledWeek?: (startDayOfWeek: Date) => boolean;
}
| undefined = {}) {
const [startOfTheWeek, setStartOfTheWeek] = useState(
startOfWeek(startOfDay(initialDate || new Date()), { weekStartsOn })
);
const nextWeek = () => {
const nextWeek = addDays(startOfTheWeek, 7);
if (disabledWeek && disabledWeek(nextWeek)) return;
setStartOfTheWeek(nextWeek);
};
const previousWeek = () => {
const previousWeek = addDays(startOfTheWeek, -7);
if (disabledWeek && disabledWeek(previousWeek)) return;
setStartOfTheWeek(previousWeek);
};
const goToToday = () => {
setStartOfTheWeek(startOfWeek(startOfDay(new Date()), { weekStartsOn }));
};
const days = eachDayOfInterval({
start: startOfTheWeek,
end: addDays(startOfTheWeek, 6),
}).map((day) => ({
date: day,
isToday: isToday(day),
name: format(day, "EEEE", { locale }),
shortName: format(day, "EEE", { locale }),
dayOfMonth: format(day, "d", { locale }),
dayOfMonthWithZero: format(day, "dd", { locale }),
dayOfMonthWithSuffix: format(day, "do", { locale }),
disabled: disabledDay ? disabledDay(day) : false,
cells: eachMinuteOfInterval(
{
start: startOfDay(day),
end: endOfDay(day),
},
{
step: minuteStep,
}
).map((hour) => ({
date: hour,
hour: format(hour, "HH", { locale }),
minute: format(hour, "mm", { locale }),
hourAndMinute: format(hour, "HH:mm", { locale }),
disabled: disabledCell ? disabledCell(hour) : false,
})),
}));
const isAllSameYear = isSameYear(days[0].date, days[days.length - 1].date);
const isAllSameMonth = isSameMonth(days[0].date, days[days.length - 1].date);
let viewTitle = "";
if (isAllSameMonth) viewTitle = format(days[0].date, "MMMM yyyy", { locale });
else if (isAllSameYear)
viewTitle = `${format(days[0].date, "MMM", { locale })} - ${format(
days[days.length - 1].date,
"MMM",
{ locale }
)} ${format(days[0].date, "yyyy", { locale })}`;
else
viewTitle = `${format(days[0].date, "MMM yyyy", { locale })} - ${format(
days[days.length - 1].date,
"MMM yyyy",
{ locale }
)}`;
const weekNumber = format(days[0].date, "w", { locale });
return {
nextWeek,
previousWeek,
goToToday,
days,
weekNumber,
viewTitle,
};
}
export type Days = ReturnType<typeof useWeekView>["days"];
export type Cell = Days[number]["cells"][number];