@adiraku/react-native-ui 1.2.8-canary-1 → 1.2.8-canary-2
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/lib/commonjs/components/TextInput/TextInput.component.js +45 -6
- package/lib/commonjs/components/TextInput/TextInput.component.js.map +1 -1
- package/lib/commonjs/components/calendars/calendars.component.js +215 -0
- package/lib/commonjs/components/calendars/calendars.component.js.map +1 -0
- package/lib/commonjs/components/calendars/calendars.service.js +68 -0
- package/lib/commonjs/components/calendars/calendars.service.js.map +1 -0
- package/lib/commonjs/components/calendars/calendars.style.js +126 -0
- package/lib/commonjs/components/calendars/calendars.style.js.map +1 -0
- package/lib/commonjs/components/calendars/calendars.type.js +14 -0
- package/lib/commonjs/components/calendars/calendars.type.js.map +1 -0
- package/lib/commonjs/components/calendars/month-picker-modal.component.js +104 -0
- package/lib/commonjs/components/calendars/month-picker-modal.component.js.map +1 -0
- package/lib/commonjs/components/index.js +7 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/components/typography/typography.style.js +181 -0
- package/lib/commonjs/components/typography/typography.style.js.map +1 -1
- package/lib/module/components/TextInput/TextInput.component.js +46 -7
- package/lib/module/components/TextInput/TextInput.component.js.map +1 -1
- package/lib/module/components/calendars/calendars.component.js +207 -0
- package/lib/module/components/calendars/calendars.component.js.map +1 -0
- package/lib/module/components/calendars/calendars.service.js +56 -0
- package/lib/module/components/calendars/calendars.service.js.map +1 -0
- package/lib/module/components/calendars/calendars.style.js +119 -0
- package/lib/module/components/calendars/calendars.style.js.map +1 -0
- package/lib/module/components/calendars/calendars.type.js +8 -0
- package/lib/module/components/calendars/calendars.type.js.map +1 -0
- package/lib/module/components/calendars/month-picker-modal.component.js +95 -0
- package/lib/module/components/calendars/month-picker-modal.component.js.map +1 -0
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/typography/typography.style.js +181 -0
- package/lib/module/components/typography/typography.style.js.map +1 -1
- package/lib/typescript/components/TextInput/TextInput.component.d.ts.map +1 -1
- package/lib/typescript/components/TextInput/TextInput.type.d.ts +7 -0
- package/lib/typescript/components/TextInput/TextInput.type.d.ts.map +1 -1
- package/lib/typescript/components/calendars/calendars.component.d.ts +8 -0
- package/lib/typescript/components/calendars/calendars.component.d.ts.map +1 -0
- package/lib/typescript/components/calendars/calendars.service.d.ts +9 -0
- package/lib/typescript/components/calendars/calendars.service.d.ts.map +1 -0
- package/lib/typescript/components/calendars/calendars.style.d.ts +20 -0
- package/lib/typescript/components/calendars/calendars.style.d.ts.map +1 -0
- package/lib/typescript/components/calendars/calendars.type.d.ts +26 -0
- package/lib/typescript/components/calendars/calendars.type.d.ts.map +1 -0
- package/lib/typescript/components/calendars/month-picker-modal.component.d.ts +15 -0
- package/lib/typescript/components/calendars/month-picker-modal.component.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/components/information-box/information-box.type.d.ts +13 -2
- package/lib/typescript/components/information-box/information-box.type.d.ts.map +1 -1
- package/lib/typescript/components/typography/typography.style.d.ts +28 -0
- package/lib/typescript/components/typography/typography.style.d.ts.map +1 -1
- package/lib/typescript/components/typography/typography.type.d.ts +4 -4
- package/lib/typescript/components/typography/typography.type.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/components/TextInput/TextInput.component.tsx +114 -50
- package/src/components/TextInput/TextInput.type.ts +11 -0
- package/src/components/calendars/calendars.component.tsx +296 -0
- package/src/components/calendars/calendars.service.ts +64 -0
- package/src/components/calendars/calendars.style.ts +148 -0
- package/src/components/calendars/calendars.type.tsx +57 -0
- package/src/components/calendars/month-picker-modal.component.tsx +137 -0
- package/src/components/index.ts +1 -0
- package/src/components/information-box/information-box.type.ts +13 -5
- package/src/components/typography/typography.style.tsx +243 -0
- package/src/components/typography/typography.type.ts +31 -3
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
3
|
+
import { Animated } from 'react-native';
|
|
4
|
+
import type {
|
|
5
|
+
GestureResponderEvent,
|
|
6
|
+
LayoutChangeEvent,
|
|
7
|
+
NativeSyntheticEvent,
|
|
8
|
+
TextInputFocusEventData,
|
|
9
|
+
} from 'react-native';
|
|
5
10
|
import MaskInput from 'react-native-mask-input';
|
|
11
|
+
|
|
12
|
+
import { getStyle } from './TextInput.style';
|
|
6
13
|
import { Typography } from '../typography/typography.component';
|
|
7
|
-
import {
|
|
14
|
+
import { Calendars } from '../calendars/calendars.component';
|
|
15
|
+
|
|
8
16
|
import { Palettes } from '../../themes';
|
|
9
|
-
import type {
|
|
10
|
-
import type { NativeSyntheticEvent } from 'react-native';
|
|
11
|
-
import type { TextInputFocusEventData } from 'react-native';
|
|
17
|
+
import type { TextInputProps } from './TextInput.type';
|
|
12
18
|
|
|
13
19
|
const TextInput: React.FunctionComponent<TextInputProps> = (props) => {
|
|
14
20
|
const {
|
|
@@ -22,12 +28,20 @@ const TextInput: React.FunctionComponent<TextInputProps> = (props) => {
|
|
|
22
28
|
isError,
|
|
23
29
|
counter = 0,
|
|
24
30
|
inputIcon = null,
|
|
31
|
+
onTouchStart,
|
|
32
|
+
showSoftInputOnFocus = true,
|
|
33
|
+
inputType = 'text',
|
|
34
|
+
calendarProps,
|
|
35
|
+
onChangeDate: onDateChange,
|
|
25
36
|
...rest
|
|
26
37
|
} = props;
|
|
27
38
|
|
|
28
39
|
const [labelWidth, setLabelWidth] = React.useState(0);
|
|
29
40
|
const [focused, setFocused] = React.useState(false);
|
|
30
41
|
|
|
42
|
+
// for date input
|
|
43
|
+
const [isModalDateVisible, setIsModalDateVisible] = React.useState(false);
|
|
44
|
+
|
|
31
45
|
const computedStyle = getStyle(props, focused);
|
|
32
46
|
|
|
33
47
|
const animation = React.useRef(new Animated.Value(0));
|
|
@@ -76,53 +90,103 @@ const TextInput: React.FunctionComponent<TextInputProps> = (props) => {
|
|
|
76
90
|
setLabelWidth(width + 24);
|
|
77
91
|
};
|
|
78
92
|
|
|
93
|
+
const computedValue = React.useMemo(() => {
|
|
94
|
+
if (inputType === 'date' && typeof value === 'object') {
|
|
95
|
+
const options: Intl.DateTimeFormatOptions = {
|
|
96
|
+
weekday: 'long',
|
|
97
|
+
day: '2-digit',
|
|
98
|
+
month: 'short',
|
|
99
|
+
year: 'numeric',
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const formattedDate = new Intl.DateTimeFormat('id-ID', options).format(
|
|
103
|
+
value
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Capitalize the first letter of the weekday and month for consistency with the example format.
|
|
107
|
+
return formattedDate.replace(/(^\w{1})|(\s\w{1})/g, (letter) =>
|
|
108
|
+
letter.toUpperCase()
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return value;
|
|
112
|
+
}, [value, inputType]);
|
|
113
|
+
|
|
114
|
+
const handleOnTouchStart = (e: GestureResponderEvent) => {
|
|
115
|
+
if (inputType === 'date') {
|
|
116
|
+
setIsModalDateVisible(true);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
onTouchStart?.(e);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const handleOnDateChangeSave = (date: Date) => {
|
|
123
|
+
onDateChange?.(date);
|
|
124
|
+
};
|
|
125
|
+
|
|
79
126
|
return (
|
|
80
|
-
|
|
81
|
-
<View style={computedStyle.
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{label}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
127
|
+
<>
|
|
128
|
+
<View style={computedStyle.fieldWrapper}>
|
|
129
|
+
<View style={computedStyle.fieldContainer}>
|
|
130
|
+
{!!label && (
|
|
131
|
+
<Animated.View
|
|
132
|
+
style={[
|
|
133
|
+
computedStyle.labelContainer,
|
|
134
|
+
{
|
|
135
|
+
transform: [{ scale }, { translateY }, { translateX }],
|
|
136
|
+
},
|
|
137
|
+
]}
|
|
138
|
+
onLayout={getLabelWidth}
|
|
139
|
+
pointerEvents="none"
|
|
140
|
+
>
|
|
141
|
+
<Typography variant="body2" style={computedStyle.label}>
|
|
142
|
+
{label}
|
|
143
|
+
</Typography>
|
|
144
|
+
</Animated.View>
|
|
145
|
+
)}
|
|
146
|
+
<View style={computedStyle.inputWrapper}>
|
|
147
|
+
<MaskInput
|
|
148
|
+
value={computedValue}
|
|
149
|
+
style={[computedStyle.textField]}
|
|
150
|
+
onFocus={handleOnFocus}
|
|
151
|
+
onBlur={handleOnBlur}
|
|
152
|
+
placeholderTextColor={
|
|
153
|
+
focused ? Palettes.black[500] : 'transparent'
|
|
154
|
+
}
|
|
155
|
+
showSoftInputOnFocus={
|
|
156
|
+
inputType === 'date' ? false : showSoftInputOnFocus
|
|
157
|
+
}
|
|
158
|
+
onTouchStart={handleOnTouchStart}
|
|
159
|
+
{...rest}
|
|
160
|
+
/>
|
|
161
|
+
{inputIcon || counter > 0
|
|
162
|
+
? inputIcon || (
|
|
163
|
+
<Typography style={computedStyle.counter} variant="caption">
|
|
164
|
+
{`${computedValue?.length}/${counter}`}
|
|
165
|
+
</Typography>
|
|
166
|
+
)
|
|
167
|
+
: null}
|
|
168
|
+
</View>
|
|
114
169
|
</View>
|
|
170
|
+
{errorMessage || helperMessage ? (
|
|
171
|
+
<Typography
|
|
172
|
+
variant="caption"
|
|
173
|
+
style={computedStyle.messageHelper}
|
|
174
|
+
{...helperMessageProps}
|
|
175
|
+
>
|
|
176
|
+
{errorMessage || ((!isError && helperMessage) as string)}
|
|
177
|
+
</Typography>
|
|
178
|
+
) : null}
|
|
115
179
|
</View>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
{
|
|
121
|
-
|
|
122
|
-
{
|
|
123
|
-
|
|
124
|
-
)
|
|
125
|
-
|
|
180
|
+
|
|
181
|
+
{inputType === 'date' && (
|
|
182
|
+
<Calendars
|
|
183
|
+
isVisible={isModalDateVisible}
|
|
184
|
+
onDateSave={handleOnDateChangeSave}
|
|
185
|
+
onDismiss={() => setIsModalDateVisible(false)}
|
|
186
|
+
{...calendarProps}
|
|
187
|
+
/>
|
|
188
|
+
)}
|
|
189
|
+
</>
|
|
126
190
|
);
|
|
127
191
|
};
|
|
128
192
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import { MaskInputProps } from 'react-native-mask-input';
|
|
3
3
|
import { TypographyProps } from '../typography/typography.type';
|
|
4
|
+
import { CalendarPropsAleph } from '../calendars/calendars.type';
|
|
4
5
|
|
|
5
6
|
export interface TextInputProps extends MaskInputProps {
|
|
6
7
|
/**
|
|
@@ -37,4 +38,14 @@ export interface TextInputProps extends MaskInputProps {
|
|
|
37
38
|
* Show Icon at the end of TextInput.
|
|
38
39
|
*/
|
|
39
40
|
inputIcon?: ReactNode;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Type of the input. won't show keyboard if value set to 'date'
|
|
44
|
+
*/
|
|
45
|
+
inputType?: 'text' | 'date';
|
|
46
|
+
|
|
47
|
+
// handler which get executed when the save button on calendar pressed. Usable only when inputType='date'
|
|
48
|
+
onChangeDate?: (date: Date) => void;
|
|
49
|
+
|
|
50
|
+
calendarProps?: Omit<CalendarPropsAleph, 'isVisible' | 'onDateSave'>;
|
|
40
51
|
}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
memo,
|
|
3
|
+
useCallback,
|
|
4
|
+
useMemo,
|
|
5
|
+
useState,
|
|
6
|
+
} from 'react';
|
|
7
|
+
import { TouchableHighlight, View } from 'react-native';
|
|
8
|
+
import {
|
|
9
|
+
Calendar,
|
|
10
|
+
LocaleConfig,
|
|
11
|
+
} from 'react-native-calendars';
|
|
12
|
+
import { DateData, MarkedDates } from 'react-native-calendars/src/types';
|
|
13
|
+
import ReactNativeModal from 'react-native-modal';
|
|
14
|
+
|
|
15
|
+
import { Palettes, Spacing } from '../../themes';
|
|
16
|
+
import {
|
|
17
|
+
adjustDate,
|
|
18
|
+
findYearPairIndex,
|
|
19
|
+
generateYearPairs,
|
|
20
|
+
getFullDate,
|
|
21
|
+
getMonth,
|
|
22
|
+
getYear,
|
|
23
|
+
} from './calendars.service';
|
|
24
|
+
import { calendarTheme, getStyle } from './calendars.style';
|
|
25
|
+
import { CalendarPropsAleph, ModeSelect, MonthID } from './calendars.type';
|
|
26
|
+
|
|
27
|
+
import { IconChevronLeft, IconChevronRight } from '../../icons';
|
|
28
|
+
import { Typography } from '../typography/typography.component';
|
|
29
|
+
import { Button } from '../button/button.component';
|
|
30
|
+
import { MonthPickerModal, YearPicker } from './month-picker-modal.component';
|
|
31
|
+
|
|
32
|
+
// localization for calendar component
|
|
33
|
+
LocaleConfig.locales['id'] = MonthID;
|
|
34
|
+
LocaleConfig.defaultLocale = 'id';
|
|
35
|
+
|
|
36
|
+
export type OnMonthChange = (data: { num: number }) => void;
|
|
37
|
+
|
|
38
|
+
export type OnArrowChange = (direction: 'left' | 'right') => void;
|
|
39
|
+
|
|
40
|
+
export function Calendars({
|
|
41
|
+
isVisible,
|
|
42
|
+
initialDate = new Date(),
|
|
43
|
+
onDismiss = () => {},
|
|
44
|
+
minDate,
|
|
45
|
+
maxDate,
|
|
46
|
+
onDateSave,
|
|
47
|
+
selectedDate,
|
|
48
|
+
...rest
|
|
49
|
+
}: CalendarPropsAleph) {
|
|
50
|
+
const computedStyle = getStyle();
|
|
51
|
+
|
|
52
|
+
const [dateindicator, setDateIndicator] = useState(
|
|
53
|
+
selectedDate || initialDate
|
|
54
|
+
);
|
|
55
|
+
const [markedDate, setMarkedDate] = useState<MarkedDates>({});
|
|
56
|
+
const [selectMode, setSelectMode] = useState<ModeSelect>('calendar');
|
|
57
|
+
|
|
58
|
+
const yearIntervalPair = useMemo(() => {
|
|
59
|
+
let minYear = 1900;
|
|
60
|
+
let maxYear = new Date().getFullYear();
|
|
61
|
+
if (minDate) {
|
|
62
|
+
minYear = new Date(minDate).getFullYear();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (maxDate) {
|
|
66
|
+
maxYear = new Date(maxDate).getFullYear();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log({ minYear, maxYear, minDate, maxDate });
|
|
70
|
+
|
|
71
|
+
return generateYearPairs(minYear, maxYear, 12);
|
|
72
|
+
}, [minDate, maxDate]);
|
|
73
|
+
|
|
74
|
+
const initYearPairIndex = findYearPairIndex(
|
|
75
|
+
yearIntervalPair,
|
|
76
|
+
initialDate?.getFullYear() || 0
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const [yearPairSelectIndex, setYearPairSelectIndex] =
|
|
80
|
+
useState(initYearPairIndex);
|
|
81
|
+
|
|
82
|
+
const handleOnMonthChange: OnMonthChange = ({ num }) => {
|
|
83
|
+
setDateIndicator(adjustDate(dateindicator, num));
|
|
84
|
+
setSelectMode('calendar');
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const handleOnArrowPress: OnArrowChange = (direction) => {
|
|
88
|
+
if (selectMode === 'calendar') {
|
|
89
|
+
setDateIndicator(
|
|
90
|
+
adjustDate(dateindicator, direction === 'left' ? -1 : 1)
|
|
91
|
+
);
|
|
92
|
+
} else if (selectMode === 'month') {
|
|
93
|
+
setDateIndicator(
|
|
94
|
+
adjustDate(dateindicator, direction === 'left' ? -12 : 12)
|
|
95
|
+
);
|
|
96
|
+
} else {
|
|
97
|
+
if (yearPairSelectIndex <= 0 && direction === 'right') return;
|
|
98
|
+
if (
|
|
99
|
+
yearPairSelectIndex >= yearIntervalPair.length - 1 &&
|
|
100
|
+
direction === 'left'
|
|
101
|
+
)
|
|
102
|
+
return;
|
|
103
|
+
|
|
104
|
+
// don't ask what i'm doing, I know it's crazy T_T
|
|
105
|
+
setYearPairSelectIndex((e) => (direction === 'left' ? e + 1 : e - 1));
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const onDayPress = useCallback((dates: DateData) => {
|
|
110
|
+
if (!dates) return;
|
|
111
|
+
|
|
112
|
+
setDateIndicator(new Date(dates.timestamp));
|
|
113
|
+
setMarkedDate({
|
|
114
|
+
[dates.dateString]: { selected: true, ...dates },
|
|
115
|
+
});
|
|
116
|
+
}, []);
|
|
117
|
+
|
|
118
|
+
const handleSelectModeChange = (mode: ModeSelect) => {
|
|
119
|
+
setSelectMode(mode);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const handleOnDismiss = () => {
|
|
123
|
+
onDismiss();
|
|
124
|
+
|
|
125
|
+
// reset back to initial state
|
|
126
|
+
setSelectMode('calendar');
|
|
127
|
+
setDateIndicator(initialDate);
|
|
128
|
+
setYearPairSelectIndex(initYearPairIndex);
|
|
129
|
+
setMarkedDate({});
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const handleOnDateSubmit = () => {
|
|
133
|
+
const keys = Object.keys(markedDate)
|
|
134
|
+
|
|
135
|
+
if (keys.length <= 0) return;
|
|
136
|
+
|
|
137
|
+
const testDate = markedDate[keys[0] || ''] as MarkedDates[number] & {
|
|
138
|
+
timestamp: number;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const selectedDate = new Date(testDate?.timestamp);
|
|
142
|
+
onDateSave?.(selectedDate);
|
|
143
|
+
onDismiss();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<ReactNativeModal
|
|
148
|
+
isVisible={isVisible}
|
|
149
|
+
onBackdropPress={handleOnDismiss}
|
|
150
|
+
onBackButtonPress={handleOnDismiss}
|
|
151
|
+
backdropTransitionOutTiming={0}
|
|
152
|
+
needsOffscreenAlphaCompositing={true}
|
|
153
|
+
animationIn="zoomInDown"
|
|
154
|
+
animationOut="zoomOut"
|
|
155
|
+
style={computedStyle.modalContainer}
|
|
156
|
+
>
|
|
157
|
+
<View style={computedStyle.container}>
|
|
158
|
+
<CalendarHeader
|
|
159
|
+
initialDate={dateindicator}
|
|
160
|
+
mode={selectMode}
|
|
161
|
+
handleOnArrowPress={handleOnArrowPress}
|
|
162
|
+
handleSelectMode={handleSelectModeChange}
|
|
163
|
+
yearPairSelectIndex={yearPairSelectIndex}
|
|
164
|
+
yearIntervalPair={yearIntervalPair}
|
|
165
|
+
/>
|
|
166
|
+
|
|
167
|
+
<View
|
|
168
|
+
style={[
|
|
169
|
+
computedStyle.calendarContainer,
|
|
170
|
+
{
|
|
171
|
+
paddingHorizontal:
|
|
172
|
+
selectMode === 'calendar' ? Spacing[4] : Spacing[4],
|
|
173
|
+
},
|
|
174
|
+
]}
|
|
175
|
+
>
|
|
176
|
+
{selectMode === 'calendar' ? (
|
|
177
|
+
<>
|
|
178
|
+
<Calendar
|
|
179
|
+
markedDates={markedDate}
|
|
180
|
+
initialDate={getFullDate(dateindicator)}
|
|
181
|
+
style={{ marginHorizontal: Spacing[12] }}
|
|
182
|
+
theme={calendarTheme}
|
|
183
|
+
renderHeader={() => null}
|
|
184
|
+
onDayPress={onDayPress}
|
|
185
|
+
enableSwipeMonths
|
|
186
|
+
minDate={minDate}
|
|
187
|
+
maxDate={maxDate}
|
|
188
|
+
{...rest}
|
|
189
|
+
/>
|
|
190
|
+
|
|
191
|
+
<View style={computedStyle.calendarBottomContainer}>
|
|
192
|
+
<View style={{ flex: 1 }}>
|
|
193
|
+
<Button
|
|
194
|
+
label="Batal"
|
|
195
|
+
variant="secondary"
|
|
196
|
+
onPress={handleOnDismiss}
|
|
197
|
+
/>
|
|
198
|
+
</View>
|
|
199
|
+
<View style={{ width: 16 }} />
|
|
200
|
+
<View style={{ flex: 1 }}>
|
|
201
|
+
<Button
|
|
202
|
+
label="Simpan"
|
|
203
|
+
onPress={handleOnDateSubmit}
|
|
204
|
+
disabled={Object.keys(markedDate).length <= 0}
|
|
205
|
+
/>
|
|
206
|
+
</View>
|
|
207
|
+
</View>
|
|
208
|
+
</>
|
|
209
|
+
) : selectMode === 'month' ? (
|
|
210
|
+
<MonthPickerModal
|
|
211
|
+
initialDate={dateindicator}
|
|
212
|
+
onMonthChange={handleOnMonthChange}
|
|
213
|
+
/>
|
|
214
|
+
) : (
|
|
215
|
+
<YearPicker
|
|
216
|
+
initialDate={dateindicator}
|
|
217
|
+
yearPairSelectIndex={yearPairSelectIndex}
|
|
218
|
+
yearIntervalPair={yearIntervalPair}
|
|
219
|
+
onYearChange={handleOnMonthChange}
|
|
220
|
+
/>
|
|
221
|
+
)}
|
|
222
|
+
</View>
|
|
223
|
+
</View>
|
|
224
|
+
</ReactNativeModal>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
type CalendarHeaderProps = {
|
|
229
|
+
mode: ModeSelect;
|
|
230
|
+
handleSelectMode: (mode: ModeSelect) => void;
|
|
231
|
+
handleOnArrowPress: OnArrowChange;
|
|
232
|
+
yearPairSelectIndex: number;
|
|
233
|
+
yearIntervalPair: [number, number][];
|
|
234
|
+
} & Pick<CalendarPropsAleph, 'initialDate'>;
|
|
235
|
+
|
|
236
|
+
const CalendarHeader = memo(function ({
|
|
237
|
+
mode = 'calendar',
|
|
238
|
+
initialDate = new Date(),
|
|
239
|
+
yearIntervalPair,
|
|
240
|
+
yearPairSelectIndex,
|
|
241
|
+
handleSelectMode,
|
|
242
|
+
handleOnArrowPress,
|
|
243
|
+
}: CalendarHeaderProps) {
|
|
244
|
+
const computedStyle = getStyle();
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<View style={computedStyle.headerContainer}>
|
|
248
|
+
<TouchableHighlight
|
|
249
|
+
onPress={() => handleOnArrowPress('left')}
|
|
250
|
+
style={computedStyle.headerArrowWrapper}
|
|
251
|
+
underlayColor={Palettes.black[900] + '33'}
|
|
252
|
+
>
|
|
253
|
+
<IconChevronLeft />
|
|
254
|
+
</TouchableHighlight>
|
|
255
|
+
|
|
256
|
+
<View style={computedStyle.headerCenterWrapper}>
|
|
257
|
+
{mode === 'calendar' || mode === 'month' ? (
|
|
258
|
+
<>
|
|
259
|
+
<TouchableHighlight
|
|
260
|
+
onPress={() => handleSelectMode('month')}
|
|
261
|
+
style={computedStyle.headerCenterItem}
|
|
262
|
+
underlayColor={Palettes.black[900] + '33'}
|
|
263
|
+
>
|
|
264
|
+
<Typography variant="button">{getMonth(initialDate)}</Typography>
|
|
265
|
+
</TouchableHighlight>
|
|
266
|
+
<TouchableHighlight
|
|
267
|
+
onPress={() => handleSelectMode('year')}
|
|
268
|
+
style={computedStyle.headerCenterItem}
|
|
269
|
+
underlayColor={Palettes.black[900] + '33'}
|
|
270
|
+
>
|
|
271
|
+
<Typography variant="button">{getYear(initialDate)}</Typography>
|
|
272
|
+
</TouchableHighlight>
|
|
273
|
+
</>
|
|
274
|
+
) : (
|
|
275
|
+
<TouchableHighlight
|
|
276
|
+
style={computedStyle.headerCenterItem}
|
|
277
|
+
underlayColor={Palettes.black[900] + '33'}
|
|
278
|
+
>
|
|
279
|
+
<Typography variant="button">
|
|
280
|
+
{yearIntervalPair[yearPairSelectIndex]?.[1]} -{' '}
|
|
281
|
+
{yearIntervalPair[yearPairSelectIndex]?.[0]}
|
|
282
|
+
</Typography>
|
|
283
|
+
</TouchableHighlight>
|
|
284
|
+
)}
|
|
285
|
+
</View>
|
|
286
|
+
|
|
287
|
+
<TouchableHighlight
|
|
288
|
+
onPress={() => handleOnArrowPress('right')}
|
|
289
|
+
style={computedStyle.headerArrowWrapper}
|
|
290
|
+
underlayColor={Palettes.black[900] + '33'}
|
|
291
|
+
>
|
|
292
|
+
<IconChevronRight />
|
|
293
|
+
</TouchableHighlight>
|
|
294
|
+
</View>
|
|
295
|
+
);
|
|
296
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export const getMonth = (date: Date) => {
|
|
2
|
+
return new Intl.DateTimeFormat('id-ID', { month: 'long' }).format(date);
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export const getYear = (date: Date) => {
|
|
6
|
+
return new Intl.DateTimeFormat('id-ID', { year: 'numeric' }).format(date);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const getFullDate = (date: Date) => {
|
|
10
|
+
const formatter = new Intl.DateTimeFormat('en-CA', {
|
|
11
|
+
year: 'numeric',
|
|
12
|
+
month: '2-digit',
|
|
13
|
+
day: '2-digit',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Format the date
|
|
17
|
+
const formattedDate = formatter.format(date);
|
|
18
|
+
|
|
19
|
+
// Since the formatter returns a date in the format of "YYYY/MM/DD",
|
|
20
|
+
// we need to replace the slashes with dashes
|
|
21
|
+
return formattedDate.replace(/\//g, '-');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function adjustDate(date: Date, number: number) {
|
|
25
|
+
// Ensure the input date is a Date object
|
|
26
|
+
const newDate = new Date(date);
|
|
27
|
+
|
|
28
|
+
// Adjust the date by the specified number of days
|
|
29
|
+
newDate.setMonth(newDate.getMonth() + number);
|
|
30
|
+
|
|
31
|
+
return newDate;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type YearPair = [number, number];
|
|
35
|
+
|
|
36
|
+
// endYear < startYear
|
|
37
|
+
export function generateYearPairs(endYear: number, startYear: number, interval: number): YearPair[] {
|
|
38
|
+
const yearPairs: YearPair[] = [];
|
|
39
|
+
let currentYear = startYear;
|
|
40
|
+
|
|
41
|
+
while (currentYear - interval >= endYear) {
|
|
42
|
+
yearPairs.push([currentYear, currentYear - interval + 1]);
|
|
43
|
+
currentYear -= interval;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
yearPairs.push([currentYear, endYear])
|
|
47
|
+
|
|
48
|
+
return yearPairs;
|
|
49
|
+
}
|
|
50
|
+
export function findYearPairIndex(
|
|
51
|
+
years: [number, number][],
|
|
52
|
+
targetYear: number
|
|
53
|
+
): number {
|
|
54
|
+
for (let i = 0; i < years.length; i++) {
|
|
55
|
+
const pair = years[i];
|
|
56
|
+
if (!pair) continue; // Skip if the pair is undefined
|
|
57
|
+
|
|
58
|
+
const [startYear, endYear] = pair;
|
|
59
|
+
if (targetYear >= endYear && targetYear <= startYear) {
|
|
60
|
+
return i;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return -1; // Return -1 if the target year is not found in any pair
|
|
64
|
+
}
|