FormInput.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /* eslint-disable react/jsx-props-no-spreading */
  2. /* eslint-disable no-shadow */
  3. /* eslint-disable no-underscore-dangle */
  4. /* eslint-disable no-restricted-syntax */
  5. import * as WebBrowser from "expo-web-browser";
  6. import * as React from "react";
  7. import { View, StyleSheet, TouchableWithoutFeedback } from "react-native";
  8. import {
  9. Layout,
  10. Input,
  11. Button,
  12. Icon,
  13. Text,
  14. SelectItem,
  15. } from "@ui-kitten/components";
  16. import { Cascader, BottomModal } from "beeshell";
  17. import { useModel } from "flooks";
  18. import moment from "moment";
  19. import OpenTime from "./OpenTime";
  20. import Datepicker from "./Datepicker";
  21. import UpLoadImage from "./UpLoadImage";
  22. import Actionsheet from "./Actionsheet";
  23. const styles = StyleSheet.create({
  24. inputContainer: {
  25. flexDirection: "row",
  26. alignItems: "center",
  27. paddingVertical: 10,
  28. paddingHorizontal: 4,
  29. },
  30. input: {
  31. flex: 1,
  32. },
  33. label: {
  34. width: 80,
  35. marginRight: 19,
  36. flexShrink: 0,
  37. },
  38. labelleft: {
  39. width: 73,
  40. flexShrink: 0,
  41. },
  42. right: {
  43. flexDirection: "row",
  44. },
  45. code: {
  46. paddingHorizontal: 5,
  47. marginLeft: 5,
  48. },
  49. selectContent: {
  50. backgroundColor: "#F0F0F0",
  51. },
  52. titleStyle: {
  53. fontSize: 15,
  54. },
  55. leftLabelTextStyle: {
  56. fontSize: 13,
  57. },
  58. rightLabelTextStyle: {
  59. fontSize: 13,
  60. },
  61. sub: {
  62. color: "#787878",
  63. position: "absolute",
  64. left: 90,
  65. zIndex: 2,
  66. },
  67. upload: {
  68. marginTop: 20,
  69. width: 67,
  70. height: 67,
  71. },
  72. });
  73. function* flattenSelect(array, key) {
  74. for (const item of array) {
  75. const _array = key ? item[key] : item;
  76. if (Array.isArray(_array) && _array.length > 0) {
  77. yield* flattenSelect(_array, key);
  78. } else {
  79. yield item;
  80. }
  81. }
  82. }
  83. const FormInput = React.memo(props => {
  84. const { appearance, type } = props;
  85. const [secureTextEntry, setSecureTextEntry] = React.useState(true);
  86. const { cancel, confirm } = useModel("wordsModel");
  87. const toggleSecureEntry = () => {
  88. setSecureTextEntry(!secureTextEntry);
  89. };
  90. // eslint-disable-next-line no-shadow
  91. const renderIcon = props => (
  92. <TouchableWithoutFeedback onPress={toggleSecureEntry}>
  93. <Icon {...props} name={secureTextEntry ? "eye-off" : "eye"} />
  94. </TouchableWithoutFeedback>
  95. );
  96. function getInputProps(props) {
  97. let _props = {
  98. value: props.value || "",
  99. placeholder: props.placeholder,
  100. };
  101. if (type === "phone") {
  102. _props = {
  103. ..._props,
  104. dataDetectorTypes: "phoneNumber",
  105. maxLength: 11,
  106. keyboardType: "phone-pad",
  107. };
  108. } else if (type === "password") {
  109. _props = {
  110. ..._props,
  111. accessoryRight: ImageProps => renderIcon(ImageProps),
  112. secureTextEntry,
  113. };
  114. } else if (type === "code") {
  115. _props = {
  116. ..._props,
  117. maxLength: 6,
  118. keyboardType: "numeric",
  119. };
  120. } else if (type === "amount" || props.type === "money") {
  121. _props = {
  122. ..._props,
  123. keyboardType: "numeric",
  124. };
  125. }
  126. if (props.onChange) {
  127. _props = {
  128. ..._props,
  129. onChangeText: nextValue => props.onChange(nextValue),
  130. };
  131. }
  132. return _props;
  133. }
  134. const inputProps = getInputProps(props);
  135. // const myInput = () => {
  136. // if (inputProps != null) {
  137. // return;
  138. // }
  139. // };
  140. const Label = ({ type, labelStyle, label }) => {
  141. return (
  142. <View
  143. style={[
  144. appearance === "inner" ? styles.labelleft : styles.label,
  145. type === "img" ? { alignSelf: "flex-start" } : {},
  146. labelStyle || {},
  147. ]}
  148. >
  149. <Text
  150. category="c1"
  151. style={{
  152. textAlign: appearance !== "inner" ? "right" : "left",
  153. }}
  154. >
  155. {label}
  156. </Text>
  157. </View>
  158. );
  159. };
  160. const ForwardIcon = props => <Icon {...props} name="arrow-ios-forward" />;
  161. const selectList = props.selectList ? props.selectList : [];
  162. const [bottomModalX, changeBottomModalx] = React.useState("");
  163. const [selectVal, setSelectVal] = React.useState("");
  164. const selectInfo = React.useMemo(() => {
  165. if (type === "select" && props.value && selectList.length > 0) {
  166. const childrens = [...flattenSelect(selectList, "children")];
  167. return (
  168. childrens.find(item => {
  169. return item.id === props.value;
  170. }) || { name: " " }
  171. );
  172. }
  173. return { name: " " };
  174. }, [props.value, props.type, selectList]);
  175. const [open, ChangeOpen] = React.useState(false);
  176. const Btn = ({ btnText }) => (
  177. <Button
  178. appearance="ghost"
  179. size="tiny"
  180. style={{ paddingVertical: 8, marginLeft: 5 }}
  181. >
  182. {btnText}
  183. </Button>
  184. );
  185. function getMain(type, props) {
  186. if (type === "select") {
  187. return (
  188. <>
  189. <SelectItem
  190. appearance="form"
  191. style={{ flex: 1 }}
  192. accessoryRight={ForwardIcon}
  193. title={selectInfo.name}
  194. onPress={() => {
  195. bottomModalX.open();
  196. }}
  197. />
  198. <BottomModal
  199. ref={c => {
  200. changeBottomModalx(c);
  201. }}
  202. title={props.selectTitle}
  203. titleStyle={styles.titleStyle}
  204. cancelable
  205. leftLabelText={cancel}
  206. leftLabelTextStyle={styles.leftLabelTextStyle}
  207. rightLabelText={confirm}
  208. rightLabelTextStyle={styles.rightLabelTextStyle}
  209. rightCallback={() => {
  210. props.onChange(selectVal);
  211. }}
  212. >
  213. <Cascader
  214. style={{
  215. width: "100%",
  216. height: 200,
  217. marginBottom: 50,
  218. minHeight: 200,
  219. }}
  220. data={selectList}
  221. fieldKeys={{
  222. labelKey: "name",
  223. idKey: "id",
  224. activeKey: "choose",
  225. }}
  226. onChange={value => {
  227. setSelectVal(value[0]);
  228. }}
  229. />
  230. </BottomModal>
  231. </>
  232. );
  233. }
  234. if (type === "openTime") {
  235. return (
  236. <OpenTime
  237. open={open}
  238. submit={(start, end, week) => {
  239. ChangeOpen(false);
  240. props.onChange(
  241. week.join(","),
  242. moment(start, "HH:mm").format("HH:mm:ss"),
  243. moment(end, "HH:mm").format("HH:mm:ss")
  244. );
  245. }}
  246. cancelEvent={() => {
  247. ChangeOpen(false);
  248. }}
  249. openModal={() => {
  250. ChangeOpen(true);
  251. }}
  252. week={props.week}
  253. startTime={props.startTime}
  254. endTime={props.endTime}
  255. />
  256. );
  257. }
  258. if (type === "date") {
  259. return <Datepicker chooseDate={props.onChange} value={props.value} />;
  260. }
  261. if (type === "url") {
  262. return (
  263. <SelectItem
  264. appearance="form"
  265. style={{ flex: 1 }}
  266. accessoryRight={ForwardIcon}
  267. title={props.value || " "}
  268. onPress={props.changePath}
  269. />
  270. );
  271. }
  272. if (type === "actionSheet") {
  273. return (
  274. <>
  275. <Actionsheet
  276. list={props.list}
  277. value={props.value}
  278. onChange={props.onChange}
  279. />
  280. </>
  281. );
  282. }
  283. if (type === "img") {
  284. return (
  285. <UpLoadImage
  286. style={styles.upload}
  287. value={props.value}
  288. changeIcon={props.onChange}
  289. />
  290. );
  291. }
  292. if (appearance === "inner" && type === "code") {
  293. return (
  294. <Input
  295. {...inputProps}
  296. accessoryLeft={leftprops => <Label {...props} {...leftprops} />}
  297. accessoryRight={() => <Btn btnText={props.btnText} />}
  298. size="small"
  299. style={styles.input}
  300. appearance="innerCode"
  301. />
  302. );
  303. }
  304. if (appearance === "inner") {
  305. return (
  306. <Input
  307. {...inputProps}
  308. accessoryLeft={leftprops => <Label {...props} {...leftprops} />}
  309. size="small"
  310. style={styles.input}
  311. appearance="inner"
  312. />
  313. );
  314. }
  315. return <Input {...inputProps} size="small" style={styles.input} />;
  316. }
  317. return (
  318. <Layout
  319. level="1"
  320. style={[
  321. styles.inputContainer,
  322. { ...props.style },
  323. props.type === "img" ? { flexDirection: "column" } : {},
  324. { paddingVertical: appearance === "inner" ? 0 : 10 },
  325. ]}
  326. >
  327. {appearance !== "inner" && <Label {...props} />}
  328. {(!props.value || props.value === " ") && (
  329. <Text category="c1" style={styles.sub}>
  330. {props.sub}
  331. </Text>
  332. )}
  333. {getMain(props.type, props)}
  334. {appearance !== "inner" && props.type === "code" && Btn(props)}
  335. </Layout>
  336. );
  337. });
  338. export default FormInput;