index.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import React, { useEffect, useState } from 'react';
  2. import { View } from 'react-native';
  3. import { Modal } from '../../Modal';
  4. import DateTimePicker, { DateType } from 'react-native-ui-datepicker';
  5. import dayjs from 'dayjs';
  6. import 'dayjs/locale/en';
  7. import calendar from 'dayjs/plugin/calendar';
  8. import updateLocale from 'dayjs/plugin/updateLocale';
  9. import localeData from 'dayjs/plugin/localeData';
  10. import customParseFormat from 'dayjs/plugin/customParseFormat';
  11. dayjs.locale('en');
  12. dayjs.extend(calendar);
  13. dayjs.extend(updateLocale);
  14. dayjs.extend(localeData);
  15. dayjs.extend(customParseFormat);
  16. import { styles } from './style';
  17. import { Colors } from '../../../theme';
  18. import { Button } from 'src/components/Button';
  19. import { ButtonVariants } from 'src/types/components';
  20. export default function RangeCalendar({
  21. isModalVisible,
  22. closeModal,
  23. allowRangeSelection = true,
  24. disableFutureDates = false,
  25. disablePastDates = false,
  26. highlightedDates,
  27. selectedDate
  28. }: {
  29. isModalVisible: boolean;
  30. closeModal: (startDate?: string | null, endDate?: string | null) => void;
  31. allowRangeSelection?: boolean;
  32. disableFutureDates?: boolean;
  33. disablePastDates?: boolean;
  34. highlightedDates?: string[];
  35. selectedDate?: string;
  36. }) {
  37. const [selectedStartDate, setSelectedStartDate] = useState<string | null>(null);
  38. const [selectedEndDate, setSelectedEndDate] = useState<string | null>(null);
  39. const [singleDate, setSingleDate] = useState<DateType>(undefined);
  40. const [startDate, setStartDate] = useState<DateType>(undefined);
  41. const [endDate, setEndDate] = useState<DateType>(undefined);
  42. useEffect(() => {
  43. if (selectedDate) {
  44. setSelectedStartDate(selectedDate);
  45. setSingleDate(dayjs(selectedDate));
  46. }
  47. }, [selectedDate]);
  48. const getDisabledDates = (date: DateType) => {
  49. const dateString = dayjs(date).format('YYYY-MM-DD');
  50. if (disableFutureDates) {
  51. if (dayjs(date).isAfter(dayjs(), 'day')) {
  52. return true;
  53. }
  54. }
  55. if (disablePastDates) {
  56. if (dayjs(date).isBefore(dayjs(), 'day')) {
  57. return true;
  58. }
  59. }
  60. if (highlightedDates && highlightedDates.length > 0) {
  61. return !highlightedDates.includes(dateString);
  62. }
  63. return false;
  64. };
  65. const handleDateChange = (params: any) => {
  66. if (allowRangeSelection) {
  67. setStartDate(params.startDate);
  68. setEndDate(params.endDate);
  69. if (params.startDate) {
  70. setSelectedStartDate(dayjs(params.startDate).format('YYYY-MM-DD'));
  71. }
  72. if (params.endDate) {
  73. setSelectedEndDate(dayjs(params.endDate).format('YYYY-MM-DD'));
  74. } else {
  75. setSelectedEndDate(null);
  76. }
  77. } else {
  78. setSingleDate(params.date);
  79. setSelectedStartDate(dayjs(params.date).format('YYYY-MM-DD'));
  80. setSelectedEndDate(null);
  81. }
  82. };
  83. const resetSelections = () => {
  84. closeModal();
  85. setSelectedStartDate(null);
  86. setSelectedEndDate(null);
  87. setStartDate(undefined);
  88. setEndDate(undefined);
  89. setSingleDate(undefined);
  90. };
  91. const handleClose = () => {
  92. closeModal(selectedStartDate, selectedEndDate);
  93. setSelectedStartDate(null);
  94. setSelectedEndDate(null);
  95. setStartDate(undefined);
  96. setEndDate(undefined);
  97. setSingleDate(undefined);
  98. };
  99. const minDate =
  100. highlightedDates && highlightedDates.length > 0 ? dayjs(highlightedDates[0]) : undefined;
  101. const maxDate =
  102. highlightedDates && highlightedDates.length > 0
  103. ? dayjs(highlightedDates[highlightedDates.length - 1])
  104. : undefined;
  105. return (
  106. <Modal
  107. visibleInPercent={'auto'}
  108. visible={isModalVisible}
  109. onRequestClose={resetSelections}
  110. headerTitle={allowRangeSelection ? 'Select Dates' : 'Select Date'}
  111. >
  112. <View style={styles.modalContent}>
  113. <DateTimePicker
  114. mode={allowRangeSelection ? 'range' : 'single'}
  115. date={singleDate}
  116. startDate={startDate}
  117. endDate={endDate}
  118. onChange={handleDateChange}
  119. minDate={minDate}
  120. maxDate={maxDate}
  121. disabledDates={getDisabledDates}
  122. firstDayOfWeek={1}
  123. timePicker={false}
  124. showOutsideDays={true}
  125. weekdaysFormat={'short'}
  126. styles={{
  127. header: {
  128. paddingBottom: 10
  129. },
  130. month_selector_label: {
  131. color: Colors.DARK_BLUE,
  132. fontWeight: 'bold',
  133. fontSize: 15
  134. },
  135. year_selector_label: {
  136. color: Colors.DARK_BLUE,
  137. fontWeight: 'bold',
  138. fontSize: 15
  139. },
  140. button_prev: {},
  141. button_next: {},
  142. weekday_label: {
  143. color: Colors.DARK_BLUE,
  144. fontWeight: 'bold',
  145. fontSize: 12
  146. },
  147. days: {},
  148. day_cell: {},
  149. day: {},
  150. day_label: {
  151. color: Colors.DARK_BLUE,
  152. fontSize: 14,
  153. fontWeight: 'normal'
  154. },
  155. today: {
  156. borderWidth: 1,
  157. borderRadius: 23,
  158. width: 46,
  159. height: 46,
  160. maxHeight: 46,
  161. borderColor: Colors.ORANGE
  162. },
  163. today_label: {
  164. color: Colors.DARK_BLUE,
  165. fontWeight: '500'
  166. },
  167. selected: {
  168. backgroundColor: Colors.ORANGE,
  169. borderRadius: 23,
  170. width: 46,
  171. height: 46,
  172. maxHeight: 46,
  173. marginVertical: 'auto',
  174. alignItems: 'center',
  175. justifyContent: 'center'
  176. },
  177. selected_label: {
  178. color: 'white',
  179. fontWeight: '500'
  180. },
  181. range_start: {
  182. backgroundColor: Colors.ORANGE,
  183. borderRadius: 23,
  184. width: 46,
  185. height: 46,
  186. alignItems: 'center',
  187. justifyContent: 'center'
  188. },
  189. range_start_label: {
  190. color: 'white'
  191. },
  192. range_end: {
  193. backgroundColor: Colors.ORANGE,
  194. borderRadius: 23,
  195. width: 46,
  196. height: 46,
  197. alignItems: 'center',
  198. justifyContent: 'center'
  199. },
  200. range_end_label: {
  201. color: 'white'
  202. },
  203. range_middle_label: {
  204. color: Colors.DARK_BLUE,
  205. fontWeight: '500'
  206. },
  207. range_fill: {
  208. backgroundColor: Colors.ORANGE,
  209. opacity: 0.2
  210. },
  211. disabled: {
  212. opacity: 0.3
  213. },
  214. disabled_label: {
  215. color: Colors.TEXT_GRAY
  216. },
  217. outside_label: {
  218. color: Colors.LIGHT_GRAY
  219. }
  220. }}
  221. />
  222. </View>
  223. <View style={styles.modalFooter}>
  224. <Button
  225. children="Done"
  226. onPress={handleClose}
  227. disabled={!selectedStartDate}
  228. variant={!selectedStartDate ? ButtonVariants.OPACITY : ButtonVariants.FILL}
  229. containerStyles={{ borderWidth: 0 }}
  230. />
  231. </View>
  232. </Modal>
  233. );
  234. }