aretherecookies-mobile/js/pages/CreateFoodItem.js

192 lines
5.1 KiB
JavaScript

// @flow
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import theme from '../ui-theme';
import { Divider } from 'react-native-material-ui';
import FoodItemRecord from '../records/FoodItemRecord';
import PlaceRecord from '../records/PlaceRecord';
import NameModal from '../modals/FoodItemNameModal';
import ImagePreviewModal from '../modals/ImagePreviewModal';
import QuantityPicker from '../components/QuantityPicker';
import {
compose,
branch,
withState,
withHandlers,
renderComponent,
mapProps,
lifecycle,
} from 'recompose';
import RNGooglePlaces from 'react-native-google-places';
import CategoryPicker from '../components/CategoryPicker';
import { ImageThumb, ImagePicker } from '../components/ImagePicker';
import { withCreateFoodItemState } from '../enhancers/createFoodItemEnhancers';
import { withPlaceForFoodItem, withPlaceId, withPlaceActions } from '../enhancers/placeEnhancers';
import Spinner from 'react-native-loading-spinner-overlay';
import { openImagePicker } from '../helpers/ImagePickerHelpers';
import { IndexedSeq } from 'immutable';
import Snackbar from 'react-native-snackbar';
type Props = {
foodItem: typeof FoodItemRecord,
setPropOfFoodItem: Function,
toggleNameModal: Function,
setFoodItem: Function,
setModalsVisible: Function,
place: ?PlaceRecord,
updatePlace: (place: GooglePlaceObject) => void,
addImage: (uri: string) => void,
setImagePreview: (index?: number) => void,
loading: boolean,
setLoading: (arg: boolean) => void,
emitPlace: (place: Object) => void,
withFoodItemsAsSeq: IndexedSeq<FoodItemRecord>,
};
type GooglePlaceObject = {
placeID: string,
latitude: number,
longitude: number,
name: string,
address: string,
};
const fieldStyle = {
paddingTop: 10,
};
const fieldNameStyle = {
fontSize: 18,
paddingBottom: 10,
paddingLeft: 10,
};
const Field = ({ onPress, text = '' }: { onPress?: Function, text: string }) => (
<TouchableOpacity style={fieldStyle} onPress={onPress}>
<Text style={fieldNameStyle}>{text}</Text>
<Divider />
</TouchableOpacity>
);
const openPlaceModal = (onChoosePlace: (place: GooglePlaceObject) => void) => () => {
RNGooglePlaces.openAutocompleteModal({ type: 'establishment' }).then(onChoosePlace);
};
const CreateFoodItem = (props: Props) => {
const {
foodItem,
toggleNameModal,
setPropOfFoodItem,
updatePlace,
addImage,
setImagePreview,
loading,
place,
} = props;
return (
<View style={{ ...theme.page.container, backgroundColor: 'white', padding: 10 }}>
<Spinner visible={loading} />
<Field text={foodItem.name || 'Name'} onPress={toggleNameModal} />
<Field text={(place && place.name) || 'Place'} onPress={openPlaceModal(updatePlace)} />
<CategoryPicker
selected={foodItem.category}
onValueChange={setPropOfFoodItem('category')}
style={{ height: 50 }}
/>
<Divider />
<QuantityPicker
quantity={foodItem.quantity}
onValueChange={setPropOfFoodItem('quantity')}
style={{ height: 50 }}
/>
<Divider />
<ImagePicker onCreateNew={addImage}>
{foodItem.images.map((image, index) => (
<ImageThumb key={index} uri={image} onPress={() => setImagePreview(index)} />
))}
</ImagePicker>
</View>
);
};
const NameModalComp = compose(
renderComponent,
mapProps(({ toggleNameModal, setPropOfFoodItem }: Props) => {
return {
onClose: toggleNameModal,
onUpdate: setPropOfFoodItem('name'),
};
})
)(NameModal);
const ImagePreviewComp = compose(
renderComponent,
mapProps(({ foodItem, setFoodItem, setImagePreview, imagePreview }) => {
return {
onClose: () => setImagePreview(-1),
onDelete: () => {
setFoodItem(foodItem.deleteIn(['images', imagePreview]));
setImagePreview(-1);
},
imageSrc: foodItem.images.get(imagePreview),
};
})
)(ImagePreviewModal);
const setPropOfFoodItem = ({ foodItem, setFoodItem }: Props) => (prop: string) => (value: any) => {
setFoodItem(foodItem.set(prop, value));
};
const addImage = ({ foodItem, setFoodItem }: Props) => async () => {
const uri = await openImagePicker();
Snackbar.show({
title: 'Photo added.',
});
setFoodItem(foodItem.update('images', images => images.add(uri)));
};
const updatePlace = ({ foodItem, setFoodItem, emitPlace }: Props) => placeDetails => {
const { placeID, latitude, longitude } = placeDetails;
emitPlace(
new PlaceRecord({
...placeDetails,
id: placeID,
})
);
setFoodItem(
foodItem.merge({
placeId: placeID,
latitude,
longitude,
})
);
};
const toggleNameModal = ({ nameModalOpen, setNameModalOpen }) => () =>
setNameModalOpen(!nameModalOpen);
export default compose(
withCreateFoodItemState,
withPlaceId,
withPlaceForFoodItem,
withPlaceActions,
withState('nameModalOpen', 'setNameModalOpen', false),
withState('imagePreview', 'setImagePreview', -1),
withHandlers({
setPropOfFoodItem,
addImage,
updatePlace,
toggleNameModal,
}),
lifecycle({
componentDidMount() {
const { placeId, setFoodItem } = this.props;
setFoodItem(new FoodItemRecord({ placeId }));
},
}),
branch(({ nameModalOpen }) => !!nameModalOpen, NameModalComp),
branch(({ imagePreview }) => imagePreview > -1, ImagePreviewComp)
)(CreateFoodItem);