Skip to content

Instantly share code, notes, and snippets.

@andrewhl
Last active June 8, 2017 00:01
Show Gist options
  • Save andrewhl/61864bf936b4f1ccfd52bdf8e1a2ae20 to your computer and use it in GitHub Desktop.
Save andrewhl/61864bf936b4f1ccfd52bdf8e1a2ae20 to your computer and use it in GitHub Desktop.
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Container, Header, Left, Button, Body, Title, Right, Icon, Text } from 'native-base';
import { TouchableWithoutFeedback, Keyboard, Alert } from 'react-native';
import { getFormValues, isPristine, isValid } from 'redux-form';
import AddItemFormContainer from '../../components/AddItemFormContainer';
import * as itemsModule from '../../../../redux/modules/items';
import BackButton from './components/BackButton';
import SubmitButton from './components/SubmitButton';
import type {
Navigation,
navigationOptions,
navigationOptionsFunction,
} from '../../../../../types/navigation';
type props = {
navigation: Navigation,
screenProps: Array<mixed>,
};
export class AddItem extends Component {
props: props;
state = {
submitting: false,
};
componentWillReceiveProps(nextProps) {
if (nextProps.valid === this.props.valid) {
return;
}
this.props.navigation.setParams({
valid: this.props.valid,
values: this.props.values,
pristine: this.props.pristine,
addItem: this.props.addItem,
});
}
static navigationOptions: navigationOptionsFunction = ({ navigation }): navigationOptions => ({
title: 'Add item',
headerLeft: <BackButton form={navigation.state.params} navigation={navigation} />,
headerRight: <SubmitButton form={navigation.state.params} navigation={navigation} />,
});
render(): React.Element<*> {
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<Container>
<AddItemFormContainer ref={node => (this.form = node)} />
</Container>
</TouchableWithoutFeedback>
);
}
}
const mapStateToProps = (state: Object): Object => ({
values: getFormValues('addItem')(state),
pristine: isPristine('addItem')(state),
valid: isValid('addItem')(state),
items: state.items,
});
const mapDispatchToProps = {
addItem: itemsModule.add,
};
export default connect(mapStateToProps, mapDispatchToProps)(AddItem);
import React, { Component } from 'react';
import Collapsible from 'react-native-collapsible';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import moment from 'moment';
import { Field } from 'redux-form';
import { View, List, Item, Input, Picker, Text, Left, Body, ListItem } from 'native-base';
import { DatePickerIOS } from 'react-native';
import style from './style';
type props = {
input: {
onChange: () => void,
restInput: Array<mixed>,
},
};
const renderTitleField = ({ input: { onChange, ...restInput } }: props): React.Element<*> =>
<Input
style={style.inputField}
onChangeText={onChange}
placeholder="Title"
{...restInput}
/>;
const renderShapeField = ({ input: { onChange, ...restInput } }: props): React.Element<*> =>
<Picker
iosHeader="Shape"
mode="dropdown"
selectedValue={restInput.value}
onValueChange={onChange}
>
<Picker.Item label="Select" value="select" />
<Picker.Item label="Round" value="round" />
<Picker.Item label="Flat" value="flat" />
<Picker.Item label="Cubic" value="cubic" />
<Picker.Item label="Other" value="other" />
</Picker>;
const renderSizeField = ({ input: { onChange, ...restInput } }: props): React.Element<*> =>
<Picker
iosHeader="Size"
mode="dropdown"
selectedValue={restInput.value}
onValueChange={onChange}
>
<Picker.Item label="Select" value="select" />
<Picker.Item label="Big" value="big" />
<Picker.Item label="Small" value="small" />
<Picker.Item label="Other" value="other" />
</Picker>;
const renderCreatedAtField = ({ input: { onChange, ...restInput } }: props): React.Element<*> =>
<DatePickerIOS
date={new Date(restInput.value)}
mode="date"
onDateChange={onChange}
{...restInput}
/>;
const required = value => (value ? undefined : 'Required');
type formProps = {
created_at: Date,
};
class AddItemFormComponent extends Component {
props: formProps;
state = {
createdAtIsCollapsed: true,
};
render() {
return (
<View style={style.wrapper}>
<KeyboardAwareScrollView>
<List style={style.group}>
<ListItem style={style.formField}>
<Left>
<Text>Title</Text>
</Left>
<Body>
<Field
name="title"
component={renderTitleField}
validate={required}
/>
</Body>
</ListItem>
<ListItem>
<Left>
<Text>Shape</Text>
</Left>
<Body>
<Field
name="shape"
component={renderShapeField}
validate={required}
/>
</Body>
</ListItem>
<ListItem>
<Left>
<Text>Size</Text>
</Left>
<Body>
<Field
name="size"
component={renderSizeField}
validate={required}
/>
</Body>
</ListItem>
<ListItem noBorder onPress={this.toggleCreatedAt}>
<Left>
<Text>Created At</Text>
</Left>
<Body>
{this.renderCreatedAt()}
</Body>
</ListItem>
<Collapsible collapsed={this.state.createdAtIsCollapsed}>
<View>
<Field
name="created_at"
component={renderCreatedAtField}
validate={required}
/>
</View>
</Collapsible>
</List>
</KeyboardAwareScrollView>
</View>
);
}
renderCreatedAt() {
const createdAt = moment(this.props.created_at);
return <Text>{createdAt.format('LL')}</Text>;
}
toggleCreatedAt = () => {
this.setState({
createdAtIsCollapsed: ! this.state.createdAtIsCollapsed,
});
};
}
export default AddItemFormComponent;
import React from 'react';
import { reduxForm, formValueSelector } from 'redux-form';
import { connect } from 'react-redux';
import AddItemFormComponent from './AddItemFormComponent';
const validate = (values) => {
const errors = {};
if (values.size === 'select') {
errors.size = 'Please select a size.';
}
if (values.shape === 'select') {
errors.shape = 'Please select a shape.';
}
return errors;
};
let AddItemFormContainer: React.Element<*> = reduxForm({
form: 'addItem',
validate,
})(AddItemFormComponent);
const mapStateToProps = (state: Object): Object => {
const selector = formValueSelector('addItem');
const createdAt = selector(state, 'created_at');
return {
created_at: createdAt,
initialValues: {
created_at: new Date(),
shape: 'Select',
size: 'Select',
},
};
};
const mergeProps = (stateProps, dispatchProps, ownProps) =>
Object.assign({}, stateProps, dispatchProps, ownProps);
AddItemFormContainer = connect(mapStateToProps, null, mergeProps)(AddItemFormContainer);
export default AddItemFormContainer;
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Alert } from 'react-native';
import { View, Button, Text } from 'native-base';
import type { props } from './types';
import styles from './style';
class SubmitButton extends Component {
props: props;
state = {
submitting: false,
};
render() {
console.log(this.props.form);
return (
<View style={styles.container}>
<Button
transparent
disabled={this.state.submitting}
onPress={() => this.handleDone(this.props.form.values)}
>
<Text>Save</Text>
</Button>
</View>
);
}
handleDone = (): void => {
if (! this.props.form.valid) {
return;
}
this.setState({ submitting: true }, () => {
this.props.form.addItem(this.props.form.values);
});
};
}
export default SubmitButton;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment