index.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. import {
  2. useEffect
  3. } from "react";
  4. import {
  5. View
  6. } from "react-native";
  7. import type {
  8. TimeInputRangeType
  9. } from "./components/timeInput/type";
  10. import type ITimeSelectorProps from "./type";
  11. import type {
  12. UpdateDateRangeType,
  13. UpdateDateType
  14. } from "./type";
  15. import stylesheet, {
  16. useStyles
  17. } from "./stylesheet";
  18. import TimeInput from "./components/timeInput";
  19. import {
  20. NCoreUIKitLocalize,
  21. NCoreUIKitTheme,
  22. NCoreUIKitToast
  23. } from "../../core/hooks";
  24. import type {
  25. DateTimePickerDateRange
  26. } from "../dateTimePicker/type";
  27. import moment from "moment";
  28. import {
  29. Fragment
  30. } from "react/jsx-runtime";
  31. import Text from "../text";
  32. const TimeSelector = ({
  33. isTimeSelectWorksWithCenterWhenTimePicker,
  34. multipleSelectMinimumRequireMS,
  35. isWorkWith24HoursFormat = true,
  36. isWorkWithSeconds = false,
  37. multipleSelectMaximumMS,
  38. setIsSheetContentReady,
  39. selectMultipleObject,
  40. selectObject,
  41. pickerType,
  42. dateRange,
  43. maxDate,
  44. minDate,
  45. variant,
  46. date
  47. }: ITimeSelectorProps) => {
  48. const {
  49. spaces
  50. } = NCoreUIKitTheme.useContext();
  51. const {
  52. localize
  53. } = NCoreUIKitLocalize.useContext();
  54. const {
  55. inputsContainer: inputsContainerDynamicStyle,
  56. rangeContainer: rangeContainerDynamicStyle,
  57. container: containerDynamicStyle,
  58. colonText: colonTextDynamicStyle,
  59. timeTitle: timeTitleDynamicStyle
  60. } = useStyles({
  61. isTimeSelectWorksWithCenterWhenTimePicker,
  62. pickerType,
  63. spaces
  64. });
  65. useEffect(() => {
  66. if(pickerType === "time") setIsSheetContentReady(true);
  67. }, []);
  68. const setDateRangeValue = ({
  69. rangeType,
  70. seconds,
  71. minutes,
  72. hours
  73. }: UpdateDateRangeType) => {
  74. if(!dateRange) {
  75. return;
  76. }
  77. const newRangeDate = dateRange[rangeType] ? dateRange[rangeType] : new Date();
  78. if(hours !== undefined) {
  79. newRangeDate?.setHours(hours);
  80. }
  81. if(minutes !== undefined) {
  82. newRangeDate?.setMinutes(minutes);
  83. }
  84. if(seconds !== undefined) {
  85. newRangeDate?.setSeconds(seconds);
  86. }
  87. const newMultipleObject = dateRange;
  88. newMultipleObject[rangeType] = newRangeDate;
  89. return newMultipleObject;
  90. };
  91. const setDateValue = ({
  92. seconds,
  93. minutes,
  94. hours
  95. }: UpdateDateType) => {
  96. const newDate = date ? date : new Date();
  97. if(hours !== undefined) {
  98. newDate?.setHours(hours);
  99. }
  100. if(minutes !== undefined) {
  101. newDate?.setMinutes(minutes);
  102. }
  103. if(seconds !== undefined) {
  104. newDate?.setSeconds(seconds);
  105. }
  106. return newDate;
  107. };
  108. const rangeValidation = ({
  109. dateRangeValue,
  110. rangeType
  111. }: {
  112. dateRangeValue: DateTimePickerDateRange;
  113. rangeType: TimeInputRangeType;
  114. }) => {
  115. const start = rangeType === "start" ? dateRangeValue[rangeType] : dateRange?.start;
  116. const end = rangeType === "end" ? dateRangeValue[rangeType] : dateRange?.end;
  117. if(start && end) {
  118. if(multipleSelectMinimumRequireMS && Math.abs(moment(end).diff(start, "milliseconds")) < multipleSelectMinimumRequireMS) {
  119. NCoreUIKitToast.open({
  120. title: localize("selected-start-and-end-times-cannot-be-less-than-x-times-apart", [
  121. moment.duration(multipleSelectMinimumRequireMS).humanize()
  122. ])
  123. });
  124. return false;
  125. }
  126. if(multipleSelectMaximumMS && Math.abs(moment(end).diff(start, "milliseconds")) > multipleSelectMaximumMS) {
  127. NCoreUIKitToast.open({
  128. title: localize("selected-start-and-end-times-cannot-exceed-x-intervals", [
  129. moment.duration(multipleSelectMaximumMS).humanize()
  130. ])
  131. });
  132. return false;
  133. }
  134. if(moment(end).isBefore(start)) {
  135. NCoreUIKitToast.open({
  136. title: localize("selected-end-time-cannot-before-from-start-time")
  137. });
  138. return false;
  139. }
  140. if(moment(start).isAfter(end)) {
  141. NCoreUIKitToast.open({
  142. title: localize("selected-start-time-cannot-after-then-end-time")
  143. });
  144. return false;
  145. }
  146. }
  147. return true;
  148. };
  149. const renderTimeInputs = () => {
  150. if(variant === "range") {
  151. return <View
  152. style={[
  153. stylesheet.rangeContainer,
  154. rangeContainerDynamicStyle
  155. ]}
  156. >
  157. <Text
  158. variant="labelMediumSize"
  159. style={{
  160. ...stylesheet.timeTitle,
  161. ...timeTitleDynamicStyle
  162. }}
  163. >
  164. {localize("start-time")}:
  165. </Text>
  166. <View
  167. style={[
  168. stylesheet.inputsContainer,
  169. inputsContainerDynamicStyle,
  170. {
  171. marginBottom: spaces.spacingMd
  172. }
  173. ]}
  174. >
  175. <TimeInput
  176. initialValue={dateRange?.start?.getHours().toString().padStart(2, "0")}
  177. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  178. selectMultipleObject={selectMultipleObject}
  179. setDateRangeValue={setDateRangeValue}
  180. rangeValidation={rangeValidation}
  181. setDateValue={setDateValue}
  182. selectObject={selectObject}
  183. variant={variant}
  184. maxDate={maxDate}
  185. minDate={minDate}
  186. rangeType="start"
  187. timeType="hours"
  188. />
  189. <Text
  190. variant="titleMediumSize"
  191. style={{
  192. ...stylesheet.colonText,
  193. ...colonTextDynamicStyle
  194. }}
  195. >
  196. :
  197. </Text>
  198. <TimeInput
  199. initialValue={dateRange?.start?.getMinutes().toString().padStart(2, "0")}
  200. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  201. selectMultipleObject={selectMultipleObject}
  202. setDateRangeValue={setDateRangeValue}
  203. rangeValidation={rangeValidation}
  204. setDateValue={setDateValue}
  205. selectObject={selectObject}
  206. timeType="minutes"
  207. variant={variant}
  208. maxDate={maxDate}
  209. minDate={minDate}
  210. rangeType="start"
  211. />
  212. {
  213. isWorkWithSeconds ?
  214. <Fragment>
  215. <Text
  216. variant="titleMediumSize"
  217. style={{
  218. ...stylesheet.colonText,
  219. ...colonTextDynamicStyle
  220. }}
  221. >
  222. :
  223. </Text>
  224. <TimeInput
  225. initialValue={dateRange?.start?.getSeconds().toString().padStart(2, "0")}
  226. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  227. selectMultipleObject={selectMultipleObject}
  228. setDateRangeValue={setDateRangeValue}
  229. rangeValidation={rangeValidation}
  230. setDateValue={setDateValue}
  231. selectObject={selectObject}
  232. timeType="seconds"
  233. variant={variant}
  234. maxDate={maxDate}
  235. minDate={minDate}
  236. rangeType="start"
  237. />
  238. </Fragment>
  239. :
  240. null
  241. }
  242. </View>
  243. <Text
  244. variant="labelMediumSize"
  245. style={{
  246. ...stylesheet.timeTitle,
  247. ...timeTitleDynamicStyle
  248. }}
  249. >
  250. {localize("end-time")}:
  251. </Text>
  252. <View
  253. style={[
  254. stylesheet.inputsContainer,
  255. inputsContainerDynamicStyle
  256. ]}
  257. >
  258. <TimeInput
  259. initialValue={dateRange?.end?.getHours().toString().padStart(2, "0")}
  260. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  261. selectMultipleObject={selectMultipleObject}
  262. setDateRangeValue={setDateRangeValue}
  263. rangeValidation={rangeValidation}
  264. setDateValue={setDateValue}
  265. selectObject={selectObject}
  266. variant={variant}
  267. maxDate={maxDate}
  268. minDate={minDate}
  269. timeType="hours"
  270. rangeType="end"
  271. />
  272. <Text
  273. variant="titleMediumSize"
  274. style={{
  275. ...stylesheet.colonText,
  276. ...colonTextDynamicStyle
  277. }}
  278. >
  279. :
  280. </Text>
  281. <TimeInput
  282. initialValue={dateRange?.end?.getMinutes().toString().padStart(2, "0")}
  283. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  284. selectMultipleObject={selectMultipleObject}
  285. setDateRangeValue={setDateRangeValue}
  286. rangeValidation={rangeValidation}
  287. setDateValue={setDateValue}
  288. selectObject={selectObject}
  289. timeType="minutes"
  290. variant={variant}
  291. maxDate={maxDate}
  292. minDate={minDate}
  293. rangeType="end"
  294. />
  295. {
  296. isWorkWithSeconds ?
  297. <Fragment>
  298. <Text
  299. variant="titleMediumSize"
  300. style={{
  301. ...stylesheet.colonText,
  302. ...colonTextDynamicStyle
  303. }}
  304. >
  305. :
  306. </Text>
  307. <TimeInput
  308. initialValue={dateRange?.end?.getSeconds().toString().padStart(2, "0")}
  309. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  310. selectMultipleObject={selectMultipleObject}
  311. setDateRangeValue={setDateRangeValue}
  312. rangeValidation={rangeValidation}
  313. setDateValue={setDateValue}
  314. selectObject={selectObject}
  315. timeType="seconds"
  316. variant={variant}
  317. maxDate={maxDate}
  318. minDate={minDate}
  319. rangeType="end"
  320. />
  321. </Fragment>
  322. :
  323. null
  324. }
  325. </View>
  326. </View>;
  327. }
  328. return <View>
  329. <Text
  330. variant="labelMediumSize"
  331. style={{
  332. ...stylesheet.timeTitle,
  333. ...timeTitleDynamicStyle
  334. }}
  335. >
  336. {localize("end-time")}:
  337. </Text>
  338. <View
  339. style={[
  340. stylesheet.inputsContainer,
  341. inputsContainerDynamicStyle
  342. ]}
  343. >
  344. <TimeInput
  345. initialValue={date?.getHours().toString().padStart(2, "0")}
  346. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  347. selectMultipleObject={selectMultipleObject}
  348. setDateRangeValue={setDateRangeValue}
  349. setDateValue={setDateValue}
  350. selectObject={selectObject}
  351. variant={variant}
  352. maxDate={maxDate}
  353. minDate={minDate}
  354. timeType="hours"
  355. />
  356. <Text
  357. variant="titleMediumSize"
  358. style={{
  359. ...stylesheet.colonText,
  360. ...colonTextDynamicStyle
  361. }}
  362. >
  363. :
  364. </Text>
  365. <TimeInput
  366. initialValue={date?.getMinutes().toString().padStart(2, "0")}
  367. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  368. selectMultipleObject={selectMultipleObject}
  369. setDateRangeValue={setDateRangeValue}
  370. setDateValue={setDateValue}
  371. selectObject={selectObject}
  372. timeType="minutes"
  373. variant={variant}
  374. maxDate={maxDate}
  375. minDate={minDate}
  376. />
  377. {
  378. isWorkWithSeconds ?
  379. <Fragment>
  380. <Text
  381. variant="titleMediumSize"
  382. style={{
  383. ...stylesheet.colonText,
  384. ...colonTextDynamicStyle
  385. }}
  386. >
  387. :
  388. </Text>
  389. <TimeInput
  390. initialValue={date?.getSeconds().toString().padStart(2, "0")}
  391. isWorkWith24HoursFormat={isWorkWith24HoursFormat}
  392. selectMultipleObject={selectMultipleObject}
  393. setDateRangeValue={setDateRangeValue}
  394. setDateValue={setDateValue}
  395. selectObject={selectObject}
  396. timeType="seconds"
  397. variant={variant}
  398. maxDate={maxDate}
  399. minDate={minDate}
  400. />
  401. </Fragment>
  402. :
  403. null
  404. }
  405. </View>
  406. </View>;
  407. };
  408. return <View
  409. style={[
  410. stylesheet.container,
  411. containerDynamicStyle
  412. ]}
  413. >
  414. {renderTimeInputs()}
  415. </View>;
  416. };
  417. export default TimeSelector;