mirror of
https://gitlab.com/wheres-the-tp/ui-mobile.git
synced 2026-01-25 09:54:55 -06:00
192 lines
5.1 KiB
JavaScript
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);
|