mirror of
https://gitlab.com/wheres-the-tp/ui-mobile.git
synced 2026-01-25 06:04:55 -06:00
255 lines
6.7 KiB
JavaScript
255 lines
6.7 KiB
JavaScript
// @flow
|
|
import React from 'react';
|
|
import { Button, Image, Text, View } from 'react-native';
|
|
import theme from '../ui-theme';
|
|
import { StrongText, SubText } from '../components/ItemTile';
|
|
import typeof FoodItemRecord from '../records/FoodItemRecord';
|
|
import { type Quantity } from '../constants/QuantityConstants';
|
|
import typeof PlaceRecord from '../records/PlaceRecord';
|
|
import {
|
|
compose,
|
|
withState,
|
|
withHandlers,
|
|
onlyUpdateForKeys,
|
|
withProps,
|
|
lifecycle,
|
|
} from 'recompose';
|
|
import IconButton from '../components/IconButton';
|
|
import { withFoodItem } from '../enhancers/foodItemEnhancers';
|
|
import { withPlaceForFoodItem } from '../enhancers/placeEnhancers';
|
|
import Carousel from 'react-native-looped-carousel';
|
|
import CountBadge from '../components/CountBadge';
|
|
import { routeWithTitle } from '../helpers/RouteHelpers';
|
|
import { Link } from 'react-router-native';
|
|
import moment from 'moment';
|
|
import { withUpdateQuantity } from '../enhancers/quantityEnhancers';
|
|
import { getQuantityLabelText } from '../helpers/QuantityHelpers';
|
|
import AuthManager from '../AuthManager';
|
|
import RouterButton from 'react-router-native-button';
|
|
import QuantityModal from '../modals/QuantityModal';
|
|
import { withImages } from '../enhancers/imagesEnhancers';
|
|
import { openImagePicker } from '../helpers/ImagePickerHelpers';
|
|
import { identity } from 'ramda';
|
|
import Spinner from 'react-native-loading-spinner-overlay';
|
|
import ImageRecord from '../records/ImageRecord';
|
|
import { List } from 'immutable';
|
|
import Snackbar from 'react-native-snackbar';
|
|
|
|
const { foodItemDetails: style } = theme;
|
|
|
|
const stretchedStyle = { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 };
|
|
|
|
const FoodItemImages = ({
|
|
currentImage,
|
|
visibleImages,
|
|
changeCurrentImage,
|
|
}: {
|
|
currentImage: number,
|
|
visibleImages: List<ImageRecord>,
|
|
changeCurrentImage: (img: number) => void,
|
|
}) => {
|
|
return (
|
|
<View style={{ flex: 3 }}>
|
|
{visibleImages.size === 1 && (
|
|
<View style={stretchedStyle}>
|
|
<Image
|
|
style={{ flex: 1, resizeMode: 'cover' }}
|
|
resizeMethod="resize"
|
|
source={{ uri: visibleImages.first().get('url', '') }}
|
|
/>
|
|
</View>
|
|
)}
|
|
{visibleImages.size > 1 && (
|
|
<Carousel autoplay={false} onAnimateNextPage={changeCurrentImage} style={stretchedStyle}>
|
|
{visibleImages.map(image => (
|
|
<Image
|
|
key={image.get('url', '')}
|
|
style={{ flex: 1, resizeMode: 'cover' }}
|
|
resizeMethod="resize"
|
|
source={{ uri: image.get('url', '') }}
|
|
/>
|
|
))}
|
|
</Carousel>
|
|
)}
|
|
{visibleImages.size > 0 && (
|
|
<CountBadge currentImage={currentImage + 1} totalCount={visibleImages.size} />
|
|
)}
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const contentTileStyle = {
|
|
backgroundColor: 'white',
|
|
padding: 15,
|
|
marginBottom: 10,
|
|
};
|
|
|
|
type Props = {
|
|
foodItem: ?FoodItemRecord,
|
|
foodItemId: string,
|
|
place: PlaceRecord,
|
|
currentImage: number,
|
|
quantityModalOpen: boolean,
|
|
isLoggedIn: boolean,
|
|
changeCurrentImage: (index: number) => void,
|
|
updateAmount: (quantity: Quantity) => void,
|
|
updateQuantity: (arg: { foodItemId: string, quantity: Quantity }) => void,
|
|
toggleQuantityModal: () => void,
|
|
addPhoto: () => void,
|
|
addImage: (arg: { foodItemId: string, imageUri: string }) => Promise<void>,
|
|
imagesLoading: boolean,
|
|
setImagesLoading: (loading: boolean) => void,
|
|
};
|
|
|
|
export const FoodItemDetail = (props: Props) => {
|
|
const {
|
|
foodItem,
|
|
place,
|
|
currentImage,
|
|
changeCurrentImage,
|
|
isLoggedIn,
|
|
addPhoto,
|
|
toggleQuantityModal,
|
|
quantityModalOpen,
|
|
updateAmount,
|
|
imagesLoading,
|
|
} = props;
|
|
|
|
if (!foodItem || !place) {
|
|
return <View />;
|
|
}
|
|
|
|
if (quantityModalOpen) {
|
|
return (
|
|
<QuantityModal foodItem={foodItem} onUpdate={updateAmount} onClose={toggleQuantityModal} />
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View style={{ ...theme.page.container }}>
|
|
<Spinner visible={imagesLoading} />
|
|
<FoodItemImages
|
|
currentImage={currentImage}
|
|
visibleImages={foodItem.images.filter(identity)}
|
|
changeCurrentImage={changeCurrentImage}
|
|
/>
|
|
<View style={{ ...contentTileStyle }}>
|
|
<Link
|
|
to={routeWithTitle(`/place/${place.id || ''}`, place.name)}
|
|
underlayColor={theme.itemTile.pressHighlightColor}>
|
|
<View>
|
|
<StrongText>{place.name}</StrongText>
|
|
<SubText>{place.address}</SubText>
|
|
</View>
|
|
</Link>
|
|
</View>
|
|
<View
|
|
style={{
|
|
flexBasis: 100,
|
|
flexGrow: 1,
|
|
...contentTileStyle,
|
|
flexDirection: 'column',
|
|
justifyContent: 'space-between',
|
|
}}>
|
|
<Text style={{ fontSize: 42, color: 'black' }}>
|
|
{getQuantityLabelText(foodItem.quantity)}
|
|
</Text>
|
|
<SubText>
|
|
Last updated at {moment(foodItem.lastupdated).format('h:mm A on MMM D, YYYY')}
|
|
</SubText>
|
|
{isLoggedIn && (
|
|
<Button
|
|
title="Update quantity"
|
|
onPress={toggleQuantityModal}
|
|
color={theme.palette.primaryColor}
|
|
/>
|
|
)}
|
|
{!isLoggedIn && (
|
|
<RouterButton
|
|
title="Log in to update quantity"
|
|
to={'/login'}
|
|
color={theme.palette.primaryColor}
|
|
/>
|
|
)}
|
|
</View>
|
|
<View style={{ flex: 1, ...contentTileStyle }}>
|
|
{/* <IconButton
|
|
glyph="stars"
|
|
text="Add to Faves"
|
|
onPress={this.addToFaves}
|
|
color={style.actionIconColor}
|
|
/> */}
|
|
{isLoggedIn && (
|
|
<IconButton
|
|
glyph="insert-photo"
|
|
text="Add Photo"
|
|
onPress={addPhoto}
|
|
color={style.actionIconColor}
|
|
/>
|
|
)}
|
|
</View>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
export default compose(
|
|
withFoodItem,
|
|
withPlaceForFoodItem,
|
|
withUpdateQuantity,
|
|
withImages,
|
|
withProps(() => ({
|
|
isLoggedIn: AuthManager.isLoggedIn(),
|
|
})),
|
|
withState('currentImage', 'changeCurrentImage', 0),
|
|
withState('quantityModalOpen', 'setQuantityModalOpen', false),
|
|
withState('imagesLoading', 'setImagesLoading', true),
|
|
withHandlers({
|
|
addPhoto: ({ addImage, foodItem, setImagesLoading }: Props) => async () => {
|
|
if (!foodItem) {
|
|
return;
|
|
}
|
|
const { path: imageUri } = await openImagePicker();
|
|
setImagesLoading(true);
|
|
await addImage({ foodItemId: foodItem.id, imageUri });
|
|
setImagesLoading(false);
|
|
setTimeout(
|
|
() =>
|
|
Snackbar.show({
|
|
title: 'Food updated.',
|
|
backgroundColor: 'black',
|
|
color: 'white',
|
|
}),
|
|
700
|
|
);
|
|
},
|
|
updateAmount: ({ updateQuantity, foodItem }: Props) => async (quantity: Quantity) => {
|
|
if (!foodItem) {
|
|
return;
|
|
}
|
|
await updateQuantity({ foodItemId: foodItem.id, quantity });
|
|
Snackbar.show({ title: 'Food updated.', backgroundColor: 'black', color: 'white' });
|
|
},
|
|
toggleQuantityModal: ({ quantityModalOpen, setQuantityModalOpen }) => () => {
|
|
setQuantityModalOpen(!quantityModalOpen);
|
|
},
|
|
}),
|
|
onlyUpdateForKeys([
|
|
'foodItem',
|
|
'place',
|
|
'currentImage',
|
|
'quantityModalOpen',
|
|
'imagesLoading',
|
|
'isLoggedIn',
|
|
]),
|
|
lifecycle({
|
|
componentDidMount() {
|
|
const { getImages, foodItemId, setImagesLoading } = this.props;
|
|
|
|
getImages({
|
|
foodItemId,
|
|
}).then(() => {
|
|
setImagesLoading(false);
|
|
});
|
|
},
|
|
})
|
|
)(FoodItemDetail);
|