index.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. {LoadingIconComponentProp ? <LoadingIconComponentProp
  244. color="emphasized"
  245. size={20}
  246. /> : <Loading/>}
  247. </View>;
  248. }
  249. return <View
  250. style={[
  251. stylesheet.contentContainer,
  252. contentContainerDynamicStyle
  253. ]}
  254. >
  255. {renderCalenderChangerTool()}
  256. {renderDateCalendar()}
  257. {
  258. pickerType === "date" ? null : <TimeSelector
  259. isTimeSelectWorksWithCenterWhenTimePicker={isTimeSelectWorksWithCenterWhenTimePicker}
  260. multipleSelectMinimumRequireMS={multipleSelectMinimumRequireMS}
  261. multipleSelectMaximumMS={multipleSelectMaximumMS}
  262. setIsSheetContentReady={setIsSheetContentReady}
  263. selectMultipleObject={selectMultipleObject}
  264. isWorkWithSeconds={isWorkWithSeconds}
  265. selectObject={selectObject}
  266. pickerType={pickerType}
  267. dateRange={dateRange}
  268. maxDate={maxDate}
  269. minDate={minDate}
  270. variant={variant}
  271. date={date}
  272. />
  273. }
  274. </View>;
  275. };
  276. const renderTools = () => {
  277. if(!isShowTools) {
  278. return null;
  279. }
  280. if(minChoice && maxChoice !== -1) {
  281. return null;
  282. }
  283. let isAnySelected = false;
  284. if(variant === "single" && date) {
  285. isAnySelected = true;
  286. }
  287. if(variant === "range" && dateRange && (dateRange.start || dateRange.end)) {
  288. isAnySelected = true;
  289. }
  290. if(variant === "rrule" && dateRule) {
  291. isAnySelected = true;
  292. }
  293. return <View
  294. style={[
  295. stylesheet.toolsContainer,
  296. toolsContainerDynamicStyle
  297. ]}
  298. >
  299. {!minChoice ? <CheckBox
  300. isChecked={isAnySelected ? "checked" : null}
  301. title={localize("clean-selection")}
  302. spreadBehaviour="free"
  303. onPress={() => {
  304. clean();
  305. }}
  306. /> : null}
  307. <Button
  308. onPress={() => {
  309. if(monthCalendarRef.current) monthCalendarRef.current.changeCurrentYear(new Date());
  310. if(yearCalendarRef.current) yearCalendarRef.current.changeCurrentView(new Date());
  311. if(dayCalendarRef.current) dayCalendarRef.current.changeCurrentMonth(new Date());
  312. }}
  313. title={localize("go-to-today")}
  314. spreadBehaviour="free"
  315. size="small"
  316. />
  317. </View>;
  318. };
  319. const renderBottomSheetHeader = () => {
  320. return <View
  321. style={[
  322. stylesheet.headerContainer,
  323. headerContainerDynamicStyle
  324. ]}
  325. >
  326. {title ? <Text
  327. variant="titleMediumSize"
  328. style={[
  329. headerTitleDynamicStyle
  330. ]}
  331. >
  332. {title}
  333. </Text> : null}
  334. {renderTools()}
  335. </View>;
  336. };
  337. const renderBottomSheetBottom = () => {
  338. if(isWorkWithRealtime) {
  339. return null;
  340. }
  341. return <View
  342. style={[
  343. stylesheet.bottomContainer,
  344. bottomContainerDynamicStyle
  345. ]}
  346. >
  347. <Button
  348. title={localize("cancel")}
  349. spreadBehaviour="stretch"
  350. variant="outline"
  351. type="neutral"
  352. onPress={() => {
  353. cancel();
  354. }}
  355. style={{
  356. ...cancelButtonDynamicStyle
  357. }}
  358. />
  359. <Button
  360. spreadBehaviour="stretch"
  361. title={localize("ok")}
  362. onPress={() => {
  363. ok();
  364. }}
  365. style={{
  366. ...okButtonDynamicStyle
  367. }}
  368. />
  369. </View>;
  370. };
  371. return <BottomSheet
  372. {...bottomSheetProps}
  373. key={`${dateTimePickerKey}-bottomsheet`}
  374. isContentReady={isSheetContentReady}
  375. customKey={dateTimePickerKey}
  376. ref={bottomSheetRef}
  377. isAutoHeight={true}
  378. isActive={isActive}
  379. renderBottom={() => {
  380. return renderBottomSheetBottom();
  381. }}
  382. renderHeader={() => {
  383. return renderBottomSheetHeader();
  384. }}
  385. onClosed={() => {
  386. setIsActive(false);
  387. }}
  388. >
  389. {renderBottomSheetContent()}
  390. </BottomSheet>;
  391. };
  392. export default DateTimeSheet;