index.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. import {
  2. useState,
  3. useRef
  4. } from "react";
  5. import {
  6. TouchableOpacity,
  7. View
  8. } from "react-native";
  9. import type IDateTimeSheetProps from "./type";
  10. import stylesheet, {
  11. useStyles
  12. } from "./stylesheet";
  13. import {
  14. NCoreUIKitLocalize,
  15. NCoreUIKitTheme
  16. } from "../../core/hooks";
  17. import type {
  18. IDateSelectorRef
  19. } from "../dateSelector/type";
  20. import type {
  21. IMonthSelectorRef
  22. } from "../monthSelector/type";
  23. import type {
  24. IYearSelectorRef
  25. } from "../yearSelector/type";
  26. import MonthSelector from "../monthSelector";
  27. import TimeSelector from "../timeSelector";
  28. import YearSelector from "../yearSelector";
  29. import DateSelector from "../dateSelector";
  30. import BottomSheet from "../bottomSheet";
  31. import CheckBox from "../checkBox";
  32. import Loading from "../loading";
  33. import Button from "../button";
  34. import Text from "../text";
  35. const DateTimeSheet = ({
  36. isTimeSelectWorksWithCenterWhenTimePicker,
  37. dateCalendarType: dateCalendarTypeProp,
  38. multipleSelectMinimumRequiredDayCount,
  39. localeBasedFirstDayOfWeek = true,
  40. multipleSelectMinimumRequireMS,
  41. isShowTodayIndicator = true,
  42. isShowCalenderChangerTool,
  43. dayOfWeekLength = "short",
  44. LoadingIconComponentProp,
  45. multipleSelectMaximumMS,
  46. multipleSelectDayLimit,
  47. monthOfYearLengthType,
  48. selectMultipleObject,
  49. isWorkWithRealtime,
  50. isShowTools = true,
  51. isWorkWithSeconds,
  52. dateTimePickerKey,
  53. bottomSheetProps,
  54. bottomSheetRef,
  55. customLocalize,
  56. selectObject,
  57. customTheme,
  58. setIsActive,
  59. pickerType,
  60. dateRange,
  61. maxChoice,
  62. minChoice,
  63. isLoading,
  64. isActive,
  65. dateRule,
  66. variant,
  67. maxDate,
  68. minDate,
  69. cancel,
  70. clean,
  71. title,
  72. date,
  73. ok
  74. }: IDateTimeSheetProps) => {
  75. const {
  76. radiuses,
  77. borders,
  78. spaces,
  79. colors
  80. } = NCoreUIKitTheme.useContext(customTheme);
  81. const {
  82. localize
  83. } = NCoreUIKitLocalize.useContext(customLocalize);
  84. const [
  85. isSheetContentReady,
  86. setIsSheetContentReady
  87. ] = useState(false);
  88. const [
  89. dateCalendarType,
  90. setDateCalendarType
  91. ] = useState(dateCalendarTypeProp ?? "day");
  92. const monthCalendarRef = useRef<IMonthSelectorRef>(null);
  93. const yearCalendarRef = useRef<IYearSelectorRef>(null);
  94. const dayCalendarRef = useRef<IDateSelectorRef>(null);
  95. const {
  96. calendarChangerToolContainer: calendarChangerToolContainerDynamicStyle,
  97. calendarChangerToolButton: calendarChangerToolButtonDynamicStyle,
  98. loadingContainer: loadingContainerDynamicStyle,
  99. contentContainer: contentContainerDynamicStyle,
  100. headerContainer: headerContainerDynamicStyle,
  101. bottomContainer: bottomContainerDynamicStyle,
  102. toolsContainer: toolsContainerDynamicStyle,
  103. cancelButton: cancelButtonDynamicStyle,
  104. headerTitle: headerTitleDynamicStyle,
  105. okButton: okButtonDynamicStyle
  106. } = useStyles({
  107. radiuses,
  108. borders,
  109. spaces,
  110. colors
  111. });
  112. const renderCalenderChangerTool = () => {
  113. if(!isShowCalenderChangerTool) {
  114. return null;
  115. }
  116. if(dateCalendarTypeProp) {
  117. return null;
  118. }
  119. return <View
  120. style={[
  121. stylesheet.calendarChangerToolContainer,
  122. calendarChangerToolContainerDynamicStyle
  123. ]}
  124. >
  125. <TouchableOpacity
  126. style={[
  127. stylesheet.calendarChangerToolButton,
  128. calendarChangerToolButtonDynamicStyle,
  129. dateCalendarType === "day" ? {
  130. backgroundColor: colors.content.container.primary
  131. } : null
  132. ]}
  133. onPress={() => {
  134. setDateCalendarType("day");
  135. }}
  136. >
  137. <Text
  138. color={dateCalendarType === "day" ? "onPrimary" : undefined}
  139. >
  140. {localize("daily")}
  141. </Text>
  142. </TouchableOpacity>
  143. <TouchableOpacity
  144. style={[
  145. stylesheet.calendarChangerToolButton,
  146. calendarChangerToolButtonDynamicStyle,
  147. dateCalendarType === "month" ? {
  148. backgroundColor: colors.content.container.primary
  149. } : null
  150. ]}
  151. onPress={() => {
  152. setDateCalendarType("month");
  153. }}
  154. >
  155. <Text
  156. color={dateCalendarType === "month" ? "onPrimary" : undefined}
  157. >
  158. {localize("monthly")}
  159. </Text>
  160. </TouchableOpacity>
  161. <TouchableOpacity
  162. style={[
  163. stylesheet.calendarChangerToolButton,
  164. calendarChangerToolButtonDynamicStyle,
  165. dateCalendarType === "year" ? {
  166. backgroundColor: colors.content.container.primary
  167. } : null
  168. ]}
  169. onPress={() => {
  170. setDateCalendarType("year");
  171. }}
  172. >
  173. <Text
  174. color={dateCalendarType === "year" ? "onPrimary" : undefined}
  175. >
  176. {localize("yearly")}
  177. </Text>
  178. </TouchableOpacity>
  179. </View>;
  180. };
  181. const renderDateCalendar = () => {
  182. if(pickerType === "time") {
  183. return null;
  184. }
  185. if(dateCalendarType === "month") {
  186. return <MonthSelector
  187. multipleSelectMinimumRequiredDayCount={multipleSelectMinimumRequiredDayCount}
  188. setIsSheetContentReady={setIsSheetContentReady}
  189. multipleSelectDayLimit={multipleSelectDayLimit}
  190. monthOfYearLengthType={monthOfYearLengthType}
  191. selectMultipleObject={selectMultipleObject}
  192. isShowTodayIndicator={isShowTodayIndicator}
  193. selectObject={selectObject}
  194. ref={monthCalendarRef}
  195. dateRange={dateRange}
  196. maxDate={maxDate}
  197. minDate={minDate}
  198. variant={variant}
  199. date={date}
  200. />;
  201. }
  202. if(dateCalendarType === "year") {
  203. return <YearSelector
  204. multipleSelectMinimumRequiredDayCount={multipleSelectMinimumRequiredDayCount}
  205. setIsSheetContentReady={setIsSheetContentReady}
  206. multipleSelectDayLimit={multipleSelectDayLimit}
  207. selectMultipleObject={selectMultipleObject}
  208. isShowTodayIndicator={isShowTodayIndicator}
  209. selectObject={selectObject}
  210. dateRange={dateRange}
  211. ref={yearCalendarRef}
  212. maxDate={maxDate}
  213. minDate={minDate}
  214. variant={variant}
  215. date={date}
  216. />;
  217. }
  218. return <DateSelector
  219. multipleSelectMinimumRequiredDayCount={multipleSelectMinimumRequiredDayCount}
  220. localeBasedFirstDayOfWeek={localeBasedFirstDayOfWeek}
  221. setIsSheetContentReady={setIsSheetContentReady}
  222. multipleSelectDayLimit={multipleSelectDayLimit}
  223. selectMultipleObject={selectMultipleObject}
  224. isShowTodayIndicator={isShowTodayIndicator}
  225. dayOfWeekLength={dayOfWeekLength}
  226. selectObject={selectObject}
  227. dateRange={dateRange}
  228. ref={dayCalendarRef}
  229. maxDate={maxDate}
  230. minDate={minDate}
  231. variant={variant}
  232. date={date}
  233. />;
  234. };
  235. const renderBottomSheetContent = () => {
  236. if(isLoading) {
  237. return <View
  238. style={[
  239. stylesheet.loadingContainer,
  240. loadingContainerDynamicStyle
  241. ]}
  242. >
  243. {
  244. LoadingIconComponentProp ?
  245. <LoadingIconComponentProp
  246. color="emphasized"
  247. size={20}
  248. />
  249. :
  250. <Loading/>
  251. }
  252. </View>;
  253. }
  254. return <View
  255. style={[
  256. stylesheet.contentContainer,
  257. contentContainerDynamicStyle
  258. ]}
  259. >
  260. {renderCalenderChangerTool()}
  261. {renderDateCalendar()}
  262. {
  263. pickerType === "date" ?
  264. null
  265. :
  266. <TimeSelector
  267. isTimeSelectWorksWithCenterWhenTimePicker={isTimeSelectWorksWithCenterWhenTimePicker}
  268. multipleSelectMinimumRequireMS={multipleSelectMinimumRequireMS}
  269. multipleSelectMaximumMS={multipleSelectMaximumMS}
  270. setIsSheetContentReady={setIsSheetContentReady}
  271. selectMultipleObject={selectMultipleObject}
  272. isWorkWithSeconds={isWorkWithSeconds}
  273. selectObject={selectObject}
  274. pickerType={pickerType}
  275. dateRange={dateRange}
  276. maxDate={maxDate}
  277. minDate={minDate}
  278. variant={variant}
  279. date={date}
  280. />
  281. }
  282. </View>;
  283. };
  284. const renderTools = () => {
  285. if(!isShowTools) {
  286. return null;
  287. }
  288. if(minChoice && maxChoice !== -1) {
  289. return null;
  290. }
  291. let isAnySelected = false;
  292. if(variant === "single" && date) {
  293. isAnySelected = true;
  294. }
  295. if(variant === "range" && dateRange && (dateRange.start || dateRange.end)) {
  296. isAnySelected = true;
  297. }
  298. if(variant === "rrule" && dateRule) {
  299. isAnySelected = true;
  300. }
  301. return <View
  302. style={[
  303. stylesheet.toolsContainer,
  304. toolsContainerDynamicStyle
  305. ]}
  306. >
  307. {
  308. !minChoice ?
  309. <CheckBox
  310. isChecked={isAnySelected ? "checked" : null}
  311. title={localize("clean-selection")}
  312. spreadBehaviour="free"
  313. onPress={() => {
  314. clean();
  315. }}
  316. />
  317. :
  318. null
  319. }
  320. <Button
  321. onPress={() => {
  322. if(monthCalendarRef.current) monthCalendarRef.current.changeCurrentYear(new Date());
  323. if(yearCalendarRef.current) yearCalendarRef.current.changeCurrentView(new Date());
  324. if(dayCalendarRef.current) dayCalendarRef.current.changeCurrentMonth(new Date());
  325. }}
  326. title={localize("go-to-today")}
  327. spreadBehaviour="free"
  328. size="small"
  329. />
  330. </View>;
  331. };
  332. const renderBottomSheetHeader = () => {
  333. return <View
  334. style={[
  335. stylesheet.headerContainer,
  336. headerContainerDynamicStyle
  337. ]}
  338. >
  339. {
  340. title ?
  341. <Text
  342. variant="titleMediumSize"
  343. style={[
  344. headerTitleDynamicStyle
  345. ]}
  346. >
  347. {title}
  348. </Text>
  349. :
  350. null
  351. }
  352. {renderTools()}
  353. </View>;
  354. };
  355. const renderBottomSheetBottom = () => {
  356. if(isWorkWithRealtime) {
  357. return null;
  358. }
  359. return <View
  360. style={[
  361. stylesheet.bottomContainer,
  362. bottomContainerDynamicStyle
  363. ]}
  364. >
  365. <Button
  366. title={localize("cancel")}
  367. spreadBehaviour="stretch"
  368. variant="outline"
  369. type="neutral"
  370. onPress={() => {
  371. cancel();
  372. }}
  373. style={{
  374. ...cancelButtonDynamicStyle
  375. }}
  376. />
  377. <Button
  378. spreadBehaviour="stretch"
  379. title={localize("ok")}
  380. onPress={() => {
  381. ok();
  382. }}
  383. style={{
  384. ...okButtonDynamicStyle
  385. }}
  386. />
  387. </View>;
  388. };
  389. return <BottomSheet
  390. {...bottomSheetProps}
  391. key={`${dateTimePickerKey}-bottomsheet`}
  392. isContentReady={isSheetContentReady}
  393. customKey={dateTimePickerKey}
  394. ref={bottomSheetRef}
  395. isAutoHeight={true}
  396. isActive={isActive}
  397. renderBottom={() => {
  398. return renderBottomSheetBottom();
  399. }}
  400. renderHeader={() => {
  401. return renderBottomSheetHeader();
  402. }}
  403. onClosed={() => {
  404. setIsActive(false);
  405. }}
  406. >
  407. {renderBottomSheetContent()}
  408. </BottomSheet>;
  409. };
  410. export default DateTimeSheet;