Last active
May 27, 2020 15:33
-
-
Save iksena/2edab1f569e8d997abaaafba2b621b0b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { PureComponent } from 'react'; | |
import { | |
Dimensions, | |
ImageStyle, | |
Modal, | |
Platform, | |
ScrollView, | |
StyleSheet, | |
Text, | |
TouchableOpacity, | |
View, | |
ViewStyle | |
} from 'react-native'; | |
import ImageViewer from 'react-native-image-zoom-viewer'; | |
import Carousel, { | |
CarouselStatic, | |
ParallaxImage, | |
ParallaxImageProps | |
} from 'react-native-snap-carousel'; | |
import HTML from 'react-native-render-html'; | |
import { Rating, Button } from 'react-native-elements'; | |
import { | |
Image, | |
Product | |
} from '../../Components/ProductItem/ProductItem.component'; | |
import { toAmount } from '../../Utils'; | |
const { width: screenWidth } = Dimensions.get('window'); | |
interface Props { | |
product: Product; | |
handleShowImages: () => void; | |
imagesShown: boolean; | |
addToCart?: (product: Product) => void; | |
} | |
class DetailComponent extends PureComponent<Props> { | |
private carousel: CarouselStatic<object> | null; | |
constructor(props: Props) { | |
super(props); | |
this.carousel = null; | |
} | |
_setCarousel = (carousel: null): void => { | |
this.carousel = carousel; | |
}; | |
_mapImages = (images: Array<Image>) => | |
images.map((image: Image) => ({ url: image.src })); | |
_renderImageItem = (handleShowImages: () => void) => ( | |
{ item }: { item: { url: string } }, | |
parallaxProps: ParallaxImageProps | |
): JSX.Element => ( | |
<TouchableOpacity style={styles.item} onPress={handleShowImages}> | |
<ParallaxImage | |
{...parallaxProps} | |
source={{ uri: item.url }} | |
containerStyle={styles.imageContainer} | |
style={styles.image} | |
/> | |
</TouchableOpacity> | |
); | |
_renderImages = ( | |
images: Array<Image>, | |
handleShowImages: () => void | |
): JSX.Element => ( | |
<ImageViewer | |
imageUrls={this._mapImages(images)} | |
enableSwipeDown | |
onSwipeDown={handleShowImages} | |
index={this.carousel?.currentIndex} | |
/> | |
); | |
render(): JSX.Element { | |
const { | |
product, | |
imagesShown, | |
handleShowImages, | |
addToCart = () => {} | |
} = this.props; | |
const { | |
name, | |
images, | |
description, | |
price, | |
average_rating: rating | |
} = product; | |
return ( | |
<ScrollView style={styles.wrapper}> | |
<Carousel | |
ref={this._setCarousel} | |
sliderWidth={screenWidth} | |
sliderHeight={screenWidth} | |
itemWidth={screenWidth - 60} | |
data={this._mapImages(images)} | |
renderItem={this._renderImageItem(handleShowImages)} | |
hasParallaxImages | |
/> | |
<View style={styles.detail}> | |
<Text style={styles.textTitle}>{name}</Text> | |
<Text style={styles.textPrice}>{toAmount(price)}</Text> | |
<HTML html={description} textSelectable /> | |
<View style={styles.rating}> | |
<Text style={styles.textSubHeading}>Rating:</Text> | |
<Text style={styles.textRating}>{rating}</Text> | |
<Rating readonly imageSize={20} startingValue={Number(rating)} /> | |
</View> | |
<Button | |
icon={{ | |
name: 'cart-plus', | |
type: 'font-awesome-5', | |
color: 'white', | |
size: 16 | |
}} | |
title="Add to cart" | |
onPress={(): void => addToCart(product)} | |
/> | |
</View> | |
<Modal visible={imagesShown} transparent> | |
{this._renderImages(images, handleShowImages)} | |
</Modal> | |
</ScrollView> | |
); | |
} | |
} | |
interface Styles { | |
wrapper: ViewStyle; | |
detail: ViewStyle; | |
textTitle: ViewStyle; | |
rating: ViewStyle; | |
textPrice: ViewStyle; | |
textSubHeading: ViewStyle; | |
textRating: ViewStyle; | |
item: ViewStyle; | |
imageContainer: ViewStyle; | |
image: ImageStyle; | |
} | |
const styles = StyleSheet.create<Styles>({ | |
wrapper: { | |
paddingTop: 5 | |
}, | |
detail: { | |
marginTop: 10, | |
marginHorizontal: 5 | |
}, | |
textTitle: { | |
fontSize: 24, | |
fontWeight: 'bold' | |
}, | |
rating: { flexDirection: 'row', alignItems: 'center' }, | |
textPrice: { fontSize: 18, fontWeight: 'bold', color: '#006db3' }, | |
textSubHeading: { fontSize: 18, fontWeight: 'bold', margin: 5 }, | |
textRating: { fontSize: 18, margin: 5 }, | |
item: { | |
width: screenWidth - 60, | |
height: screenWidth - 60 | |
}, | |
imageContainer: { | |
height: screenWidth - 60, | |
marginBottom: Platform.select({ ios: 0, android: 1 }), | |
backgroundColor: 'white', | |
borderRadius: 5 | |
}, | |
image: { | |
...StyleSheet.absoluteFillObject, | |
resizeMode: 'cover' | |
} | |
}); | |
export default DetailComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect, useState } from 'react'; | |
import { useRoute, RouteProp } from '@react-navigation/native'; | |
import DetailComponent from './Detail.component'; | |
import { Product } from '../../Components/ProductItem/ProductItem.component'; | |
import WooCommerce from '../../Services/WooCommerce'; | |
import { NavigationParams } from '../../Navigations'; | |
const DetailContainer = (): JSX.Element => { | |
const initialProduct = { | |
id: 1, | |
name: '', | |
price: 0, | |
description: '', | |
average_rating: '', | |
images: [] | |
}; | |
const [product, setProduct] = useState<Product>(initialProduct); | |
const [imagesShown, showImages] = useState(false); | |
const route = useRoute<RouteProp<NavigationParams, 'Detail'>>(); | |
const handlers = { | |
handleShowImages: (): void => showImages((prevState: boolean) => !prevState) | |
}; | |
useEffect(() => { | |
WooCommerce.get(`/products/${route.params.id}`).then(({ data }) => { | |
setProduct(data); | |
}); | |
}, [route.params.id]); | |
return ( | |
<DetailComponent | |
{...handlers} | |
imagesShown={imagesShown} | |
product={product} | |
/> | |
); | |
}; | |
export default DetailContainer; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment