aretherecookies-mobile/js/pages/CreateFoodItem.js
2020-01-19 22:59:57 -06:00

232 lines
6.4 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 CategoryModal from '../modals/CategoryModal';
import ImagePreviewModal from '../modals/ImagePreviewModal';
import {
compose,
branch,
withState,
withHandlers,
renderComponent,
mapProps,
lifecycle,
} from 'recompose';
import RNGooglePlaces from 'react-native-google-places';
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';
import { getCategoryText } from '../helpers/CategoryHelpers';
import { getQuantityDropdownText } from '../helpers/QuantityHelpers';
import QuantityModal from '../modals/QuantityModal';
import { wrapModalComponent } from '../modals/FullScreenModal';
type Props = {
foodItem: typeof FoodItemRecord,
setPropOfFoodItem: Function,
toggleNameModal: Function,
setFoodItem: Function,
setModalsVisible: Function,
place: ?PlaceRecord,
updatePlace: (place: GooglePlaceObject) => void,
addImage: (uri: string) => void,
setImagePreview: (imageURI?: string) => void,
loading: boolean,
setLoading: (arg: boolean) => void,
emitPlace: (place: Object) => void,
withFoodItemsAsSeq: IndexedSeq<FoodItemRecord>,
toggleCategoryModal: () => void,
toggleQuantityModal: () => void,
};
type GooglePlaceObject = {
placeID: string,
latitude: number,
longitude: number,
name: string,
address: string,
};
const fieldStyle = {
paddingTop: 24,
paddingLeft: 8,
paddingRight: 8,
};
const fieldNameStyle = {
fontSize: 16,
paddingBottom: 8,
};
const Field = ({
onPress,
text = '',
placeholder,
}: {
onPress?: Function,
text: string,
placeholder?: string,
}) => (
<TouchableOpacity style={fieldStyle} onPress={onPress}>
<Text style={[fieldNameStyle, !text && { color: theme.palette.disabledColor }]}>
{text || placeholder}
</Text>
<Divider />
</TouchableOpacity>
);
const openPlaceModal = (onChoosePlace: (place: GooglePlaceObject) => void) => () => {
RNGooglePlaces.openAutocompleteModal({ type: 'establishment' }).then(onChoosePlace);
};
const CreateFoodItem = (props: Props) => {
const {
foodItem,
toggleNameModal,
updatePlace,
addImage,
setImagePreview,
loading,
place,
toggleCategoryModal,
toggleQuantityModal,
} = props;
return (
<View style={{ ...theme.page.container, backgroundColor: 'white', padding: 10 }}>
<Spinner visible={loading} />
<Field text={foodItem.name} onPress={toggleNameModal} placeholder="Name" />
<Field text={place && place.name} onPress={openPlaceModal(updatePlace)} placeholder="Place" />
<Field
text={foodItem.category && getCategoryText(foodItem.category)}
onPress={toggleCategoryModal}
placeholder="Category"
/>
<Field
text={foodItem.quantity && getQuantityDropdownText(foodItem.quantity)}
onPress={toggleQuantityModal}
placeholder="Quantity"
/>
<ImagePicker onCreateNew={addImage}>
{foodItem.images.map((imageURI: string) => (
<ImageThumb key={imageURI} uri={imageURI} onPress={() => setImagePreview(imageURI)} />
))}
</ImagePicker>
</View>
);
};
const ImagePreviewComp = compose(
renderComponent,
mapProps(({ foodItem, setFoodItem, setImagePreview, imagePreview }) => {
return {
onClose: () => setImagePreview(-1),
onDelete: () => {
setFoodItem(foodItem.deleteIn(['images', imagePreview]));
setImagePreview(null);
},
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 { path } = await openImagePicker();
Snackbar.show({
title: 'Photo added.',
});
setFoodItem(foodItem.update('images', images => images.add(path)));
};
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,
})
);
};
export default compose(
withCreateFoodItemState,
withPlaceId,
withPlaceForFoodItem,
withPlaceActions,
withState('nameModalOpen', 'setNameModalOpen', false),
withState('imagePreview', 'setImagePreview', null),
withState('categoryModalOpen', 'setCategoryModalOpen', false),
withState('quantityModalOpen', 'setQuantityModalOpen', false),
withHandlers({
setPropOfFoodItem,
addImage,
updatePlace,
toggleNameModal: ({ nameModalOpen, setNameModalOpen }) => () => {
setNameModalOpen(!nameModalOpen);
},
toggleCategoryModal: ({ categoryModalOpen, setCategoryModalOpen }) => () => {
setCategoryModalOpen(!categoryModalOpen);
},
toggleQuantityModal: ({ quantityModalOpen, setQuantityModalOpen }) => () => {
setQuantityModalOpen(!quantityModalOpen);
},
}),
withHandlers({
setQuantity: ({ setPropOfFoodItem }) => setPropOfFoodItem('quantity'),
setCategory: ({ setPropOfFoodItem }) => setPropOfFoodItem('category'),
setName: ({ setPropOfFoodItem }) => setPropOfFoodItem('name'),
}),
lifecycle({
componentDidMount() {
const { placeId, setFoodItem } = this.props;
setFoodItem(new FoodItemRecord({ placeId }));
},
}),
branch(
({ nameModalOpen }) => !!nameModalOpen,
wrapModalComponent({
component: NameModal,
onCloseProp: 'toggleNameModal',
onUpdateProp: 'setName',
})
),
branch(({ imagePreview }) => !!imagePreview, ImagePreviewComp),
branch(
({ categoryModalOpen }) => !!categoryModalOpen,
wrapModalComponent({
component: CategoryModal,
onCloseProp: 'toggleCategoryModal',
onUpdateProp: 'setCategory',
})
),
branch(
({ quantityModalOpen }) => !!quantityModalOpen,
wrapModalComponent({
component: QuantityModal,
onCloseProp: 'toggleQuantityModal',
onUpdateProp: 'setQuantity',
})
)
)(CreateFoodItem);