diff --git a/navigation/index.js b/navigation/index.js index 019cd2f..056cf98 100644 --- a/navigation/index.js +++ b/navigation/index.js @@ -352,6 +352,7 @@ const HomeStackScreen = () => { + @@ -375,6 +376,7 @@ const ProductsStackScreen = () => { > + @@ -392,6 +394,7 @@ const VODStackScreen = () => { > + ); diff --git a/src/components/AlertModal.js b/src/components/AlertModal.js index 4e27962..d6eedff 100644 --- a/src/components/AlertModal.js +++ b/src/components/AlertModal.js @@ -91,18 +91,31 @@ const AlertModal = props => { confirmButtonColor={alert.confirmButtonColor} onCancelPressed={onCancelPressed} onConfirmPressed={(onConfirmPressed)} + cancelButtonTextStyle={{ + color : '#777', + fontFamily : 'regular', + }} + confirmButtonTextStyle={{ + fontFamily : 'regular', + + }} contentStyle={{ width: ReactNative.Dimensions.get('window').width / 1.5, }} cancelButtonStyle={{ fontFamily : 'regular', + borderColor : "#777", + borderWidth : 1, + backgroundColor : 'white', }} confirmButtonStyle={ { width: ReactNative.Dimensions.get('window').width / 4, alignItems: 'center', justifyContent: 'center', - fontFamily : 'regular' + fontFamily : 'regular', + borderColor : "#2980b9", + borderWidth : 1, } } useNativeDriver={true} diff --git a/src/components/Drawer.js b/src/components/Drawer.js index fcbc975..7bd9a50 100644 --- a/src/components/Drawer.js +++ b/src/components/Drawer.js @@ -9,7 +9,6 @@ import { TouchableOpacity, Image, LayoutAnimation, - StatusBar, } from "react-native"; import { useNavigation } from "@react-navigation/native"; import { asyncAwesomeAlert } from "../utils/AsyncWrappers"; diff --git a/src/components/Navbar.js b/src/components/Navbar.js index 6264906..e88a728 100644 --- a/src/components/Navbar.js +++ b/src/components/Navbar.js @@ -5,6 +5,7 @@ import { Text, Appearance, TouchableOpacity, + ActivityIndicator, } from "react-native"; import Svg, { @@ -36,6 +37,7 @@ const Navbar = ({ deleteBookmark, userFavoriteList, theme, + bookmarkLoading, }) => { const navigation = useNavigation(); @@ -391,7 +393,9 @@ const Navbar = ({ )} {headerOptions?.bookmark && - (isActiveBookmark ? ( + (bookmarkLoading ? ( + + ) : isActiveBookmark ? ( ({ userFavoriteList: state.userFavorite.list, theme: state.publicApi.theme, + bookmarkLoading: state.userFavorite.loading, }); const mapDispatchToProps = { diff --git a/src/redux/actions/userProduct.js b/src/redux/actions/userProduct.js index e30e9d8..8720881 100644 --- a/src/redux/actions/userProduct.js +++ b/src/redux/actions/userProduct.js @@ -19,7 +19,6 @@ const userProduct = { (data = {}, data2 = {}, data3 = {}) => async (dispatch) => { await proxy.post("userProduct/add", data, { dispatch }); - await proxy.get("userProduct/list", data2, { dispatch }); await proxy.get("userFactor/info", data3, { dispatch }); }, del: diff --git a/src/redux/reducers/userFactor.js b/src/redux/reducers/userFactor.js index 020f153..b23f668 100644 --- a/src/redux/reducers/userFactor.js +++ b/src/redux/reducers/userFactor.js @@ -58,6 +58,7 @@ export default function userFactor(state = initialState, action) { case "userFactor/error": asyncAwesomeAlert("خطا", data.message, { showCancelButton: false, + confirmText: "باشه" }); return { ...state, loading: false, error: data.message }; default: diff --git a/src/redux/reducers/userProduct.js b/src/redux/reducers/userProduct.js index b15f2b6..146cbda 100644 --- a/src/redux/reducers/userProduct.js +++ b/src/redux/reducers/userProduct.js @@ -23,6 +23,7 @@ export default function userFactor(state = initialState, action) { data.filter((item) => item.product.productType === 2).length > 0 ? true : false; + console.log('list fetched!'); return { ...state, loading: false, diff --git a/src/screens/Home/components/Blogs.js b/src/screens/Home/components/Blogs.js index 40a796d..bb4ca8f 100644 --- a/src/screens/Home/components/Blogs.js +++ b/src/screens/Home/components/Blogs.js @@ -29,7 +29,7 @@ const ios = Platform.OS === "ios"; function Blogs({ blogs, mobile, theme }) { return ( - +
@@ -37,8 +37,8 @@ function Blogs({ blogs, mobile, theme }) { showsHorizontalScrollIndicator={false} horizontal={true} inverted={true} - style={[tw("flex flex-row mt-3 pb-7")]} - data={blogs.slice(0,7)} + style={[tw("flex flex-row mt-3")]} + data={blogs.slice(0, 7)} renderItem={({ item }) => ( )} @@ -51,11 +51,10 @@ function Blogs({ blogs, mobile, theme }) { const Blog = ({ blog, mobile, theme }) => { const navigation = useNavigation(); - return ( navigation.push("Blog", { id: blog?.id })} @@ -64,7 +63,6 @@ const Blog = ({ blog, mobile, theme }) => { source={{ uri: `https://dnvn.ir/api/v1/file/${blog.fileIds}` }} resizeMode="contain" style={[ - tw("rounded-md"), { flex: 1, height: mobile ? 180 : ((width / 2.2) * 9) / 16, diff --git a/src/screens/Home/index.js b/src/screens/Home/index.js index 1126169..68ab7ed 100644 --- a/src/screens/Home/index.js +++ b/src/screens/Home/index.js @@ -78,7 +78,7 @@ const Home = ({ // Later on in your styles.. const styles = StyleSheet.create({ contentContainerStyle: { - paddingBottom: 40, + // paddingBottom: 40, // flex : 1, // alignItems: "", }, diff --git a/src/screens/Otp/index.js b/src/screens/Otp/index.js index afd7335..a0ff0c3 100644 --- a/src/screens/Otp/index.js +++ b/src/screens/Otp/index.js @@ -118,7 +118,7 @@ function Otp(props) { let timeout = setTimeout(() => { clearInterval(interval); setTimeEnd(true); - }, 10000); + }, 120000); return () => { clearInterval(interval); clearTimeout(timeout); @@ -132,10 +132,14 @@ function Otp(props) { const hour = Math.floor(value / 60); return ( (hour > 0 - ? (hour.toString().length === 1 ? "0" + hour.toString() : hour) + "" + ? (minute.toString().length === 1 + ? "0" + minute.toString() + : minute) + "" : "") + + " " + ":" + - (minute.toString().length === 1 ? "0" + minute.toString() : minute) + " " + + (hour.toString().length === 1 ? "0" + hour.toString() : hour) ); }, [props.route] @@ -345,7 +349,7 @@ function Otp(props) { }, ]} > - {"زمان باقی مانده تا ارسال مجدد: " + duration(time)} + {"زمان باقی مانده تا ارسال مجدد:" + " " + duration(time) + " "} ) : ( diff --git a/src/screens/Product/components/Book.js b/src/screens/Product/components/Book.js index 5c46e27..6de7d90 100644 --- a/src/screens/Product/components/Book.js +++ b/src/screens/Product/components/Book.js @@ -44,6 +44,7 @@ function Book({ }) { const navigation = useNavigation(); const [type, setType] = useState(1); + const [whichTypeAdded, setWhichTypeAdded] = React.useState(null); const [pageLoading, setPageLoading] = useState(false); const [imageSlider, setImageSlider] = useState(false); @@ -66,10 +67,54 @@ function Book({ )[0]; }, [userProducts, book]); + const videoAvailabileInCart = React.useMemo(() => { + return userProducts?.filter( + (product) => product?.productId === book?.product[2]?.id + )[0]; + }, [userProducts, book]); + + const addToCart = React.useCallback( + async (action, type) => { + setWhichTypeAdded(type); + await action(); + }, + [book, userId] + ); + + React.useEffect(() => { + if (userProducts.length && whichTypeAdded) { + setTimeout(() => { + if (whichTypeAdded === "video" && videoAvailabileInCart) { + asyncAwesomeAlert("", "به سبد خرید اضافه شد", { + showCancelButton: true, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + cancelText: "باشه", + }); + } else if (whichTypeAdded === "physical" && physicalAvailabileInCart) { + asyncAwesomeAlert("", "به سبد خرید اضافه شد", { + showCancelButton: true, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + cancelText: "باشه", + }); + } else if (whichTypeAdded === "digital" && digitalAvailabileInCart) { + asyncAwesomeAlert("", "به سبد خرید اضافه شد", { + showCancelButton: true, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + cancelText: "باشه", + }); + } + setWhichTypeAdded(null); + }, 500); + } + }, [userProducts]); + return ( {!mobile && } - {(!book || userFavoriteLoading) && ( + {(!book) && ( physicalAvailabileInCart ? asyncAwesomeAlert( - "نتیجه", - "این محصول قبلا به سبد خرید اضافه شده است.", + "", + "این محصول قبلا به سبد خرید شما اضافه شده است.", { - showCancelButton: false, + showCancelButton: true, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + cancelText: "باشه", } ) - : pushToCart({ - productId: book?.product[1]?.id, - userId: userId, - count: 1, - }) + : addToCart( + pushToCart({ + productId: book?.product[1]?.id, + userId: userId, + count: 1, + }), + "physical" + ) } > <> @@ -278,17 +329,23 @@ function Book({ onPress={() => digitalAvailabileInCart ? asyncAwesomeAlert( - "خطا", - "این محصول قبلا به سبد خرید اضافه شده است.", + "", + "این محصول قبلا به سبد خرید شما اضافه شده است.", { - showCancelButton: false, + showCancelButton: true, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + cancelText: "باشه", } ) - : pushToCart({ - productId: book?.product[0]?.id, - userId: userId, - count: 1, - }) + : addToCart( + pushToCart({ + productId: book?.product[0]?.id, + userId: userId, + count: 1, + }), + "digital" + ) } > <> @@ -356,11 +413,25 @@ function Book({ }, ]} onPress={() => - pushToCart({ - productId: book?.product[2]?.id, - userId: userId, - count: 1, - }) + videoAvailabileInCart + ? asyncAwesomeAlert( + "", + "این محصول قبلا به سبد خرید شما اضافه شده است.", + { + showCancelButton: true, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + cancelText: "باشه", + } + ) + : addToCart( + pushToCart({ + productId: book?.product[2]?.id, + userId: userId, + count: 1, + }), + "video" + ) } > <> diff --git a/src/screens/Profile/components/User.js b/src/screens/Profile/components/User.js index e498d67..62e3145 100644 --- a/src/screens/Profile/components/User.js +++ b/src/screens/Profile/components/User.js @@ -133,7 +133,7 @@ const User = ({ user, mobile, theme, logout }) => { style={tw(`flex w-full ${mobile ? "mt-0" : "mt-4"}`)} onPress={() => asyncAwesomeAlert( - "نتیجه", + "", "آیا قصد خروج از حساب کاربری فعلی رو داری؟", { showCancelButton: true, diff --git a/src/screens/ShoppingCart/components/Code.js b/src/screens/ShoppingCart/components/Code.js index 7baa066..2ef04ae 100644 --- a/src/screens/ShoppingCart/components/Code.js +++ b/src/screens/ShoppingCart/components/Code.js @@ -5,6 +5,7 @@ import { Pressable, TextInput, KeyboardAvoidingView, + ActivityIndicator, } from "react-native"; import { connect } from "react-redux"; import { userFactor } from "../../../redux/actions"; @@ -14,13 +15,21 @@ import fontSize from "../../../constants/fontSize"; import Colors from "../../../constants/Colors"; import tw from "tailwind-rn"; -function Code({ codeId, setCodeId, userId, factorId, theme }) { +function Code({ codeId, setCodeId, theme, loading }) { const [value, setValue] = React.useState(codeId || ""); + const [requestFlag, setRequestFlag] = React.useState(false); const setOff = () => { - setCodeId({ offCodeValue: value, userId: userId, id: factorId }); + setRequestFlag(true); + setCodeId({ offCodeValue: value }); }; + React.useEffect(() => { + if (!loading) { + setRequestFlag(false); + } + }, [loading]); + return ( setValue(text)} + onChangeText={(text) => setValue(text)} style={[ tw("border-0 flex-1 text-right pr-3"), { fontSize: fontSize.tiny, fontFamily: "regular" }, ]} placeholder={"کد تخفیف دارید ؟"} - placeholderTextColor={Colors.theme1[theme].gray20 + 'aa'} + placeholderTextColor={Colors.theme1[theme].gray20 + "aa"} /> setOff()} @@ -52,14 +61,22 @@ function Code({ codeId, setCodeId, userId, factorId, theme }) { }, ]} > - - ثبت کد - + {loading && requestFlag ? ( + + ) : ( + + ثبت کد + + )} @@ -68,9 +85,8 @@ function Code({ codeId, setCodeId, userId, factorId, theme }) { const mapStateToProps = (state) => ({ codeId: state.userFactor.info?.codeId, - userId: state.user.status?.id, - factorId: state.userFactor.info?.id, - theme: state.publicApi.theme + loading: state.userFactor.loading, + theme: state.publicApi.theme, }); const mapDispatchToProps = { diff --git a/src/screens/ShoppingCart/components/Product.js b/src/screens/ShoppingCart/components/Product.js index e919df9..258a936 100644 --- a/src/screens/ShoppingCart/components/Product.js +++ b/src/screens/ShoppingCart/components/Product.js @@ -21,7 +21,7 @@ import tw from "tailwind-rn"; const width = Dimensions.get("window").width; const ios = Platform.OS === "ios"; -function Product({ product, grades, pushToCart, loading, mobile, theme }) { +function Product({ product, grades, pushToCart, loading, mobile, theme, addActionFlag, getList }) { const [selectedProduct, setSelectedProduct] = React.useState(null); const submit = async (action) => { @@ -30,234 +30,241 @@ function Product({ product, grades, pushToCart, loading, mobile, theme }) { }; React.useEffect(() => { - if(!loading){ + if (!loading) { setSelectedProduct(null); } - },[loading]); + }, [loading]); return ( - - - - - - {product?.product?.book?.name || " "} - - - {"پایه" + " " + grades[product?.product?.book?.gradeId] || " "} - - + + - {product?.productType || 1 === 2 ? "نسخه فیزیکی" : "نسخه دیجیتال"} - + style={[ + tw(""), + { + width: mobile ? width / 5 : width / 7, + height: ((mobile ? width / 5 : width / 7) * 4) / 2.8, + }, + ]} + /> - {" " + "تومان"} + {product.product.book.name || " "} - {separate(product?.product?.price) || " "} + {"پایه" + " " + grades[product.product.book.gradeId] || " "} - - - - - - submit( - pushToCart( - { - productId: product?.productId, - userId: product?.userId, - count: product?.productType === 1 ? -1 : -product?.count, - }, - {}, - { id: product?.factorId } - ) - ) - } - /> - - - - submit( - pushToCart({ - productId: product?.productId, - userId: product?.userId, - count: 1, - }) - ) - } - style={[ - tw( - `rounded-md py-0 flex flex-row justify-center items-center border ${ - mobile ? "px-2" : "px-3" - }` - ), - { - borderColor: Colors.theme1[theme].greenCF, - }, - ]} + + {product.productType || 1 === 2 ? "نسخه فیزیکی" : "نسخه دیجیتال"} + + - + + {" " + "تومان"} - - {loading && selectedProduct === product?.productId ? ( - - ) : ( - {product?.count} + {separate(product.product.price) || " "} - )} - - - submit( - pushToCart({ - productId: product?.productId, - userId: product?.userId, - count: -1, - }) + + + + + + submit( + pushToCart( + { + productId: product.productId, + userId: product.userId, + count: product.productType === 1 ? -1 : -product?.count, + }, + {}, + { id: product.factorId } ) - } - style={[ - tw( - `rounded-md py-0 flex flex-row justify-center items-center border ${ - mobile ? "px-2.5" : "px-3.5" - }` - ), - { - borderColor: Colors.theme1[theme].greenCF, - }, - ]} + ) + } + /> + + + + submit( + pushToCart({ + productId: product.productId, + userId: product.userId, + count: 1, + }) + ) + } + style={[ + tw( + `rounded-md py-0 flex flex-row justify-center items-center border ${ + mobile ? "px-2" : "px-3" + }` + ), + { + borderColor: Colors.theme1[theme].greenCF, + }, + ]} + > + + + + + + {(loading && selectedProduct === product.productId) ? ( + + ) : ( + + {product.count} + + )} + + + submit( + pushToCart({ + productId: product.productId, + userId: product.userId, + count: -1, + }) + ) + } + style={[ + tw( + `rounded-md py-0 flex flex-row justify-center items-center border ${ + mobile ? "px-2.5" : "px-3.5" + }` + ), + { + borderColor: Colors.theme1[theme].greenCF, + }, + ]} + > + + - + + + + + + {" " + "تومان"} + - - + {separate(product.product.price * product.count) || " "} - - - - - {" " + "تومان"} - - - {separate(product?.product?.price * product?.count) || " "} - + - + ) ); } @@ -265,10 +272,12 @@ const mapStateToProps = (state) => ({ grades: state.publicApi.grades, mobile: state.publicApi.mobile, theme: state.publicApi.theme, + addActionFlag: state.userProduct.addActionFlag, }); const mapDispatchToProps = { pushToCart: userProduct.add, + getList: userProduct.list }; export default connect(mapStateToProps, mapDispatchToProps)(Product); diff --git a/src/screens/ShoppingCart/index.js b/src/screens/ShoppingCart/index.js index 92c4e44..5f1403e 100644 --- a/src/screens/ShoppingCart/index.js +++ b/src/screens/ShoppingCart/index.js @@ -91,7 +91,7 @@ function ShoppingCart({ getFactorInfo, loading, payFactor, - theme + theme, }) { const navigation = useNavigation(); const [position, setPosition] = useState("100%"); @@ -109,9 +109,7 @@ function ShoppingCart({ }, [list]); useEffect(() => { - if (list.length === 0) { - getList(); - } + getList(); getFactorInfo({ userId }); }, []); @@ -293,7 +291,7 @@ const mapStateToProps = (state) => ({ userId: state.user.status?.id, hasPhysical: state.userProduct.hasPhysical, loading: state.userProduct.loading, - theme: state.publicApi.theme + theme: state.publicApi.theme, }); const mapDispatchToProps = { diff --git a/src/screens/Video/index.js b/src/screens/Video/index.js index 829b229..d21c965 100644 --- a/src/screens/Video/index.js +++ b/src/screens/Video/index.js @@ -11,9 +11,11 @@ import { Text, Appearance, } from "react-native"; +import { useNavigation } from "@react-navigation/native"; import { connect } from "react-redux"; import { publicApi, userProduct } from "../../redux/actions"; import separate from "../../utils/separate"; +import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; //components import Navbar from "../../components/Navbar"; @@ -40,10 +42,12 @@ function Product({ pushToCart, loading, mobile, - theme + theme, + userProducts, }) { const [position, setPosition] = useState("100%"); - + const navigation = useNavigation(); + const [addedFlag, setAddedFlag] = React.useState(false); useEffect(() => { getBook({ bookId: route.params.id }, { id: route.params.id, vod: true }); }, []); @@ -52,6 +56,32 @@ function Product({ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); setPosition(position === "100%" ? "0%" : "100%"); }; + + const videoAvailabileInCart = React.useMemo(() => { + return userProducts?.filter( + (product) => product?.productId === book?.product[2]?.id + )[0]; + }, [userProducts, book]); + + const addToCart = React.useCallback( + async (action) => { + setAddedFlag(true); + await action(); + }, + [book, userId] + ); + + React.useEffect(() => { + if (videoAvailabileInCart && addedFlag) { + setAddedFlag(false); + asyncAwesomeAlert("", "به سبد خرید اضافه شد", { + showCancelButton: false, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + }); + } + }, [userProducts]); + return ( @@ -135,11 +168,24 @@ function Product({ width={"100%"} loading={loading} onPress={() => - pushToCart({ - productId: book?.product[2]?.id, - userId: userId, - count: 1, - }) + videoAvailabileInCart + ? asyncAwesomeAlert( + "", + "این محصول قبلا به سبد خرید شما اضافه شده است.", + { + showCancelButton: true, + onConfirm: () => navigation.push("ShoppingCart"), + confirmText: "مشاهده سبد خرید", + cancelText: "باشه", + } + ) + : addToCart( + pushToCart({ + productId: book?.product[2]?.id, + userId: userId, + count: 1, + }) + ) } /> @@ -170,13 +216,14 @@ const styles = StyleSheet.create({ const mapStateToProps = (state) => ({ book: state.book.info, + userProducts: state.userProduct.list, seasons: state.publicApi.categories, grades: state.publicApi.grades, isLogin: state.user.status, userId: state.user.status?.id, loading: state.userProduct.loading, mobile: state.publicApi.mobile, - theme: state.publicApi.theme + theme: state.publicApi.theme, }); const mapDispatchToProps = { diff --git a/src/screens/VideoDisplay/index.js b/src/screens/VideoDisplay/index.js index c722aa1..f136b91 100644 --- a/src/screens/VideoDisplay/index.js +++ b/src/screens/VideoDisplay/index.js @@ -31,7 +31,6 @@ const ios = Platform.OS === "ios"; function VideoDisplay({ route, mobile, theme }) { const video = React.useRef(null); const [width, setWidth] = useState(Dimensions.get("window").width); - const [status, setStatus] = React.useState({}); const [position, setPosition] = useState("100%"); const setBoxPosition = () => { @@ -39,15 +38,7 @@ function VideoDisplay({ route, mobile, theme }) { setPosition(position === "100%" ? "0%" : "100%"); }; - const setOrientation = () => { - if (Dimensions.get("window").height > Dimensions.get("window").width) { - //Device is in portrait mode, rotate to landscape mode. - ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE); - } else { - //Device is in landscape mode, rotate to portrait mode. - ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT); - } - } + console.log(video); return (