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

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);