@lafarmer28/densitycalendarnative 0.1.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.
Files changed (90) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +37 -0
  3. package/lib/module/components/density-calendar/context/ks-density-calendar-context.js +5 -0
  4. package/lib/module/components/density-calendar/context/ks-density-calendar-context.js.map +1 -0
  5. package/lib/module/components/density-calendar/context/ks-density-calendar-provider.js +68 -0
  6. package/lib/module/components/density-calendar/context/ks-density-calendar-provider.js.map +1 -0
  7. package/lib/module/components/density-calendar/context/use-ks-density-calendar-context.js +12 -0
  8. package/lib/module/components/density-calendar/context/use-ks-density-calendar-context.js.map +1 -0
  9. package/lib/module/components/density-calendar/day-view/day-navigation.js +172 -0
  10. package/lib/module/components/density-calendar/day-view/day-navigation.js.map +1 -0
  11. package/lib/module/components/density-calendar/day-view/ks-density-calendar-day-view.js +183 -0
  12. package/lib/module/components/density-calendar/day-view/ks-density-calendar-day-view.js.map +1 -0
  13. package/lib/module/components/density-calendar/ks-density-calendar-root.js +201 -0
  14. package/lib/module/components/density-calendar/ks-density-calendar-root.js.map +1 -0
  15. package/lib/module/components/density-calendar/ks-density-calendar.js +24 -0
  16. package/lib/module/components/density-calendar/ks-density-calendar.js.map +1 -0
  17. package/lib/module/components/density-calendar/ks-error-popup/ks-error-tooltip.js +74 -0
  18. package/lib/module/components/density-calendar/ks-error-popup/ks-error-tooltip.js.map +1 -0
  19. package/lib/module/components/density-calendar/ks-slider/ks-slider.js +174 -0
  20. package/lib/module/components/density-calendar/ks-slider/ks-slider.js.map +1 -0
  21. package/lib/module/components/density-calendar/ks-toggler/ks-toggler.js +72 -0
  22. package/lib/module/components/density-calendar/ks-toggler/ks-toggler.js.map +1 -0
  23. package/lib/module/components/density-calendar/month-view/days-of-week.js +51 -0
  24. package/lib/module/components/density-calendar/month-view/days-of-week.js.map +1 -0
  25. package/lib/module/components/density-calendar/month-view/ks-density-calendar-month-view.js +212 -0
  26. package/lib/module/components/density-calendar/month-view/ks-density-calendar-month-view.js.map +1 -0
  27. package/lib/module/components/density-calendar/month-view/top-navigation.js +118 -0
  28. package/lib/module/components/density-calendar/month-view/top-navigation.js.map +1 -0
  29. package/lib/module/components/density-calendar/utility-functions.js +50 -0
  30. package/lib/module/components/density-calendar/utility-functions.js.map +1 -0
  31. package/lib/module/components/density-calendar/week-view/ks-density-calendar-week-view.js +152 -0
  32. package/lib/module/components/density-calendar/week-view/ks-density-calendar-week-view.js.map +1 -0
  33. package/lib/module/components/density-calendar/week-view/top.js +53 -0
  34. package/lib/module/components/density-calendar/week-view/top.js.map +1 -0
  35. package/lib/module/index.js +4 -0
  36. package/lib/module/index.js.map +1 -0
  37. package/lib/module/package.json +1 -0
  38. package/lib/typescript/package.json +1 -0
  39. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-context.d.ts +17 -0
  40. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-context.d.ts.map +1 -0
  41. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-provider.d.ts +19 -0
  42. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-provider.d.ts.map +1 -0
  43. package/lib/typescript/src/components/density-calendar/context/use-ks-density-calendar-context.d.ts +2 -0
  44. package/lib/typescript/src/components/density-calendar/context/use-ks-density-calendar-context.d.ts.map +1 -0
  45. package/lib/typescript/src/components/density-calendar/day-view/day-navigation.d.ts +17 -0
  46. package/lib/typescript/src/components/density-calendar/day-view/day-navigation.d.ts.map +1 -0
  47. package/lib/typescript/src/components/density-calendar/day-view/ks-density-calendar-day-view.d.ts +21 -0
  48. package/lib/typescript/src/components/density-calendar/day-view/ks-density-calendar-day-view.d.ts.map +1 -0
  49. package/lib/typescript/src/components/density-calendar/ks-density-calendar-root.d.ts +14 -0
  50. package/lib/typescript/src/components/density-calendar/ks-density-calendar-root.d.ts.map +1 -0
  51. package/lib/typescript/src/components/density-calendar/ks-density-calendar.d.ts +43 -0
  52. package/lib/typescript/src/components/density-calendar/ks-density-calendar.d.ts.map +1 -0
  53. package/lib/typescript/src/components/density-calendar/ks-error-popup/ks-error-tooltip.d.ts +8 -0
  54. package/lib/typescript/src/components/density-calendar/ks-error-popup/ks-error-tooltip.d.ts.map +1 -0
  55. package/lib/typescript/src/components/density-calendar/ks-slider/ks-slider.d.ts +8 -0
  56. package/lib/typescript/src/components/density-calendar/ks-slider/ks-slider.d.ts.map +1 -0
  57. package/lib/typescript/src/components/density-calendar/ks-toggler/ks-toggler.d.ts +3 -0
  58. package/lib/typescript/src/components/density-calendar/ks-toggler/ks-toggler.d.ts.map +1 -0
  59. package/lib/typescript/src/components/density-calendar/month-view/days-of-week.d.ts +3 -0
  60. package/lib/typescript/src/components/density-calendar/month-view/days-of-week.d.ts.map +1 -0
  61. package/lib/typescript/src/components/density-calendar/month-view/ks-density-calendar-month-view.d.ts +17 -0
  62. package/lib/typescript/src/components/density-calendar/month-view/ks-density-calendar-month-view.d.ts.map +1 -0
  63. package/lib/typescript/src/components/density-calendar/month-view/top-navigation.d.ts +11 -0
  64. package/lib/typescript/src/components/density-calendar/month-view/top-navigation.d.ts.map +1 -0
  65. package/lib/typescript/src/components/density-calendar/utility-functions.d.ts +9 -0
  66. package/lib/typescript/src/components/density-calendar/utility-functions.d.ts.map +1 -0
  67. package/lib/typescript/src/components/density-calendar/week-view/ks-density-calendar-week-view.d.ts +12 -0
  68. package/lib/typescript/src/components/density-calendar/week-view/ks-density-calendar-week-view.d.ts.map +1 -0
  69. package/lib/typescript/src/components/density-calendar/week-view/top.d.ts +6 -0
  70. package/lib/typescript/src/components/density-calendar/week-view/top.d.ts.map +1 -0
  71. package/lib/typescript/src/index.d.ts +2 -0
  72. package/lib/typescript/src/index.d.ts.map +1 -0
  73. package/package.json +166 -0
  74. package/src/components/density-calendar/context/ks-density-calendar-context.tsx +23 -0
  75. package/src/components/density-calendar/context/ks-density-calendar-provider.tsx +96 -0
  76. package/src/components/density-calendar/context/use-ks-density-calendar-context.tsx +15 -0
  77. package/src/components/density-calendar/day-view/day-navigation.tsx +199 -0
  78. package/src/components/density-calendar/day-view/ks-density-calendar-day-view.tsx +245 -0
  79. package/src/components/density-calendar/ks-density-calendar-root.tsx +215 -0
  80. package/src/components/density-calendar/ks-density-calendar.tsx +74 -0
  81. package/src/components/density-calendar/ks-error-popup/ks-error-tooltip.tsx +71 -0
  82. package/src/components/density-calendar/ks-slider/ks-slider.tsx +185 -0
  83. package/src/components/density-calendar/ks-toggler/ks-toggler.tsx +69 -0
  84. package/src/components/density-calendar/month-view/days-of-week.tsx +47 -0
  85. package/src/components/density-calendar/month-view/ks-density-calendar-month-view.tsx +289 -0
  86. package/src/components/density-calendar/month-view/top-navigation.tsx +137 -0
  87. package/src/components/density-calendar/utility-functions.ts +67 -0
  88. package/src/components/density-calendar/week-view/ks-density-calendar-week-view.tsx +189 -0
  89. package/src/components/density-calendar/week-view/top.tsx +54 -0
  90. package/src/index.tsx +1 -0
@@ -0,0 +1,199 @@
1
+ import { StyleSheet, View, Text, Pressable } from 'react-native';
2
+ import { format } from 'date-fns';
3
+ import {
4
+ MaterialIcons,
5
+ MaterialCommunityIcons,
6
+ Ionicons,
7
+ } from '@expo/vector-icons';
8
+ import { useKSDensityCalendar } from '../context/use-ks-density-calendar-context';
9
+ import KSToggler from '../ks-toggler/ks-toggler';
10
+ import type { ThemeKeyProps } from '../ks-density-calendar';
11
+
12
+ type DayNavigationProps = {
13
+ handlePreviousDay: () => void;
14
+ dateSelected: Date;
15
+ handleNextDay: () => void;
16
+ handleToday: () => void;
17
+ previousCalendarDisplay: string;
18
+ toWeekHandler: () => void;
19
+ toMonthHandler: () => void;
20
+ themeKeys: ThemeKeyProps['themeKeys'];
21
+ svgIconColor: string;
22
+ svgIconSize: number;
23
+ svgIconUnactiveColor?: string;
24
+ };
25
+
26
+ const DayNavigation = ({
27
+ handlePreviousDay,
28
+ dateSelected,
29
+ handleNextDay,
30
+ handleToday,
31
+ previousCalendarDisplay,
32
+ toMonthHandler,
33
+ toWeekHandler,
34
+ svgIconColor,
35
+ svgIconSize,
36
+ svgIconUnactiveColor,
37
+ }: DayNavigationProps) => {
38
+ const { state } = useKSDensityCalendar();
39
+ const { isSmallScreen } = state;
40
+
41
+ const backHandler =
42
+ previousCalendarDisplay === 'Month' ? toMonthHandler : toWeekHandler;
43
+
44
+ // Helper for consistent Pressable styling
45
+ const pressableStyle = ({ pressed }: { pressed: boolean }) => [
46
+ styles.iconPressable,
47
+ { opacity: pressed ? 0.5 : 1 },
48
+ ];
49
+
50
+ return (
51
+ <View style={styles.container}>
52
+ {!isSmallScreen && (
53
+ <View style={styles.sideSection}>
54
+ <Pressable onPress={backHandler} style={pressableStyle}>
55
+ <Ionicons
56
+ name="arrow-back"
57
+ size={svgIconSize}
58
+ color={svgIconColor}
59
+ />
60
+ </Pressable>
61
+ </View>
62
+ )}
63
+
64
+ <View style={[styles.centerSection, isSmallScreen && styles.fullWidth]}>
65
+ <Pressable onPress={handlePreviousDay} style={pressableStyle}>
66
+ <MaterialIcons
67
+ name="chevron-left"
68
+ size={svgIconSize + 8}
69
+ color={svgIconColor}
70
+ />
71
+ </Pressable>
72
+
73
+ <Text style={styles.dateText}>
74
+ {format(
75
+ dateSelected,
76
+ previousCalendarDisplay === 'Week' ? 'EEEE' : 'eeee MMMM do yyyy'
77
+ )}
78
+ </Text>
79
+
80
+ <Pressable onPress={handleNextDay} style={pressableStyle}>
81
+ <MaterialIcons
82
+ name="chevron-right"
83
+ size={svgIconSize + 8}
84
+ color={svgIconColor}
85
+ />
86
+ </Pressable>
87
+ </View>
88
+
89
+ <View
90
+ style={[
91
+ styles.controlsSection,
92
+ isSmallScreen && styles.fullWidthCenter,
93
+ ]}
94
+ >
95
+ {isSmallScreen && (
96
+ <View style={styles.controlItem}>
97
+ <Pressable onPress={backHandler} style={pressableStyle}>
98
+ <Ionicons
99
+ name="arrow-back"
100
+ size={svgIconSize}
101
+ color={svgIconColor}
102
+ />
103
+ </Pressable>
104
+ </View>
105
+ )}
106
+
107
+ <View style={styles.controlItem}>
108
+ <MaterialCommunityIcons
109
+ name="minus"
110
+ size={svgIconSize}
111
+ color={svgIconUnactiveColor || svgIconColor}
112
+ />
113
+ </View>
114
+
115
+ <View style={styles.togglerWrapper}>
116
+ <KSToggler />
117
+ </View>
118
+
119
+ <View style={styles.controlItem}>
120
+ <MaterialCommunityIcons
121
+ name="plus"
122
+ size={svgIconSize}
123
+ color={svgIconUnactiveColor || svgIconColor}
124
+ />
125
+ </View>
126
+
127
+ {previousCalendarDisplay === 'Month' && (
128
+ <View style={styles.controlItem}>
129
+ <Pressable onPress={handleToday} style={pressableStyle}>
130
+ <MaterialCommunityIcons
131
+ name="calendar-today"
132
+ size={svgIconSize}
133
+ color={svgIconColor}
134
+ />
135
+ </Pressable>
136
+ </View>
137
+ )}
138
+ </View>
139
+ </View>
140
+ );
141
+ };
142
+
143
+ const styles = StyleSheet.create({
144
+ container: {
145
+ width: '100%',
146
+ flexDirection: 'row',
147
+ flexWrap: 'wrap',
148
+ alignItems: 'center',
149
+ paddingVertical: 10,
150
+ },
151
+ sideSection: {
152
+ width: '25%',
153
+ flexDirection: 'row',
154
+ justifyContent: 'flex-start',
155
+ paddingLeft: 8,
156
+ },
157
+ centerSection: {
158
+ width: '50%',
159
+ flexDirection: 'row',
160
+ justifyContent: 'center',
161
+ alignItems: 'center',
162
+ },
163
+ fullWidth: {
164
+ width: '100%',
165
+ },
166
+ fullWidthCenter: {
167
+ width: '100%',
168
+ justifyContent: 'center',
169
+ marginTop: 15,
170
+ },
171
+ dateText: {
172
+ fontSize: 18,
173
+ fontWeight: '600',
174
+ textAlign: 'center',
175
+ paddingHorizontal: 4,
176
+ flexShrink: 1,
177
+ },
178
+ iconPressable: {
179
+ padding: 8,
180
+ borderRadius: 20, // Optional: gives a nice hit area
181
+ justifyContent: 'center',
182
+ alignItems: 'center',
183
+ },
184
+ controlsSection: {
185
+ width: '25%',
186
+ flexDirection: 'row',
187
+ justifyContent: 'flex-end',
188
+ alignItems: 'center',
189
+ paddingRight: 8,
190
+ },
191
+ controlItem: {
192
+ paddingHorizontal: 4,
193
+ },
194
+ togglerWrapper: {
195
+ marginHorizontal: 4,
196
+ },
197
+ });
198
+
199
+ export default DayNavigation;
@@ -0,0 +1,245 @@
1
+ import { useMemo } from 'react';
2
+ import { StyleSheet, View, Text, ScrollView, DimensionValue } from 'react-native';
3
+ import { startOfDay, endOfDay, eachHourOfInterval } from 'date-fns';
4
+ import { useKSDensityCalendar } from '../context/use-ks-density-calendar-context';
5
+ import { getColorForPercentage } from '../utility-functions';
6
+ import DayNavigation from './day-navigation';
7
+ import KSSlider from '../ks-slider/ks-slider';
8
+ import {
9
+ type KSDensityCalendarEventType,
10
+ type ThemeKeyProps,
11
+ } from '../ks-density-calendar';
12
+
13
+ type KSDensityCalendarDayProps = {
14
+ dateSelected: Date;
15
+ multScheduleData: KSDensityCalendarEventType[];
16
+ toWeekHandler: () => void;
17
+ toMonthHandler: () => void;
18
+ previousCalendarDisplay: string;
19
+ handlePreviousDay: () => void;
20
+ handleNextDay: () => void;
21
+ handleToday: () => void;
22
+ calendarDisplay: string;
23
+ themeKeys: ThemeKeyProps['themeKeys'];
24
+ svgIconColor: string;
25
+ svgIconSize: number;
26
+ svgIconUnactiveColor?: string;
27
+ };
28
+
29
+ export const getHoursOfDayWithinIntersection = (
30
+ dateSelected: Date,
31
+ start: Date,
32
+ end: Date
33
+ ) => {
34
+ const startingHour = startOfDay(dateSelected);
35
+ const endingHour = endOfDay(dateSelected);
36
+ const effectiveStart = start < startingHour ? startingHour : start;
37
+ const effectiveEnd = end > endingHour ? endingHour : end;
38
+
39
+ const hoursWithinInterval = eachHourOfInterval({
40
+ start: effectiveStart,
41
+ end: effectiveEnd,
42
+ });
43
+ return hoursWithinInterval.map((ht) => ht.getHours());
44
+ };
45
+
46
+ export const calcHourPercents = (
47
+ dateSelected: Date,
48
+ data: KSDensityCalendarEventType[]
49
+ ) => {
50
+ const ret = Array(24).fill(0);
51
+ const usedNames: Record<string, number[]> = {};
52
+ const startDay = startOfDay(dateSelected);
53
+ const endDay = endOfDay(dateSelected);
54
+
55
+ for (const item of data) {
56
+ // Basic null check for the item itself
57
+ if (!item || item.start > endDay || item.end < startDay) continue;
58
+
59
+ const hours = getHoursOfDayWithinIntersection(
60
+ dateSelected,
61
+ item.start,
62
+ item.end
63
+ );
64
+
65
+ hours.forEach((hour) => {
66
+ if (!usedNames[item.name]) {
67
+ usedNames[item.name] = Array(24).fill(0);
68
+ }
69
+
70
+ const nameData = usedNames[item.name];
71
+
72
+ if (nameData && nameData[hour] === 0) {
73
+ nameData[hour] = 1;
74
+ ret[hour] += 1;
75
+ }
76
+ });
77
+ }
78
+
79
+ const totalNames = Object.keys(usedNames).length;
80
+ if (totalNames > 0) {
81
+ for (let j = 0; j < ret.length; j++) {
82
+ ret[j] = Math.round((ret[j] / totalNames) * 100);
83
+ }
84
+ }
85
+ return ret;
86
+ };
87
+
88
+ const KSDensityCalendarDayView = ({
89
+ dateSelected,
90
+ calendarDisplay,
91
+ multScheduleData,
92
+ toWeekHandler,
93
+ toMonthHandler,
94
+ previousCalendarDisplay,
95
+ handleToday,
96
+ handleNextDay,
97
+ handlePreviousDay,
98
+ themeKeys,
99
+ svgIconColor,
100
+ svgIconSize,
101
+ svgIconUnactiveColor,
102
+ }: KSDensityCalendarDayProps) => {
103
+ const { state } = useKSDensityCalendar();
104
+ const { toggleKSSlider, minVal, maxVal } = state;
105
+
106
+ const percentsForHourOfDay = useMemo(
107
+ () => calcHourPercents(dateSelected, multScheduleData),
108
+ [dateSelected, multScheduleData]
109
+ );
110
+
111
+ const renderHourRow = (percentValue: number, index: number) => {
112
+ const isVisible = percentValue >= minVal && percentValue <= maxVal;
113
+ const barWidth = isVisible ? `${percentValue}%` : '0%';
114
+ const color = getColorForPercentage(percentValue);
115
+
116
+ const hourLabel =
117
+ index === 0
118
+ ? '12am'
119
+ : index === 12
120
+ ? '12pm'
121
+ : index < 12
122
+ ? `${index}am`
123
+ : `${index - 12}pm`;
124
+
125
+ return (
126
+ <View
127
+ key={index}
128
+ style={[
129
+ styles.row,
130
+ { borderColor: themeKeys.secondaryColor },
131
+ index === 23 && styles.lastRow,
132
+ ]}
133
+ >
134
+ <View style={styles.labelContainer}>
135
+ <Text style={styles.labelText}>{hourLabel}:</Text>
136
+ </View>
137
+
138
+ <View style={styles.barTrack}>
139
+ <View
140
+ style={[
141
+ styles.barFill,
142
+ {
143
+ // Force cast the string to DimensionValue
144
+ width: (isVisible
145
+ ? `${percentValue}%`
146
+ : '0%') as DimensionValue,
147
+ backgroundColor: isVisible ? color : 'transparent',
148
+ },
149
+ ]}
150
+ />
151
+ </View>
152
+
153
+ <Text style={styles.percentText}>
154
+ {isVisible && percentValue > 0 ? `${percentValue}%` : ''}
155
+ </Text>
156
+ </View>
157
+ );
158
+ };
159
+
160
+ return (
161
+ <View style={[styles.container, !toggleKSSlider && styles.paddingBottom]}>
162
+ <DayNavigation
163
+ dateSelected={dateSelected}
164
+ handleNextDay={handleNextDay}
165
+ handlePreviousDay={handlePreviousDay}
166
+ previousCalendarDisplay={previousCalendarDisplay}
167
+ toWeekHandler={toWeekHandler}
168
+ toMonthHandler={toMonthHandler}
169
+ handleToday={handleToday}
170
+ themeKeys={themeKeys}
171
+ svgIconColor={svgIconColor}
172
+ svgIconSize={svgIconSize}
173
+ svgIconUnactiveColor={svgIconUnactiveColor}
174
+ />
175
+
176
+ <ScrollView
177
+ style={styles.scrollArea}
178
+ contentContainerStyle={styles.scrollContent}
179
+ persistentScrollbar={true}
180
+ indicatorStyle="default"
181
+ >
182
+ {percentsForHourOfDay.map(renderHourRow)}
183
+ </ScrollView>
184
+
185
+ {toggleKSSlider && (
186
+ <KSSlider calendarDisplay={calendarDisplay} themeKeys={themeKeys} />
187
+ )}
188
+ </View>
189
+ );
190
+ };
191
+
192
+ const styles = StyleSheet.create({
193
+ container: {
194
+ flex: 1,
195
+ width: '100%',
196
+ paddingHorizontal: 8,
197
+ },
198
+ paddingBottom: {
199
+ paddingBottom: 8,
200
+ },
201
+ scrollArea: {
202
+ flex: 1,
203
+ width: '100%',
204
+ },
205
+ scrollContent: {
206
+ paddingVertical: 4,
207
+ },
208
+ row: {
209
+ flexDirection: 'row',
210
+ alignItems: 'center',
211
+ paddingLeft: 4,
212
+ height: 40,
213
+ borderTopWidth: 2,
214
+ borderLeftWidth: 2,
215
+ borderRightWidth: 2,
216
+ },
217
+ lastRow: {
218
+ borderBottomWidth: 2,
219
+ },
220
+ labelContainer: {
221
+ width: 60,
222
+ },
223
+ labelText: {
224
+ fontSize: 14,
225
+ fontWeight: '500',
226
+ },
227
+ barTrack: {
228
+ flex: 1,
229
+ height: '60%',
230
+ marginHorizontal: 8,
231
+ justifyContent: 'center',
232
+ },
233
+ barFill: {
234
+ height: '100%',
235
+ borderRadius: 2,
236
+ },
237
+ percentText: {
238
+ width: 45,
239
+ fontSize: 12,
240
+ textAlign: 'right',
241
+ paddingRight: 4,
242
+ },
243
+ });
244
+
245
+ export default KSDensityCalendarDayView;
@@ -0,0 +1,215 @@
1
+ import { useReducer, useEffect } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+ import { subMonths, addMonths, addDays, subDays, startOfToday } from 'date-fns';
4
+ import { firstDateOfWeek } from './utility-functions';
5
+ import KSDensityCalendarMonthView from './month-view/ks-density-calendar-month-view';
6
+ import KSDensityCalendarWeekView from './week-view/ks-density-calendar-week-view';
7
+ import KSDensityCalendarDayView from './day-view/ks-density-calendar-day-view';
8
+ import type { ThemeKeyProps } from './ks-density-calendar';
9
+
10
+ export type KSDensityCalendarProps = {
11
+ displayDate: Date;
12
+ initialDisplayMode: 'Month' | 'Week' | 'Day';
13
+ multScheduleData: any[];
14
+ };
15
+
16
+ type CalendarState = {
17
+ calendarDisplay: string;
18
+ displayDate: Date;
19
+ dateSelected: Date;
20
+ previousCalendarDisplay: string;
21
+ };
22
+
23
+ type CalendarAction =
24
+ | { type: 'SET_CALENDAR_DISPLAY'; payload: string }
25
+ | { type: 'SET_DISPLAY_DATE'; payload: Date }
26
+ | { type: 'SET_DATE_SELECTED'; payload: Date }
27
+ | { type: 'SET_PREVIOUS_CALENDAR_DISPLAY'; payload: string };
28
+
29
+ export type SVGProps = {
30
+ svgIconColor: string;
31
+ svgIconSize: number;
32
+ svgIconUnactiveColor?: string;
33
+ };
34
+
35
+ const calendarReducer = (
36
+ state: CalendarState,
37
+ action: CalendarAction
38
+ ): CalendarState => {
39
+ switch (action.type) {
40
+ case 'SET_CALENDAR_DISPLAY':
41
+ return { ...state, calendarDisplay: action.payload };
42
+ case 'SET_DISPLAY_DATE':
43
+ return { ...state, displayDate: action.payload };
44
+ case 'SET_DATE_SELECTED':
45
+ return { ...state, dateSelected: action.payload };
46
+ case 'SET_PREVIOUS_CALENDAR_DISPLAY':
47
+ return { ...state, previousCalendarDisplay: action.payload };
48
+ default:
49
+ return state;
50
+ }
51
+ };
52
+
53
+ const KSDensityCalendarRoot = ({
54
+ displayDate,
55
+ initialDisplayMode,
56
+ multScheduleData,
57
+ themeKeys,
58
+ }: KSDensityCalendarProps & ThemeKeyProps) => {
59
+ const initialState: CalendarState = {
60
+ calendarDisplay: initialDisplayMode,
61
+ displayDate: displayDate,
62
+ dateSelected: displayDate,
63
+ previousCalendarDisplay: initialDisplayMode,
64
+ };
65
+
66
+ const [state, dispatch] = useReducer(calendarReducer, initialState);
67
+
68
+ useEffect(() => {
69
+ dispatch({
70
+ type: 'SET_PREVIOUS_CALENDAR_DISPLAY',
71
+ payload: initialDisplayMode,
72
+ });
73
+ }, [initialDisplayMode]);
74
+
75
+ const handlePreviousMonth = () => {
76
+ dispatch({
77
+ type: 'SET_DISPLAY_DATE',
78
+ payload: subMonths(state.displayDate, 1),
79
+ });
80
+ };
81
+
82
+ const handleNextMonth = () => {
83
+ dispatch({
84
+ type: 'SET_DISPLAY_DATE',
85
+ payload: addMonths(state.displayDate, 1),
86
+ });
87
+ };
88
+
89
+ const handlePreviousDay = () => {
90
+ const isMonthOrDay =
91
+ state.previousCalendarDisplay === 'Month' ||
92
+ state.previousCalendarDisplay === 'Day';
93
+
94
+ if (isMonthOrDay) {
95
+ dispatch({
96
+ type: 'SET_DATE_SELECTED',
97
+ payload: subDays(state.dateSelected, 1),
98
+ });
99
+ } else if (state.previousCalendarDisplay === 'Week') {
100
+ const previousDay = subDays(state.dateSelected, 1);
101
+ if (previousDay >= firstDateOfWeek) {
102
+ dispatch({ type: 'SET_DATE_SELECTED', payload: previousDay });
103
+ } else {
104
+ dispatch({
105
+ type: 'SET_DATE_SELECTED',
106
+ payload: addDays(firstDateOfWeek, 6),
107
+ });
108
+ }
109
+ }
110
+ };
111
+
112
+ const handleNextDay = () => {
113
+ const isMonthOrDay =
114
+ state.previousCalendarDisplay === 'Month' ||
115
+ state.previousCalendarDisplay === 'Day';
116
+
117
+ if (isMonthOrDay) {
118
+ dispatch({
119
+ type: 'SET_DATE_SELECTED',
120
+ payload: addDays(state.dateSelected, 1),
121
+ });
122
+ } else if (state.previousCalendarDisplay === 'Week') {
123
+ const nextDay = addDays(state.dateSelected, 1);
124
+ if (nextDay <= addDays(firstDateOfWeek, 6)) {
125
+ dispatch({ type: 'SET_DATE_SELECTED', payload: nextDay });
126
+ } else {
127
+ dispatch({ type: 'SET_DATE_SELECTED', payload: firstDateOfWeek });
128
+ }
129
+ }
130
+ };
131
+
132
+ const handleToday = () => {
133
+ const today = startOfToday();
134
+ if (state.calendarDisplay === 'Month') {
135
+ dispatch({ type: 'SET_DISPLAY_DATE', payload: today });
136
+ } else {
137
+ dispatch({ type: 'SET_DATE_SELECTED', payload: today });
138
+ }
139
+ };
140
+
141
+ const toMonthHandler = () => {
142
+ dispatch({ type: 'SET_DISPLAY_DATE', payload: state.dateSelected });
143
+ dispatch({ type: 'SET_CALENDAR_DISPLAY', payload: 'Month' });
144
+ };
145
+
146
+ const toDayHandler = (dt: Date) => {
147
+ dispatch({ type: 'SET_DATE_SELECTED', payload: dt });
148
+ dispatch({ type: 'SET_CALENDAR_DISPLAY', payload: 'Day' });
149
+ };
150
+
151
+ const toWeekHandler = () => {
152
+ dispatch({ type: 'SET_CALENDAR_DISPLAY', payload: 'Week' });
153
+ };
154
+
155
+ const svgIconColor = themeKeys.secondaryColor;
156
+ const svgIconSize = 32;
157
+ const svgIconUnactiveColor = themeKeys.secondaryColorPnt15;
158
+
159
+ return (
160
+ <View style={styles.container}>
161
+ {state.calendarDisplay === 'Month' && (
162
+ <KSDensityCalendarMonthView
163
+ displayDate={state.displayDate}
164
+ toDayHandler={toDayHandler}
165
+ multScheduleData={multScheduleData}
166
+ handlePrevious={handlePreviousMonth}
167
+ handleNext={handleNextMonth}
168
+ handleToday={handleToday}
169
+ calendarDisplay={state.calendarDisplay}
170
+ themeKeys={themeKeys}
171
+ svgIconColor={svgIconColor}
172
+ svgIconSize={svgIconSize}
173
+ svgIconUnactiveColor={svgIconUnactiveColor}
174
+ />
175
+ )}
176
+ {state.calendarDisplay === 'Week' && (
177
+ <KSDensityCalendarWeekView
178
+ displayDate={state.displayDate}
179
+ toDayHandler={toDayHandler}
180
+ multScheduleData={multScheduleData}
181
+ calendarDisplay={state.calendarDisplay}
182
+ themeKeys={themeKeys}
183
+ svgIconColor={svgIconColor}
184
+ svgIconSize={svgIconSize}
185
+ svgIconUnactiveColor={svgIconUnactiveColor}
186
+ />
187
+ )}
188
+ {state.calendarDisplay === 'Day' && (
189
+ <KSDensityCalendarDayView
190
+ dateSelected={state.dateSelected}
191
+ multScheduleData={multScheduleData}
192
+ toWeekHandler={toWeekHandler}
193
+ toMonthHandler={toMonthHandler}
194
+ previousCalendarDisplay={state.previousCalendarDisplay}
195
+ handlePreviousDay={handlePreviousDay}
196
+ handleNextDay={handleNextDay}
197
+ handleToday={handleToday}
198
+ calendarDisplay={state.calendarDisplay}
199
+ themeKeys={themeKeys}
200
+ svgIconColor={svgIconColor}
201
+ svgIconSize={svgIconSize}
202
+ svgIconUnactiveColor={svgIconUnactiveColor}
203
+ />
204
+ )}
205
+ </View>
206
+ );
207
+ };
208
+
209
+ const styles = StyleSheet.create({
210
+ container: {
211
+ flex: 1,
212
+ },
213
+ });
214
+
215
+ export default KSDensityCalendarRoot;