mirror of
https://gitlab.com/wheres-the-tp/ui-mobile.git
synced 2026-01-25 07:44:54 -06:00
234 lines
6.5 KiB
JavaScript
234 lines
6.5 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';
|
|
import { withAuthRedirect } from '../enhancers/authEnhancers';
|
|
|
|
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(
|
|
withAuthRedirect,
|
|
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);
|