You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
550 lines
16 KiB
550 lines
16 KiB
import React, { useState, useEffect } from "react"; |
|
import { |
|
View, |
|
Text, |
|
Image, |
|
ScrollView, |
|
TouchableHighlight, |
|
Dimensions, |
|
Platform, |
|
ActivityIndicator, |
|
} from "react-native"; |
|
import { useNavigation } from "@react-navigation/native"; |
|
import { product, userProduct } from "../../../redux/actions"; |
|
import { asyncAwesomeAlert } from "../../../utils/AsyncWrappers"; |
|
import { connect } from "react-redux"; |
|
import separate from "../../../utils/separate"; |
|
|
|
//components |
|
import LinkBox from "./LinkBox"; |
|
import Comments from "./Comments"; |
|
import Rates from "./Rates"; |
|
|
|
//style |
|
import tw from "tailwind-rn"; |
|
import fontSize from "../../../constants/fontSize"; |
|
import Colors from "../../../constants/Colors"; |
|
|
|
const ios = Platform.OS === "ios"; |
|
|
|
function Book({ |
|
book, |
|
grades, |
|
pushToCart, |
|
userId, |
|
userProductsLoading, |
|
userFavoriteLoading, |
|
mobile, |
|
userProducts, |
|
theme, |
|
orientation, |
|
availableForSell, |
|
}) { |
|
const [width, setWidth] = React.useState(Dimensions.get("window").width); |
|
const navigation = useNavigation(); |
|
const [whichTypeAdded, setWhichTypeAdded] = React.useState(null); |
|
|
|
const physicalAvailableForSell = React.useMemo(() => { |
|
return availableForSell?.filter((product) => product === 2)?.length; |
|
}, [availableForSell]); |
|
|
|
const digitalAvailableForSell = React.useMemo(() => { |
|
return availableForSell?.filter((product) => product === 1)?.length; |
|
}, [availableForSell]); |
|
|
|
const videoAvailableForSell = React.useMemo(() => { |
|
return availableForSell?.filter((product) => product === 4)?.length; |
|
}, [availableForSell]); |
|
|
|
const physicalProduct = React.useMemo(() => { |
|
return book?.product?.filter((product) => product?.productType === 2)[0]; |
|
}, [book]); |
|
|
|
const digitalProduct = React.useMemo(() => { |
|
return book?.product?.filter((product) => product?.productType === 1)[0]; |
|
}, [book]); |
|
|
|
const videoProduct = React.useMemo(() => { |
|
return book?.product?.filter((product) => product?.productType === 4)[0]; |
|
}, [book]); |
|
|
|
const physicalAvailabileInCart = React.useMemo(() => { |
|
return userProducts?.filter( |
|
(product) => |
|
product?.productId === physicalProduct?.id && product?.condition < 2 |
|
)?.length; |
|
}, [userProducts, book]); |
|
|
|
const digitalAvailabileInCart = React.useMemo(() => { |
|
return userProducts?.filter( |
|
(product) => |
|
product?.productId === digitalProduct?.id && product?.condition < 2 |
|
)?.length; |
|
}, [userProducts, book]); |
|
|
|
const videoAvailabileInCart = React.useMemo(() => { |
|
return userProducts?.filter( |
|
(product) => |
|
product?.productId === videoProduct?.id && product?.condition < 2 |
|
)?.length; |
|
}, [userProducts, book]); |
|
|
|
const addToCart = React.useCallback( |
|
async (action, type) => { |
|
setWhichTypeAdded(type); |
|
action(); |
|
}, |
|
[book, userId] |
|
); |
|
|
|
React.useEffect(() => { |
|
if (userProducts?.length && whichTypeAdded) { |
|
setTimeout(() => { |
|
if (whichTypeAdded === "video" && videoAvailabileInCart) { |
|
asyncAwesomeAlert("", "به سبد خرید اضافه شد", { |
|
showCancelButton: true, |
|
onConfirm: () => |
|
navigation.navigate("Root", { |
|
screen: "ShoppingCartTab", |
|
}), |
|
confirmText: "مشاهده سبد خرید", |
|
cancelText: "ادامه خرید", |
|
}); |
|
} else if (whichTypeAdded === "physical" && physicalAvailabileInCart) { |
|
asyncAwesomeAlert("", "به سبد خرید اضافه شد", { |
|
showCancelButton: true, |
|
onConfirm: () => |
|
navigation.navigate("Root", { |
|
screen: "ShoppingCartTab", |
|
}), |
|
confirmText: "مشاهده سبد خرید", |
|
cancelText: "ادامه خرید", |
|
}); |
|
} else if (whichTypeAdded === "digital" && digitalAvailabileInCart) { |
|
asyncAwesomeAlert("", "به سبد خرید اضافه شد", { |
|
showCancelButton: true, |
|
onConfirm: () => |
|
navigation.navigate("Root", { |
|
screen: "ShoppingCartTab", |
|
}), |
|
confirmText: "مشاهده سبد خرید", |
|
cancelText: "ادامه خرید", |
|
}); |
|
} |
|
setWhichTypeAdded(null); |
|
}, 500); |
|
} |
|
}, [userProducts]); |
|
|
|
const ProductButton = ({ |
|
availableInCart, |
|
availableForSell, |
|
product, |
|
type, |
|
onLoad, |
|
title, |
|
sample, |
|
sampleAction, |
|
}) => { |
|
return product ? ( |
|
<View style={tw("w-full flex flex-row-reverse justify-between")}> |
|
<TouchableHighlight |
|
underlayColor={Colors.theme1.greenFF + "22"} |
|
style={[ |
|
tw("flex flex-row-reverse justify-between px-2 py-3 mb-4"), |
|
{ |
|
borderWidth: 1, |
|
borderColor: Colors.theme1.greenCF, |
|
backgroundColor: |
|
theme === "light" ? Colors.theme1.greenFF + "0a" : null, |
|
width: width - 32 - 8 - (fontSize.sm * 6 + 18), |
|
}, |
|
]} |
|
onPress={() => |
|
availableInCart |
|
? asyncAwesomeAlert( |
|
"", |
|
"این محصول قبلا به سبد خرید شما اضافه شده است.", |
|
{ |
|
showCancelButton: true, |
|
onConfirm: () => |
|
navigation.navigate("Root", { |
|
screen: "ShoppingCartTab", |
|
}), |
|
confirmText: "مشاهده سبد خرید", |
|
cancelText: "باشه", |
|
} |
|
) |
|
: availableForSell |
|
? addToCart( |
|
pushToCart({ |
|
productId: product?.id, |
|
userId: userId, |
|
count: 1, |
|
}), |
|
type |
|
) |
|
: null |
|
} |
|
> |
|
<> |
|
{onLoad ? ( |
|
<ActivityIndicator |
|
color={ |
|
theme === "light" |
|
? Colors.theme1.green79 |
|
: Colors.theme1.greenCF |
|
} |
|
size={fontSize.sm} |
|
/> |
|
) : ( |
|
<Text |
|
style={{ |
|
fontFamily: "Medium", |
|
fontSize: fontSize.sm, |
|
color: |
|
theme === "light" |
|
? Colors.theme1.green79 |
|
: Colors.theme1.greenCF, |
|
|
|
paddingVertical: 4, |
|
}} |
|
> |
|
{title} |
|
</Text> |
|
)} |
|
|
|
<View style={tw("flex flex-row-reverse items-center")}> |
|
<View style={tw("w-px h-full bg-green-300")}></View> |
|
<View style={tw("flex")}> |
|
<Text |
|
style={[ |
|
tw("py-1 pr-2"), |
|
{ |
|
fontFamily: "Medium", |
|
color: |
|
theme === "light" |
|
? Colors.theme1.green79 |
|
: Colors.theme1.greenCF, |
|
|
|
fontSize: fontSize.sm, |
|
}, |
|
]} |
|
> |
|
{availableForSell |
|
? (separate(product?.price) || " ") + " " + "تومان" |
|
: "ناموجود"} |
|
</Text> |
|
</View> |
|
</View> |
|
</> |
|
</TouchableHighlight> |
|
{sample ? ( |
|
<TouchableHighlight |
|
underlayColor={Colors.theme1.greenFF + "22"} |
|
style={[ |
|
tw("flex flex-row-reverse justify-center px-2 py-3 mb-4"), |
|
{ |
|
borderWidth: 1, |
|
borderColor: Colors.theme1.greenCF, |
|
backgroundColor: |
|
theme === "light" ? Colors.theme1.greenFF + "0a" : null, |
|
width: fontSize.sm * 6 + 18, |
|
}, |
|
]} |
|
onPress={() => sampleAction()} |
|
> |
|
<Text |
|
style={{ |
|
fontFamily: "Medium", |
|
fontSize: fontSize.xs, |
|
color: |
|
theme === "light" |
|
? Colors.theme1.green79 |
|
: Colors.theme1.greenCF, |
|
|
|
paddingVertical: 4, |
|
}} |
|
> |
|
مشاهده نمونه |
|
</Text> |
|
</TouchableHighlight> |
|
) : null} |
|
</View> |
|
) : null; |
|
}; |
|
|
|
return ( |
|
<View |
|
style={[tw("flex flex-1 relative")]} |
|
onLayout={() => setWidth(Dimensions.get("window").width)} |
|
> |
|
{!mobile ? <View style={tw("mt-5")}></View> : null} |
|
{/* {imageSlider ? <ImageSlider /> : null} */} |
|
<View style={[tw("flex flex-row-reverse")]}> |
|
<Image |
|
source={{ uri: `https://dnvn.ir/api/v1/file/${book?.fileIds}` }} |
|
resizeMode="contain" |
|
style={[ |
|
tw("rounded-sm"), |
|
{ |
|
height: mobile |
|
? ((width / 3) * 4) / 2.6 |
|
: orientation === "portrait" |
|
? ((width / 4) * 4) / 2.6 |
|
: ((width / 6) * 4) / 2.6, |
|
width: mobile |
|
? width / 3 |
|
: orientation === "portrait" |
|
? width / 4 |
|
: width / 6, |
|
}, |
|
]} |
|
/> |
|
<View |
|
style={[ |
|
tw("flex flex-1 justify-between items-end"), |
|
{ |
|
paddingRight: 10, |
|
}, |
|
]} |
|
> |
|
<View style={tw("flex items-end")}> |
|
<Text |
|
style={{ |
|
color: |
|
theme === "light" |
|
? Colors.theme1.green79 |
|
: Colors.theme1.white, |
|
fontSize: mobile ? fontSize.base : fontSize.lg, |
|
marginBottom: 5, |
|
fontFamily: "Medium", |
|
textAlign: ios ? "right" : "auto", |
|
}} |
|
> |
|
{book?.name || ""} |
|
</Text> |
|
<Text |
|
style={{ |
|
color: |
|
theme === "light" |
|
? Colors.theme1.green79 |
|
: Colors.theme1.white, |
|
fontSize: mobile ? fontSize.tiny : fontSize.base, |
|
fontFamily: "Regular", |
|
}} |
|
> |
|
{"پایه" + " " + (grades[book?.gradeId] || " ")} |
|
</Text> |
|
</View> |
|
</View> |
|
</View> |
|
<View |
|
style={tw("flex flex-row-reverse items-center justify-around py-8")} |
|
> |
|
<View> |
|
<Text |
|
style={{ |
|
color: |
|
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white, |
|
textAlign: "center", |
|
fontSize: mobile ? fontSize.tiny : fontSize.base, |
|
fontFamily: "Regular", |
|
}} |
|
> |
|
{" "} |
|
{(book?.pagesNum || " ") + "\n" + "صفحه"} |
|
</Text> |
|
</View> |
|
<View |
|
style={{ |
|
backgroundColor: Colors.theme1.green79 + "55", |
|
height: 20, |
|
width: 2, |
|
}} |
|
></View> |
|
<View> |
|
<Text |
|
style={{ |
|
color: |
|
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white, |
|
textAlign: "center", |
|
fontSize: mobile ? fontSize.tiny : fontSize.base, |
|
fontFamily: "Regular", |
|
}} |
|
> |
|
{" "} |
|
{`${ |
|
videoProduct |
|
? "ویدئو" |
|
: "" + physicalProduct |
|
? "فیزیکی" |
|
: "" + digitalProduct |
|
? "دیجیتال" |
|
: "" |
|
} \n در دسترس`} |
|
</Text> |
|
</View> |
|
<View |
|
style={{ |
|
backgroundColor: Colors.theme1.green79 + "55", |
|
height: 20, |
|
width: 2, |
|
}} |
|
></View> |
|
<View> |
|
<Text |
|
style={{ |
|
color: |
|
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white, |
|
textAlign: "center", |
|
fontSize: mobile ? fontSize.tiny : fontSize.base, |
|
fontFamily: "Regular", |
|
}} |
|
> |
|
{" "} |
|
{book?.rate || 4 + "\n" + "امتیاز"} |
|
</Text> |
|
</View> |
|
</View> |
|
{book?.product?.length > 1 ? ( |
|
<Text |
|
style={[ |
|
tw("w-full text-right"), |
|
{ |
|
color: |
|
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white, |
|
|
|
fontSize: mobile ? fontSize.tiny : fontSize.base, |
|
fontFamily: "DemiBold", |
|
}, |
|
]} |
|
> |
|
نسخه محصول را انتخاب کنید |
|
</Text> |
|
) : null} |
|
<View style={tw("mt-4")}> |
|
<ProductButton |
|
product={physicalProduct} |
|
availableForSell={physicalAvailableForSell} |
|
availableInCart={physicalAvailabileInCart} |
|
type="physical" |
|
onLoad={whichTypeAdded === "physical" && userProductsLoading} |
|
title="خرید نسخه فیزیکی کتاب" |
|
sample={true} |
|
sampleAction={() => |
|
navigation.push("Sample", { id: book?.sampleFileId }) |
|
} |
|
/> |
|
|
|
<ProductButton |
|
product={videoProduct} |
|
availableInCart={videoAvailabileInCart} |
|
availableForSell={videoAvailableForSell} |
|
type="video" |
|
onLoad={whichTypeAdded === "video" && userProductsLoading} |
|
title="خرید نسخه ویدئویی کتاب" |
|
sample={true} |
|
sampleAction={() => navigation.navigate("Video", { id: book?.id })} |
|
/> |
|
|
|
<ProductButton |
|
product={digitalProduct} |
|
availableInCart={digitalAvailabileInCart} |
|
availableForSell={digitalAvailableForSell} |
|
type="digital" |
|
onLoad={whichTypeAdded === "digital" && userProductsLoading} |
|
title="خرید نسخه دیجیتال کتاب" |
|
sample={false} |
|
sampleAction={() => {}} |
|
/> |
|
</View> |
|
{book?.text ? ( |
|
<LinkBox |
|
title="توضیحات" |
|
key={"4"} |
|
onPress={() => |
|
navigation.push("Info", { |
|
type: { name: "توضیحات", value: "productDescription" }, |
|
data: book?.text, |
|
}) |
|
} |
|
/> |
|
) : null} |
|
<LinkBox |
|
title="مشخصات محصول" |
|
key={"0"} |
|
onPress={() => |
|
navigation.push("Info", { |
|
type: { name: "مشخصات محصول", value: "productSpecifications" }, |
|
data: [], |
|
}) |
|
} |
|
/> |
|
<LinkBox |
|
title="نقد بررسی و توضیحات تکمیلی محصول" |
|
key={"1"} |
|
onPress={() => |
|
navigation.push("Info", { |
|
type: { name: "نقد و بررسی", value: "productReview" }, |
|
data: [], |
|
}) |
|
} |
|
/> |
|
<LinkBox |
|
title="پرسش و پاسخ" |
|
key={"2"} |
|
onPress={() => |
|
navigation.push("Info", { |
|
type: { name: "پرسش و پاسخ", value: "productQuestion" }, |
|
data: [], |
|
}) |
|
} |
|
/> |
|
{book?.rate || 4 ? ( |
|
<> |
|
<View |
|
style={tw( |
|
"flex flex-row-reverse justify-between items-center my-6" |
|
)} |
|
> |
|
<Text |
|
style={[ |
|
{ |
|
fontSize: fontSize.tiny, |
|
color: theme === "light" ? "#275077" : Colors.theme1.white, |
|
fontFamily: "Regular", |
|
}, |
|
tw(""), |
|
]} |
|
> |
|
امتیازات و نظرات |
|
</Text> |
|
</View> |
|
<Rates productId={physicalProduct?.id} rateDetail={physicalProduct?.rateDetail} /> |
|
<Comments |
|
comments={book?.comments} |
|
productId={book?.product[1]?.id} |
|
/> |
|
</> |
|
) : null} |
|
</View> |
|
); |
|
} |
|
|
|
const mapStateToProps = (state) => ({ |
|
userProducts: state.userProduct.list, |
|
userId: state.user.status?.id, |
|
userProductsLoading: state.userProduct.loading, |
|
userFavoriteLoading: state.userFavorite.loading, |
|
mobile: state.publicApi.mobile, |
|
orientation: state.publicApi.orientation, |
|
theme: state.publicApi.theme, |
|
availableForSell: state.config.availableForSell, |
|
}); |
|
|
|
const mapDispatchToProps = { |
|
pushToCart: userProduct.add, |
|
}; |
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(Book);
|
|
|