Advertisement
Guest User

ps

a guest
Dec 6th, 2019
362
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.53 KB | None | 0 0
  1. import React from 'react';
  2. import { StyleSheet, View, ScrollView, SafeAreaView, Text, Alert, Modal, TouchableOpacity, Picker, RefreshControl, ActivityIndicator } from 'react-native';
  3. import { NavigationScreenProp } from 'react-navigation';
  4. import CustomHeader from "../custom/CustomHeader";
  5. import css from '../../constants/Css';
  6. import color from '../../constants/Colors';
  7. import { RFValue } from 'react-native-responsive-fontsize';
  8. import FAButton from '../custom/FAButton';
  9. import Screen from '../../common/components/screens/Screen';
  10. import { DataColumn } from '../../common/components/widgets/table/column/DataColumn';
  11. import { ActionColumn } from '../../common/components/widgets/table/column/ActionColumn';
  12. import * as WebBrowser from 'expo-web-browser';
  13. import ReduxComponentWrapper from '../../common/components/widgets/reduxConnected/ReduxComponentWrapper';
  14. import { IRestDataSourceParams } from '../../common/dataSource/IRestDataSourceParams';
  15. import { Table as TableModel } from '../../common/components/widgets/table/Table';
  16. import { SupplierMeeting, ISupplierMetting } from '../models/SupplierMeeting';
  17. import { File as FileModel } from '../models/File';
  18. import { DataProvider } from '../../common/model/DataProvider';
  19. import { TextInput } from '../../common/components/widgets/form/input/TextInput';
  20. import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
  21. import { faCloudDownloadAlt, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons';
  22. import { CustomActionColumn } from '../custom/CustomActionColumn';
  23. import moment from 'moment';
  24. import { BasicFilter } from '../../common/components/widgets/table/filter/BasicFilter';
  25. import { BasicPaging, PagerSize } from '../../common/components/widgets/table/paging/BasicPaging';
  26. import { AxiosResponse, AxiosError } from 'axios';
  27. import { Supplier } from '../models/Supplier';
  28. import { DropdownInput } from '../../common/components/widgets/form/input/DropdownInput';
  29. import * as DocumentPicker from 'expo-document-picker';
  30. import Util from '../custom/Util';
  31. import { DateInput } from '../../common/components/widgets/form/input/DateInput';
  32.  
  33.  
  34. interface IMeetingsScreenProps {
  35. navigation: NavigationScreenProp<any, any>
  36. }
  37.  
  38. interface IMeetingsScreenComponent {
  39. isLoading: boolean,
  40. refreshing: boolean,
  41.  
  42. isEditLoading: boolean,
  43.  
  44. showForm: boolean,
  45. currentModel: any,
  46. visibleModal: string | null,
  47. textInputValue: string,
  48. fileUrl: string | null,
  49. countries: any[],
  50. supplierList: any[],
  51. isCreate: boolean,
  52.  
  53. file: any,
  54. waitForUpload: boolean,
  55.  
  56. selectedSupplierOption: string
  57. selectedDateOption: string | boolean
  58. }
  59.  
  60. export class MeetingsScreen extends Screen<IMeetingsScreenProps, IMeetingsScreenComponent>{
  61.  
  62. private supplierMeetings = new SupplierMeeting(false);
  63. private supplierModel = new Supplier(false);
  64. private meetingsDP = new DataProvider<ISupplierMetting>();
  65. private fileModel: FileModel = new FileModel();
  66.  
  67. private submitted = false;
  68.  
  69. private supplierMeetingInputs: { [attr: string]: React.RefObject<any> } = {
  70. supplier_id: React.createRef(),
  71. supplier_attendants: React.createRef(),
  72. vl_attendants: React.createRef(),
  73. subject: React.createRef(),
  74. meeting_location: React.createRef(),
  75. meeting_date: React.createRef(),
  76. attachment: React.createRef(),
  77. };
  78.  
  79. private httpReq = [];
  80.  
  81. constructor(props) {
  82. super(props);
  83.  
  84. this.delete = this.delete.bind(this);
  85. this.readInputs = this.readInputs.bind(this);
  86. this.fillInputsWithErrors = this.fillInputsWithErrors.bind(this);
  87. this.handleSubmit = this.handleSubmit.bind(this);
  88. this.setInputValues = this.setInputValues.bind(this);
  89. this.addFile = this.addFile.bind(this);
  90. this.removeFile = this.removeFile.bind(this);
  91. this.sendReq = this.sendReq.bind(this);
  92. this.searchCallback = this.searchCallback.bind(this)
  93.  
  94. this.state = {
  95. refreshing: false,
  96. isLoading: true,
  97.  
  98. isEditLoading: true,
  99.  
  100. showForm: false,
  101. currentModel: null,
  102. visibleModal: null,
  103. textInputValue: '',
  104.  
  105. file: null,
  106. fileUrl: null,
  107. countries: [],
  108. supplierList: [],
  109.  
  110.  
  111. waitForUpload: false,
  112.  
  113. selectedSupplierOption: null,
  114. selectedDateOption: null,
  115. isCreate: true
  116. }
  117. this.openModal = this.openModal.bind(this)
  118. this.edit = this.edit.bind(this)
  119. }
  120.  
  121. openModal(row?) {
  122.  
  123. this.setState({
  124. showForm: !this.state.showForm,
  125. isEditLoading: false,
  126. currentModel: row && null
  127. })
  128.  
  129. this.searchCallback = this.searchCallback.bind(this)
  130. }
  131.  
  132. delete(row) {
  133.  
  134. Alert.alert(
  135. 'Delete',
  136. 'Are you sure you want to delete this?',
  137. [
  138. { text: 'Cancel', onPress: () => { this.setState({ showForm: false }) }, style: 'cancel', },
  139. {
  140. text: 'Delete', onPress: () => {
  141. this.supplierMeetings.del(row.id);
  142. this.setState({ currentModel: null })
  143. }, style: 'destructive'
  144. },
  145. ],
  146. { cancelable: false },
  147. );
  148.  
  149. }
  150.  
  151.  
  152. setInputValues(values: any) {
  153. let inputs = this.supplierMeetingInputs;
  154.  
  155. for (let key in values) {
  156. if (inputs[key] && inputs[key].current) {
  157. inputs[key].current.setValue(values[key]);
  158. }
  159. }
  160. }
  161.  
  162. private readInputs(): any {
  163.  
  164. const plainObject = {};
  165. const inputs = this.supplierMeetingInputs;
  166.  
  167. for (const key in inputs) {
  168.  
  169. if (inputs.hasOwnProperty(key) && inputs[key].current) {
  170.  
  171. plainObject[key] = inputs[key].current.getValue();
  172. inputs[key].current.removeError();
  173. }
  174. }
  175.  
  176. this.supplierMeetings.setFromPlainObject({ ...this.supplierMeetings.asPlainObject(), ...plainObject });
  177.  
  178. return plainObject;
  179. }
  180.  
  181.  
  182. addFile = async (ref: React.RefObject<any>, event) => {
  183.  
  184. return await DocumentPicker.getDocumentAsync({ type: 'application/pdf' })
  185. .then((file) => {
  186.  
  187. if (file.type === 'success') {
  188. ref.current.setValue(file.name)
  189. }
  190.  
  191. this.setState({ file })
  192.  
  193. });
  194. }
  195.  
  196. removeFile(ref: React.RefObject<any>, e) {
  197. const inputElement: HTMLInputElement = document.getElementById(ref.current.props.id) as HTMLInputElement
  198.  
  199. inputElement.value = ''
  200.  
  201. ref.current.setValue(null);
  202. this.supplierMeetings.attachment = null;
  203.  
  204. this.supplierMeetings.update(this.supplierMeetings).then((response: AxiosResponse) => {
  205. Util.notification('Meeting successfully updated')
  206. this.setState({
  207. showForm: false
  208. })
  209.  
  210. });
  211. }
  212.  
  213.  
  214. private fillInputsWithErrors(errors: { [attr: string]: string }, inputs: any) {
  215.  
  216. for (const key in errors) {
  217. if (errors.hasOwnProperty(key) && inputs[key] !== undefined && inputs[key].current) {
  218. inputs[key].current.setError(errors[key]);
  219. }
  220. }
  221. }
  222.  
  223. private validate(event: any): boolean {
  224. this.readInputs();
  225. let inputs = this.supplierMeetingInputs;
  226. const valid = this.supplierMeetings.validate();
  227.  
  228. if (this.submitted && !valid) {
  229. const errors: { [attr: string]: string } = this.supplierMeetings.getErrors();
  230. this.fillInputsWithErrors(errors, inputs);
  231. }
  232.  
  233. event.preventDefault();
  234.  
  235. return valid;
  236. }
  237.  
  238.  
  239. sendReq() {
  240. let promise: Promise<AxiosResponse>;
  241.  
  242. if (this.state.isCreate) {
  243. promise = this.supplierMeetings.createNew();
  244. } else {
  245. promise = this.supplierMeetings.update(this.supplierMeetings);
  246. }
  247.  
  248. promise.then((response: AxiosResponse) => {
  249.  
  250. this.setState({ waitForUpload: false }) // ??
  251. this.setState({ showForm: false, selectedSupplierOption: '', selectedDateOption: '', isEditLoading: true }) // ??
  252.  
  253. Util.notification('Success')
  254.  
  255. })
  256. .catch((error: AxiosError) => {
  257. const aError: AxiosError = error;
  258.  
  259. switch (aError.response.status) {
  260. case 422:
  261.  
  262. if (aError.response && aError.response.data && aError.response.data.errors) {
  263. const respErrors: any[] = aError.response.data.errors;
  264. const errors: { [attr: string]: string } = {};
  265.  
  266. respErrors.forEach((error: any) => {
  267. errors[error.fieldName] = error.errorMessage;
  268. });
  269.  
  270. this.fillInputsWithErrors(errors, this.supplierMeetingInputs);
  271. }
  272. break;
  273. default:
  274.  
  275. Util.notification('Error', 'danger')
  276. break;
  277. }
  278.  
  279. this.setState({ selectedSupplierOption: '', selectedDateOption: '' })
  280. });
  281. }
  282.  
  283. handleSupplierChange = (selectedOption: any, ref: any) => {
  284. let value = selectedOption;
  285.  
  286. this.setState({
  287. selectedSupplierOption: value
  288. });
  289.  
  290. ref.current.setValue(value)
  291.  
  292. }
  293.  
  294. handleDateChange = (selectedOption: any, ref: any) => {
  295. let value = selectedOption;
  296.  
  297. this.setState({
  298. selectedDateOption: value
  299. });
  300.  
  301. ref.current.setValue(value)
  302.  
  303. }
  304.  
  305. uploadFilesToServer() {
  306. let data = new FormData();
  307.  
  308. let file = this.state.file;
  309.  
  310. file = {
  311. name: file.name,
  312. uri: file.uri,
  313. type: 'application/pdf'
  314. }
  315.  
  316. if (file) {
  317. data.append('files', file, file.name);
  318.  
  319. this.fileModel.createNew(data).then((response: AxiosResponse) => {
  320.  
  321. let files: string[] = response.data;
  322. this.setState({
  323. fileUrl: files[0]
  324. })
  325. })
  326. }
  327. }
  328.  
  329.  
  330. protected handleSubmit(event: any): void {
  331.  
  332. this.submitted = true;
  333.  
  334. if (this.validate(event)) {
  335.  
  336. if (this.state.file) {
  337.  
  338. this.uploadFilesToServer();
  339. this.setState({
  340. waitForUpload: true
  341. })
  342.  
  343. setTimeout(() => {
  344.  
  345. this.supplierMeetings.attachment = this.state.fileUrl;
  346.  
  347. this.sendReq()
  348. }, 1000);
  349. } else {
  350. this.sendReq()
  351. }
  352. }
  353.  
  354. this.submitted = false;
  355. }
  356.  
  357.  
  358.  
  359. getDestroyableMembers() {
  360. return [];
  361. }
  362.  
  363. searchCallback() {
  364.  
  365. if (this.state.isCreate) return (params: IRestDataSourceParams): void => {
  366.  
  367. if (!params.filters) {
  368. params.filters = [{
  369. attr: "meeting_date",
  370. operator: "gte",
  371. val: moment().format("YYYY-MM-DD")
  372. }]
  373. }
  374. this.meetingsDP.refreshWithHeaders(
  375. this.supplierMeetings.getListPlain({
  376. ...params,
  377. sort: {
  378. attr: "meeting_date",
  379. ascending: false
  380. }
  381. })
  382. )
  383. }
  384. }
  385.  
  386.  
  387. edit(row?: any) {
  388. this.supplierMeetings.loadById(row.id)
  389. .then((response: any) => {
  390.  
  391. this.supplierMeetings.setFromPlainObject(response);
  392. this.setInputValues(response);
  393.  
  394. this.setState({
  395. selectedSupplierOption: response.supplier_id,
  396. selectedDateOption: response.meeting_date
  397. });
  398.  
  399. }).then(() => {
  400. this.setState({
  401. isEditLoading: false
  402. });
  403. })
  404. .catch((error: AxiosError) => {
  405. Util.notification('Data could not be loaded', 'danger')
  406. });
  407.  
  408. this.setState({
  409. showForm: !this.state.showForm,
  410. currentModel: row && null,
  411. isCreate: !this.state.isCreate
  412. });
  413. }
  414.  
  415. catchData() {
  416. this.httpReq.push(this.supplierModel.getListPlain({
  417. sort: {
  418. attr: "name",
  419. ascending: true
  420. }
  421. })
  422. .then((response: AxiosResponse) => {
  423. this.setState({
  424. supplierList: response.data,
  425. isLoading: false
  426. });
  427.  
  428. }).catch((e: AxiosError) => {
  429. Util.notification('Supplier list cannot be loaded', 'danger')
  430. })
  431. )
  432.  
  433. return Promise.all(this.httpReq).then((results) => {
  434. this.setState({
  435. isLoading: false
  436. });
  437. });
  438. }
  439.  
  440. componentDidMount() {
  441. this.catchData()
  442. }
  443.  
  444. render() {
  445.  
  446. const colsMeeting: any[] = [
  447. new DataColumn('Subject', 'subject', null, new BasicFilter(false, 'Search meetings'), true),
  448. new DataColumn('Date', 'meeting_date', null, null),
  449. new DataColumn('Supplier', 'supplier.name', null, null),
  450. new DataColumn('Supplier attenddants', 'supplier_attendants', null, null),
  451. new DataColumn('VL attenddants', 'vl_attendants', null, null),
  452. new DataColumn('Location', 'meeting_location', null, null),
  453. new CustomActionColumn(
  454. null,
  455. (row: Object) => {
  456. this.delete(row)
  457. },
  458. (row: Object) => {
  459. this.edit(row)
  460. },
  461. 10,
  462. false
  463. ),
  464. new ActionColumn("", null, null, 10,
  465. [{
  466. operationCb: async (row: any) => {
  467. if (row.attachment) {
  468.  
  469. await WebBrowser.openBrowserAsync(row.attachment);
  470. } else {
  471. alert("No attachments")
  472. }
  473. },
  474. iconClassName: "table-edit",
  475. message: null,
  476. icon: <FontAwesomeIcon icon={faCloudDownloadAlt} size={RFValue(23, css.standardScreenHeight)} style={styles.icon} />,
  477. iconStyle: {}
  478. }],
  479. "File"
  480. )
  481. ];
  482.  
  483. let supplierList = [];
  484.  
  485. if (this.state.supplierList) {
  486. for (let i = 0; i < this.state.supplierList.length; i++) {
  487. supplierList.push({
  488. key: this.state.supplierList[i].id,
  489. value: this.state.supplierList[i].id,
  490. label: this.state.supplierList[i].name,
  491. });
  492. }
  493. }
  494.  
  495. let form
  496. form = (
  497. <Modal transparent={true} animationType="slide">
  498. <View style={[{ height: '100%', width: '100%', position: 'absolute', justifyContent: 'center', alignItems: 'center' }, [!this.state.isEditLoading ? { display: 'none' } : {}]]}>
  499. <ActivityIndicator size="large" color={color.primary} />
  500. </View>
  501. <ScrollView>
  502. <View style={this.state.isEditLoading ? { display: 'none' } : {}}>
  503. <View style={styles.modalBox}>
  504.  
  505. <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
  506.  
  507. <Text style={styles.modalTitle}>Edit meeting</Text>
  508.  
  509. <TextInput style={styles.modalInputBox}
  510. ref={this.supplierMeetingInputs.subject}
  511. placeholder="Subject"
  512. placeholderTextColor={color.primaryBlue}
  513. selectionColor="#fff"
  514. />
  515.  
  516. <DropdownInput
  517. listItems={supplierList}
  518. ref={this.supplierMeetingInputs.supplier_id}
  519. initialValue={this.state.selectedSupplierOption}
  520. placeholder={{label: 'Supplier', value: null} }
  521. label=""
  522. onChange={(option) => { this.handleSupplierChange(option, this.supplierMeetingInputs.supplier_id) }}
  523. />
  524.  
  525. <DateInput
  526. ref={this.supplierMeetingInputs.meeting_date}
  527. initialValue={this.state.selectedDateOption}
  528. onChange={(option) => { this.handleDateChange(option, this.supplierMeetingInputs.meeting_date) }}
  529. mode="date"
  530. format="YYYY-MM-DD"
  531. confirmBtnText="Confirm"
  532. cancelBtnText="Cancel"
  533. />
  534.  
  535. <TextInput style={styles.modalInputBox}
  536. placeholder="Supplier attendants"
  537. ref={this.supplierMeetingInputs.supplier_attendants}
  538. placeholderTextColor={color.primaryBlue}
  539. selectionColor="#fff"
  540. />
  541.  
  542. <TextInput style={styles.modalInputBox}
  543. placeholder="VL attendants"
  544. ref={this.supplierMeetingInputs.vl_attendants}
  545. placeholderTextColor={color.primaryBlue}
  546. selectionColor="#fff"
  547. />
  548.  
  549.  
  550. <TextInput style={styles.modalInputBox}
  551. placeholder="Location"
  552. ref={this.supplierMeetingInputs.meeting_location}
  553. placeholderTextColor={color.primaryBlue}
  554. selectionColor="#fff"
  555. />
  556.  
  557. <View style={{ justifyContent: 'center', alignItems: 'center' }}>
  558.  
  559. <TextInput style={styles.modalInputBox}
  560. placeholder="Attachment"
  561. ref={this.supplierMeetingInputs.attachment}
  562. placeholderTextColor={color.primaryBlue}
  563. selectionColor="#fff"
  564. disabled={true}
  565. />
  566.  
  567. <FontAwesomeIcon onPress={(e) => this.addFile(this.supplierMeetingInputs.attachment, e)}
  568. style={styles.uploadFile}
  569. icon={faPlus} size={RFValue(20, css.standardScreenHeight)} />
  570.  
  571.  
  572. <FontAwesomeIcon icon={faTrash} size={RFValue(20, css.standardScreenHeight)} style={styles.deleteFile} />
  573.  
  574.  
  575. </View>
  576.  
  577. <TouchableOpacity onPress={(e) => this.handleSubmit(e)} style={[styles.button, { backgroundColor: color.primary }]}>
  578. <Text style={[styles.buttonText, { color: color.whiteInput }]}>Submit</Text>
  579. </TouchableOpacity>
  580.  
  581. <TouchableOpacity onPress={() => { this.setState({ showForm: false, isEditLoading: true, selectedDateOption: '', selectedSupplierOption: '' }) }} style={[styles.button, { backgroundColor: color.whiteInput }]}>
  582. <Text style={[styles.buttonText, { color: color.primary }]}>Cancel</Text>
  583. </TouchableOpacity>
  584.  
  585. </View>
  586. </View>
  587. </View>
  588. </ScrollView>
  589.  
  590. </Modal>
  591. )
  592.  
  593. let content;
  594. if (!this.state.isLoading) {
  595. content = (
  596. <>
  597. <ScrollView style={styles.scrollView}
  598. refreshControl={<RefreshControl refreshing={this.state.refreshing} onRefresh={() => { this.refresh() }} />}>
  599. <ReduxComponentWrapper component={TableModel} componentPropsCallback={(state: any) => ({
  600. provider: this.meetingsDP,
  601. title: null,
  602. searchCallback: this.searchCallback(),
  603. columns: colsMeeting,
  604. loader: [4, 10],
  605. // paging: new BasicPaging({
  606. // pageSize: 2,
  607. // pagerSize: PagerSize.LARGE
  608. // })
  609. })} />
  610. </ScrollView>
  611.  
  612. <FAButton function={() => this.openModal()} />
  613.  
  614. {this.state.showForm ? form : null}
  615. </>
  616. )
  617. } else {
  618. content = (
  619. <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
  620. <ActivityIndicator size="large" color={color.primary} />
  621. </View>
  622. )
  623. }
  624.  
  625.  
  626. return (
  627. <SafeAreaView style={styles.container} >
  628. <CustomHeader navigation={this.props.navigation} withBack={true} name="Meetings" marginBottom={-1} />
  629.  
  630. {content}
  631.  
  632. </SafeAreaView >
  633. );
  634. }
  635. }
  636.  
  637.  
  638. const styles = StyleSheet.create({
  639. icon: {
  640. color: color.primaryBlue,
  641. marginHorizontal: 10
  642. },
  643. container: {
  644. flex: 1,
  645. backgroundColor: color.backgroundColor
  646. },
  647. scrollView: {
  648. paddingBottom: 10,
  649. },
  650. searchBox: {
  651. backgroundColor: "white",
  652. marginBottom: 15
  653. },
  654. searchInput: {
  655. backgroundColor: color.backgroundColor,
  656. marginVertical: 5,
  657. marginHorizontal: 20,
  658. paddingHorizontal: 10,
  659. borderRadius: 10,
  660. fontSize: RFValue(css.defaultFontSize, css.standardScreenHeight)
  661. },
  662. modalBox: {
  663. flex: 1,
  664. backgroundColor: 'white',
  665. margin: 5,
  666. padding: css.defaultPadding,
  667. borderRadius: css.appBorderRadius,
  668. shadowColor: "#000",
  669. shadowOffset: {
  670. width: 0,
  671. height: 1,
  672. },
  673. shadowOpacity: 0.18,
  674. shadowRadius: 1.00,
  675. elevation: 1,
  676. },
  677. modalTitle: {
  678. color: color.primary,
  679. fontSize: RFValue(css.defaultTitleFontSize, css.standardScreenHeight),
  680. fontWeight: "bold"
  681. },
  682. modalInputBox: {
  683. width: 300,
  684. backgroundColor: color.backgroundColor,
  685. borderRadius: css.inputBorderRadius,
  686. paddingHorizontal: 16,
  687. paddingVertical: 12,
  688. fontSize: RFValue(css.defaultFontSize, css.standardScreenHeight),
  689. color: color.blackInput,
  690. marginVertical: 10,
  691. },
  692. button: {
  693. width: 300,
  694. backgroundColor: color.primary,
  695. borderRadius: css.buttonBorderRadius,
  696. marginVertical: 10,
  697. paddingVertical: 12
  698. },
  699. buttonText: {
  700. fontSize: RFValue(css.defaultFontSize, css.standardScreenHeight),
  701. fontWeight: '500',
  702. color: '#ffffff',
  703. textAlign: 'center'
  704. },
  705. uploadFile: {
  706. position: 'absolute',
  707. right: RFValue(50, css.standardScreenHeight)
  708. },
  709. deleteFile: {
  710. position: 'absolute',
  711. right: RFValue(15, css.standardScreenHeight),
  712. }
  713. });
  714.  
  715.  
  716.  
  717. ---- *----
  718.  
  719.  
  720.  
  721. import * as React from 'react';
  722. import { FormInput, IFormInputProps } from "../FormInput";
  723. import Colors from '../../../../../constants/Colors';
  724. import { TextInput } from './TextInput';
  725. import ModalSelector from 'react-native-modal-selector';
  726. import Css from '../../../../../constants/Css';
  727. import { RFValue } from 'react-native-responsive-fontsize';
  728. import { StyleSheet, Text, Picker, View, Modal, Platform } from 'react-native';
  729. import DatePicker from 'react-native-datepicker'
  730.  
  731. export interface IDateInputProps extends IFormInputProps {
  732. label?: string,
  733. placeholder?: string,
  734. error?: string,
  735. id?: string,
  736. mode?: string
  737. format?: string
  738. confirmBtnText?: string,
  739. cancelBtnText?: string
  740. }
  741.  
  742. export class DateInput<T extends IDateInputProps = IDateInputProps> extends TextInput<T> {
  743. protected renderLabel(): React.ReactNode {
  744. return;
  745. }
  746.  
  747. protected renderInput(): React.ReactNode {
  748. const additionalProps: any = {};
  749.  
  750. return (
  751. <>
  752. <View style={[styles.viewDateInputBox, this.error !== null ? styles.errorInput : null]}>
  753. <DatePicker
  754. style={styles.dateInputBox} //with props
  755. onDateChange={this.props.onChange}
  756. date={this.props.initialValue}
  757. mode={this.props.mode}
  758. placeholder={"Date"}
  759. format={this.props.format}
  760. confirmBtnText={this.props.confirmBtnText}
  761. cancelBtnText={this.props.cancelBtnText}
  762. showIcon={false}
  763. customStyles={{ //with props
  764. dateInput: {
  765. borderWidth: 0,
  766. alignItems: "flex-start",
  767. },
  768. placeholderText: {
  769. fontSize: RFValue(Css.defaultFontSize, Css.standardScreenHeight),
  770. color: Colors.primaryBlue,
  771. },
  772. dateText: {
  773. fontSize: RFValue(Css.defaultFontSize, Css.standardScreenHeight),
  774. color: Colors.blackInput,
  775. }
  776. }}
  777. />
  778. </View>
  779. <TextInput
  780. id={this.props.id}
  781. ref={this.inputRef}
  782. style={styles.hidden}
  783. value={this.props.initialValue ? this.props.initialValue.toString() : this.props.initialValue}
  784. />
  785. </>
  786.  
  787. );
  788. }
  789.  
  790. public getValue(): any {
  791.  
  792. return this.props.initialValue;
  793. }
  794.  
  795. protected renderError(): React.ReactNode {
  796.  
  797. return (<Text style={(this.error !== null) ? { color: 'red', display: 'flex' } : { display: 'none' }}>{(this.error !== null) ? this.error : ""}</Text>);
  798. }
  799.  
  800. public getReadOnly(val: any): any {
  801. return;
  802. }
  803. }
  804.  
  805.  
  806. const styles = StyleSheet.create({
  807. dateInputBox: {
  808. width: 300,
  809. paddingHorizontal: 16,
  810. paddingVertical: Platform.OS === 'ios' ? 2 : 6,
  811. backgroundColor: "#f3f3f3",
  812. overflow: 'hidden',
  813. },
  814. viewDateInputBox: {
  815. borderRadius: Css.inputBorderRadius,
  816. overflow: 'hidden',
  817. marginVertical: 10,
  818. },
  819. hidden: {
  820. display: "none"
  821. },
  822. errorInput: {
  823. borderWidth: 1,
  824. borderColor: '#cc0000',
  825. },
  826. });
  827.  
  828.  
  829.  
  830. ---- ** ----
  831.  
  832.  
  833. import * as React from 'react';
  834. import { FormInput, IFormInputProps } from "../FormInput";
  835. import Colors from '../../../../../constants/Colors';
  836. import { TextInput } from './TextInput';
  837. import ModalSelector from 'react-native-modal-selector';
  838. import Css from '../../../../../constants/Css';
  839. import { RFValue } from 'react-native-responsive-fontsize';
  840. import { StyleSheet, Text, View } from 'react-native';
  841. import RNPickerSelect from 'react-native-picker-select';
  842.  
  843. export interface IDropdownListItem {
  844. value: number | string,
  845. label: string,
  846. key: number
  847. }
  848.  
  849. export interface IDropdownInputProps extends IFormInputProps {
  850. label?: string,
  851. placeholder?: any,
  852. error?: string,
  853. listItems?: IDropdownListItem[],
  854. noEmptyOption?: boolean,
  855. id?: string,
  856. }
  857.  
  858. export class DropdownInput<T extends IDropdownInputProps = IDropdownInputProps> extends TextInput<T> {
  859. protected renderLabel(): React.ReactNode {
  860. return;
  861. }
  862.  
  863. protected renderInput(): React.ReactNode {
  864. const additionalProps: any = {};
  865. let listItems: IDropdownListItem[] | undefined = [];
  866.  
  867. if (this.props.listItems && this.props.listItems.length) {
  868. for (let i = 0; i < this.props.listItems.length; i++) {
  869. listItems.push({
  870. value: this.props.listItems[i].value,
  871. label: this.props.listItems[i].label,
  872. key: this.props.listItems[i].key
  873. });
  874. }
  875. }
  876.  
  877. return (
  878. <View>
  879. <RNPickerSelect
  880. onValueChange={this.props.onChange}
  881. value={this.props.initialValue}
  882. items={listItems}
  883. style={{ inputAndroid: [styles.RNPicker, this.error !== null ? styles.errorInput : null], inputIOS: [styles.RNPickerIOS, this.error !== null ? styles.errorInput : null], placeholder: { color: Colors.primaryBlue } }}
  884. useNativeAndroidPickerStyle={false}
  885. placeholder={this.props.placeholder}
  886. />
  887.  
  888. <TextInput
  889. id={this.props.id}
  890. ref={this.inputRef}
  891. style={styles.hidden}
  892. value={this.props.initialValue ? this.props.initialValue.toString() : this.props.initialValue}
  893. />
  894. </View>
  895.  
  896. );
  897. }
  898.  
  899. public getValue(): any {
  900.  
  901. return this.props.initialValue;
  902. }
  903.  
  904. protected renderError(): React.ReactNode {
  905.  
  906. return (<Text style={(this.error !== null) ? { color: 'red', display: 'flex' } : { display: 'none' }}>{(this.error !== null) ? this.error : ""}</Text>);
  907. }
  908.  
  909. public getReadOnly(val: any): any {
  910. const listItems: IDropdownListItem[] | undefined = this.props.listItems ? this.props.listItems : [];
  911.  
  912. if (listItems) {
  913. if (listItems.length) {
  914. let result: any = '';
  915.  
  916. listItems.forEach((listItem: IDropdownListItem) => {
  917. if (listItem.key == val) {
  918. result = listItem.label;
  919. }
  920. });
  921.  
  922. return result;
  923. }
  924. }
  925.  
  926. return "";
  927. }
  928. }
  929.  
  930.  
  931. const styles = StyleSheet.create({
  932. hidden: {
  933. display: "none"
  934. },
  935. RNPicker: {
  936. fontSize: RFValue(Css.defaultFontSize, Css.standardScreenHeight),
  937. width: 300,
  938. paddingHorizontal: 16,
  939. paddingVertical: 11,
  940. backgroundColor: "#f3f3f3",
  941. color: Colors.blackInput,
  942. paddingRight: 30, // to ensure the text is never behind the icon
  943. borderRadius: Css.inputBorderRadius,
  944. overflow: 'hidden',
  945. marginVertical: 10,
  946. },
  947. RNPickerIOS: {
  948. fontSize: RFValue(Css.defaultFontSize, Css.standardScreenHeight),
  949. width: 300,
  950. paddingHorizontal: 16,
  951. paddingVertical: 12,
  952. backgroundColor: "#f3f3f3",
  953. color: Colors.blackInput,
  954. paddingRight: 30, // to ensure the text is never behind the icon
  955. borderRadius: Css.inputBorderRadius,
  956. overflow: 'hidden',
  957. marginVertical: 10,
  958. },
  959. errorInput: {
  960. borderWidth: 1,
  961. borderColor: '#cc0000',
  962. },
  963. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement