aretherecookies-mobile/js/pages/ProductDetail.js

245 lines
6.6 KiB
JavaScript
Raw Normal View History

import React from 'react';
2020-04-26 12:27:24 -05:00
import { Image, View } from 'react-native';
2017-04-01 20:53:37 -05:00
import theme from '../ui-theme';
import { StrongText, SubText } from '../components/ItemTile';
2020-04-17 22:50:23 -05:00
import typeof ProductRecord from '../records/ProductRecord';
import { type Quantity } from '../constants/QuantityConstants';
2017-06-03 19:43:45 -05:00
import typeof PlaceRecord from '../records/PlaceRecord';
2018-04-08 10:54:29 -05:00
import {
compose,
withState,
withHandlers,
onlyUpdateForKeys,
withProps,
lifecycle,
} from 'recompose';
2017-04-14 12:28:48 -05:00
import IconButton from '../components/IconButton';
2020-04-17 22:50:23 -05:00
import { withProduct } from '../enhancers/productsEnhancers';
import { withPlaceForProduct } from '../enhancers/placeEnhancers';
2017-04-20 16:28:13 -05:00
import Carousel from 'react-native-looped-carousel';
2017-04-23 20:15:46 -05:00
import CountBadge from '../components/CountBadge';
2020-03-29 19:47:33 +00:00
import { routeWithTitle, loginWithBackto } from '../helpers/RouteHelpers';
import { Link } from 'react-router-native';
import { withUpdateQuantity } from '../enhancers/quantityEnhancers';
import QuantityModal from '../modals/QuantityModal';
2020-03-29 19:47:33 +00:00
import { identity, pathOr } from 'ramda';
2018-04-08 10:54:29 -05:00
import Spinner from 'react-native-loading-spinner-overlay';
import ImageRecord from '../records/ImageRecord';
import { get } from 'immutable';
import Snackbar from 'react-native-snackbar';
2020-03-29 19:47:33 +00:00
import { withAuthed } from '../enhancers/authEnhancers';
import { withFaves } from '../enhancers/favesEnhancer';
import debounce from '../helpers/debounce';
import { withCurrentPath, withReplaceRoute } from '../enhancers/routeEnhancers';
2020-04-26 12:27:24 -05:00
import QuantityTile from '../components/QuantityTile';
2017-04-14 12:28:48 -05:00
2020-04-17 22:50:23 -05:00
const { productDetails: style } = theme;
2017-04-01 20:53:37 -05:00
2017-04-23 20:15:46 -05:00
const stretchedStyle = { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 };
2020-04-17 22:50:23 -05:00
const ProductImages = ({
2018-04-08 10:54:29 -05:00
currentImage,
visibleImages,
changeCurrentImage,
}: {
currentImage: number,
visibleImages: Set<ImageRecord>,
2018-04-08 10:54:29 -05:00
changeCurrentImage: (img: number) => void,
}) => {
return (
<View style={{ flex: 3 }}>
{visibleImages.size === 1 && (
<View style={stretchedStyle}>
<Image
style={{ flex: 1, resizeMode: 'contain' }}
resizeMethod="scale"
source={{ uri: get(visibleImages.first(), 'url', '') }}
/>
</View>
2018-04-08 10:54:29 -05:00
)}
{visibleImages.size > 1 && (
2019-12-14 09:38:07 -06:00
<Carousel
autoplay={false}
onAnimateNextPage={changeCurrentImage}
style={stretchedStyle}
currentPage={currentImage}>
{visibleImages.map(image => (
2018-04-08 10:54:29 -05:00
<Image
key={get(image, 'url', '')}
style={{ flex: 1, resizeMode: 'cover' }}
resizeMethod="resize"
source={{ uri: get(image, 'url', '') }}
2018-04-08 10:54:29 -05:00
/>
))}
</Carousel>
)}
{visibleImages.size > 0 && (
<CountBadge currentImage={currentImage + 1} totalCount={visibleImages.size} />
)}
</View>
);
};
2017-04-23 20:15:46 -05:00
const contentTileStyle = {
backgroundColor: 'white',
padding: 15,
marginBottom: 10,
2017-04-23 20:15:46 -05:00
};
2017-04-20 16:28:13 -05:00
type Props = {
2020-04-17 22:50:23 -05:00
product: ?ProductRecord,
productId: string,
place: PlaceRecord,
currentImage: number,
quantityModalOpen: boolean,
2020-03-29 19:47:33 +00:00
isAuthed: boolean,
changeCurrentImage: (index: number) => void,
updateAmount: (quantity: Quantity) => void,
2020-04-17 22:50:23 -05:00
updateQuantity: (arg: { productId: string, quantity: Quantity }) => void,
toggleQuantityModal: () => void,
addPhoto: () => void,
2020-04-17 22:50:23 -05:00
addImage: (arg: { productId: string, imageUri: string }) => Promise<void>,
2020-03-29 19:47:33 +00:00
addToFaves: () => void,
isFave: boolean,
deleteFromFaves: () => void,
};
2017-07-23 19:58:10 -05:00
2020-04-17 22:50:23 -05:00
export const ProductDetail = (props: Props) => {
const {
2020-04-17 22:50:23 -05:00
product,
place,
currentImage,
changeCurrentImage,
2020-03-29 19:47:33 +00:00
isAuthed,
addPhoto,
toggleQuantityModal,
quantityModalOpen,
updateAmount,
2020-03-29 19:47:33 +00:00
addToFaves,
isFave,
deleteFromFaves,
} = props;
2020-04-17 22:50:23 -05:00
if (!product || !place) {
return <Spinner />;
}
2017-04-20 16:28:13 -05:00
return (
<View style={{ ...theme.page.container }}>
2020-04-17 22:50:23 -05:00
<ProductImages
2018-04-08 10:54:29 -05:00
currentImage={currentImage}
2020-04-17 22:50:23 -05:00
visibleImages={product.images.filter(identity)}
2018-04-08 10:54:29 -05:00
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>
2020-04-26 12:27:24 -05:00
<QuantityTile
product={product}
isAuthed={isAuthed}
onUpdatePress={toggleQuantityModal}
style={contentTileStyle}
/>
<View style={{ flex: 1, ...contentTileStyle }}>
2020-03-29 19:47:33 +00:00
{isAuthed && isFave ? (
<IconButton
glyph="favorite"
text="Favorited"
onPress={deleteFromFaves}
color="#990000"
style={{ marginBottom: 10 }}
textStyle={{ fontSize: 20, color: '#555555' }}
/>
) : (
<IconButton
glyph="favorite"
text="Add to Faves"
onPress={addToFaves}
color={style.actionIconColor}
style={{ marginBottom: 10 }}
textStyle={{ fontSize: 20, color: '#555555' }}
/>
)}
{isAuthed && (
2018-04-08 10:54:29 -05:00
<IconButton
glyph="insert-photo"
text="Add Photo"
onPress={addPhoto}
color={style.actionIconColor}
2020-03-29 19:47:33 +00:00
textStyle={{ fontSize: 20, color: '#555555' }}
2018-04-08 10:54:29 -05:00
/>
)}
</View>
2019-12-14 09:38:07 -06:00
{quantityModalOpen && (
2020-04-17 22:50:23 -05:00
<QuantityModal product={product} onUpdate={updateAmount} onClose={toggleQuantityModal} />
2019-12-14 09:38:07 -06:00
)}
</View>
);
};
2017-04-01 20:53:37 -05:00
export default compose(
2020-04-17 22:50:23 -05:00
withProduct,
withPlaceForProduct,
withUpdateQuantity,
2020-03-29 19:47:33 +00:00
withAuthed,
withFaves,
withCurrentPath,
withReplaceRoute,
withState('currentImage', 'changeCurrentImage', 0),
withState('quantityModalOpen', 'setQuantityModalOpen', false),
withHandlers({
2020-04-17 22:50:23 -05:00
updateAmount: ({ updateQuantity, product }: Props) => async (quantity: Quantity) => {
if (!product) {
2018-05-01 16:28:01 -05:00
return;
}
2020-04-17 22:50:23 -05:00
await updateQuantity({ productId: product.id, quantity });
Snackbar.show({ title: 'Product updated.', backgroundColor: 'black', color: 'white' });
},
2020-03-29 19:47:33 +00:00
toggleQuantityModal: ({ quantityModalOpen, setQuantityModalOpen }) =>
debounce(() => {
setQuantityModalOpen(!quantityModalOpen);
}, 500),
2020-04-17 22:50:23 -05:00
addToFaves: ({ addFave, productId, isAuthed, replaceRoute }) =>
2020-03-29 19:47:33 +00:00
debounce(() => {
if (!isAuthed) {
2020-04-17 22:50:23 -05:00
replaceRoute(loginWithBackto(`/product/${productId}?loginAction=add-to-faves`));
2020-03-29 19:47:33 +00:00
} else {
2020-04-17 22:50:23 -05:00
addFave(productId);
2020-03-29 19:47:33 +00:00
}
}, 500),
2020-04-17 22:50:23 -05:00
deleteFromFaves: ({ deleteFave, productId }) => () => deleteFave(productId),
}),
withProps(props => ({
2020-04-17 22:50:23 -05:00
isFave: props.faves && !!props.faves.find(fave => get(fave, 'id') === props.productId),
2020-03-29 19:47:33 +00:00
loginAction: pathOr('', [1], /loginAction=(.+)(&?.*$)/.exec(props.currentPath)),
})),
onlyUpdateForKeys([
2020-04-17 22:50:23 -05:00
'product',
'place',
'quantityModalOpen',
// 'imagesLoading',
2020-03-29 19:47:33 +00:00
'isAuthed',
'faves',
]),
2018-04-08 10:54:29 -05:00
lifecycle({
componentDidMount() {
const { loginAction, setQuantityModalOpen, addToFaves } = this.props;
2020-03-29 19:47:33 +00:00
if (loginAction === 'open-quantity-modal') {
setQuantityModalOpen(true);
}
if (loginAction === 'add-to-faves') {
addToFaves();
}
2018-04-08 10:54:29 -05:00
},
})
2020-04-17 22:50:23 -05:00
)(ProductDetail);