diff --git a/src/redux/actions/config.js b/src/redux/actions/config.js index c764dff..471295f 100644 --- a/src/redux/actions/config.js +++ b/src/redux/actions/config.js @@ -9,6 +9,10 @@ const config = { (data = {}) => async (dispatch) => await proxy.get("config/filters", data, { dispatch }), + getAvailableForSell: + (data = {}) => + async (dispatch) => + await proxy.get("config/availableForSell", data, { dispatch }), }; export default config; diff --git a/src/redux/proxy.js b/src/redux/proxy.js index 9237955..57dc4e6 100644 --- a/src/redux/proxy.js +++ b/src/redux/proxy.js @@ -60,6 +60,7 @@ class Proxy { dispatch = dispatch || (() => {}); dispatch({ type: url.split("/")[0] + "/" + "loading" }); let response = await fetch(); + // console.log(response); switch (response.status) { case 200: dispatch({ type: url, data: response.data.data, params }); diff --git a/src/redux/reducers/config.js b/src/redux/reducers/config.js index 6e917bb..02c42b5 100644 --- a/src/redux/reducers/config.js +++ b/src/redux/reducers/config.js @@ -2,6 +2,7 @@ const initialState = { loading: false, error: null, bottomNavigation: null, + availableForSell: [], }; export default function config(state = initialState, action) { @@ -14,6 +15,14 @@ export default function config(state = initialState, action) { bottomNavigation: data.bottomNavigationList, error: null, }; + case "config/availableForSell": + console.log(data); + return { + ...state, + loading: false, + availableForSell: data.productTypes, + error: null, + }; case "config/loading": return { ...state, loading: true }; case "config/error": @@ -21,4 +30,4 @@ export default function config(state = initialState, action) { default: return state; } -} \ No newline at end of file +} diff --git a/src/redux/reducers/file.js b/src/redux/reducers/file.js index 47c9dde..b9df297 100644 --- a/src/redux/reducers/file.js +++ b/src/redux/reducers/file.js @@ -7,7 +7,7 @@ export default function file(state = initialState, action) { let { type, data, params } = action; switch (type) { case "file/upload": - console.log(data, params); + console.log(data); return { ...state, loading: false, diff --git a/src/screens/Product/components/Book.js b/src/screens/Product/components/Book.js index d7165f1..dae41a6 100644 --- a/src/screens/Product/components/Book.js +++ b/src/screens/Product/components/Book.js @@ -18,7 +18,6 @@ import separate from "../../../utils/separate"; //components import LinkBox from "./LinkBox"; import Comments from "./Comments"; -import ImageSlider from "../../../components/ImageSlider"; import Rates from "./Rates"; //style @@ -39,20 +38,23 @@ function Book({ userProducts, theme, orientation, + availableForSell, }) { const [width, setWidth] = React.useState(Dimensions.get("window").width); const navigation = useNavigation(); - const [type, setType] = useState(1); const [whichTypeAdded, setWhichTypeAdded] = React.useState(null); - const [pageLoading, setPageLoading] = useState(false); - const [imageSlider, setImageSlider] = useState(false); - useEffect(() => { - setPageLoading(true); - setTimeout(() => { - setPageLoading(false); - }, 500); - }, [type]); + 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]; @@ -134,6 +136,144 @@ function Book({ } }, [userProducts]); + const ProductButton = ({ + availableInCart, + availableForSell, + product, + type, + onLoad, + title, + sample, + sampleAction, + }) => { + return product ? ( + + + 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 ? ( + + ) : ( + + {title} + + )} + + + + + + {availableForSell + ? (separate(product?.price) || " ") + " " + "تومان" + : "ناموجود"} + + + + + + {sample ? ( + sampleAction()} + > + + مشاهده نمونه + + + ) : null} + + ) : null; + }; + return ( {" "} - {4.8 + "\n" + "امتیاز"} + {book?.rate || 4 + "\n" + "امتیاز"} {book?.product?.length > 1 ? ( - - - نسخه محصول را انتخاب کنید - - - + fontSize: mobile ? fontSize.tiny : fontSize.base, + fontFamily: "demi", + }, + ]} + > + نسخه محصول را انتخاب کنید + ) : null} - - {physicalProduct ? ( - - physicalAvailabileInCart - ? asyncAwesomeAlert( - "", - "این محصول قبلا به سبد خرید شما اضافه شده است.", - { - showCancelButton: true, - onConfirm: () => - navigation.navigate("Root", { - screen: "ShoppingCartTab", - }), - confirmText: "مشاهده سبد خرید", - cancelText: "باشه", - } - ) - : addToCart( - pushToCart({ - productId: physicalProduct?.id, - userId: userId, - count: 1, - }), - "physical" - ) - } - > - <> - {whichTypeAdded === "physical" && userProductsLoading ? ( - - ) : ( - - خرید نسخه فیزیکی کتاب - - )} - - - - - - {(separate(physicalProduct?.price) || " ") + " " + "تومان"} - - - - - - ) : null} - {physicalProduct ? ( - - navigation.push("Sample", { id: book?.sampleFileId }) - } - > - - مشاهده نمونه - - - ) : null} - - {digitalProduct ? ( - - digitalAvailabileInCart - ? asyncAwesomeAlert( - "", - "این محصول قبلا به سبد خرید شما اضافه شده است.", - { - showCancelButton: true, - onConfirm: () => - navigation.navigate("Root", { - screen: "ShoppingCartTab", - }), - confirmText: "مشاهده سبد خرید", - cancelText: "باشه", - } - ) - : addToCart( - pushToCart({ - productId: digitalProduct?.id, - userId: userId, - count: 1, - }), - "digital" - ) - } - > - <> - {whichTypeAdded === "digital" && userProductsLoading ? ( - - ) : ( - - خرید نسخه دیجیتال کتاب - - )} - - - {(separate(digitalProduct?.price) || " ") + " " + "تومان"} - - - - - ) : null} - {digitalProduct ? ( - navigation.navigate("Video", { id: book?.id })} - > - - پیش نمایش - - - ) : null} - - {videoProduct ? ( - - videoAvailabileInCart - ? asyncAwesomeAlert( - "", - "این محصول قبلا به سبد خرید شما اضافه شده است.", - { - showCancelButton: true, - onConfirm: () => - navigation.navigate("Root", { - screen: "ShoppingCartTab", - }), - confirmText: "مشاهده سبد خرید", - cancelText: "باشه", - } - ) - : addToCart( - pushToCart({ - productId: videoProduct?.id, - userId: userId, - count: 1, - }), - "video" - ) - } - > - <> - {whichTypeAdded === "video" && userProductsLoading ? ( - - ) : ( - + + navigation.push("Sample", { id: book?.sampleFileId }) + } + /> - paddingVertical: 4, - }} - > - خرید دوره ویدئویی کتاب - - )} - - - navigation.navigate("Video", { id: book?.id })} + /> - fontSize: fontSize.sm, - }, - ]} - > - {(separate(videoProduct?.price) || " ") + " " + "تومان"} - - - - - ) : null} + {}} + /> {book?.text ? ( ({ mobile: state.publicApi.mobile, orientation: state.publicApi.orientation, theme: state.publicApi.theme, + availableForSell: state.config.availableForSell, }); const mapDispatchToProps = { diff --git a/src/screens/Product/index.js b/src/screens/Product/index.js index bb21f72..54cb193 100644 --- a/src/screens/Product/index.js +++ b/src/screens/Product/index.js @@ -9,14 +9,15 @@ import { KeyboardAvoidingView, } from "react-native"; import Book from "./components/Book"; -import { book } from "../../redux/actions"; +import { book, config } from "../../redux/actions"; import { connect } from "react-redux"; import Navbar from "../../components/Navbar"; const { height, width } = Dimensions.get("window"); -function Product({ route, book, getBook, grades }) { +function Product({ route, book, getBook, grades, getAvailableForSell }) { useEffect(() => { + getAvailableForSell(); getBook({ id: route.params.id, vod: true }); }, []); @@ -69,6 +70,7 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = { getBook: book.info, + getAvailableForSell: config.getAvailableForSell }; export default connect(mapStateToProps, mapDispatchToProps)(Product); diff --git a/src/screens/Profile/components/User.js b/src/screens/Profile/components/User.js index 575ff98..1be0811 100644 --- a/src/screens/Profile/components/User.js +++ b/src/screens/Profile/components/User.js @@ -31,9 +31,7 @@ const User = ({ user, mobile, theme, upload }) => { quality: 1, }); - console.log(result); - - upload(result); + upload({file : result, name : 'file'}); if (!result.cancelled) { setImage(result.uri); diff --git a/src/screens/Splash/index.js b/src/screens/Splash/index.js index 6613c49..19d1a52 100644 --- a/src/screens/Splash/index.js +++ b/src/screens/Splash/index.js @@ -4,7 +4,6 @@ import { Image, ActivityIndicator, Dimensions, - BackHandler, StatusBar, } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; @@ -16,7 +15,6 @@ import { publicApi, config, } from "../../redux/actions"; -import { useIsFocused } from "@react-navigation/native"; import Logo from "../../assets/images/logo.png"; @@ -87,6 +85,7 @@ function Splash({ alignItems: "center", flex: 1, display: "flex", + backgroundColor : 'white' }} > @@ -101,7 +100,7 @@ function Splash({ diff --git a/src/screens/Video/components/Season.js b/src/screens/Video/components/Season.js index 24b9bf4..59ef543 100644 --- a/src/screens/Video/components/Season.js +++ b/src/screens/Video/components/Season.js @@ -1,6 +1,7 @@ import React from "react"; import { View, Text, Pressable, Appearance } from "react-native"; import { SimpleLineIcons } from "@expo/vector-icons"; +import { asyncAwesomeAlert } from "../../../utils/AsyncWrappers"; import { connect } from "react-redux"; import { publicApi } from "../../../redux/actions"; import { useNavigation } from "@react-navigation/native"; @@ -24,6 +25,7 @@ const duration = (value) => { const Season = ({ season, + videoBuyed, toggle, activeSeason, realSeasons, @@ -89,7 +91,11 @@ const Season = ({ Number(index) === 0 ? Colors.theme1.greenCF : theme === "light" - ? Colors.theme1.gray2077 + ? videoBuyed + ? Colors.theme1.greenCF + : Colors.theme1.gray2077 + : videoBuyed + ? Colors.theme1.greenCF : Colors.theme1.white + "66", }, ]} @@ -99,8 +105,19 @@ const Season = ({ season: season, unit: unit, name: seasonName, + videoBuyed: videoBuyed, + }) + : videoBuyed + ? navigation.navigate("VideoDisplay", { + season: season, + unit: unit, + name: seasonName, + videoBuyed: videoBuyed, + }) + : asyncAwesomeAlert("خطا", "ابتدا دوره را خریداری کنید", { + showCancelButton: false, + confirmText: "باشه", }) - : {} } > diff --git a/src/screens/Video/index.js b/src/screens/Video/index.js index ae0faec..c9c1489 100644 --- a/src/screens/Video/index.js +++ b/src/screens/Video/index.js @@ -13,7 +13,7 @@ import { } from "react-native"; import { useNavigation } from "@react-navigation/native"; import { connect } from "react-redux"; -import { publicApi, userProduct } from "../../redux/actions"; +import { publicApi, userProduct, config } from "../../redux/actions"; import separate from "../../utils/separate"; import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; @@ -44,11 +44,15 @@ function Product({ mobile, theme, userProducts, + getAvailableForSell, + availableForSell, }) { const [position, setPosition] = useState("100%"); const navigation = useNavigation(); const [addedFlag, setAddedFlag] = React.useState(false); + useEffect(() => { + getAvailableForSell(); getBook({ bookId: route.params.id }, { id: route.params.id, vod: true }); }, []); @@ -57,12 +61,29 @@ function Product({ setPosition(position === "100%" ? "0%" : "100%"); }; + const videoProduct = React.useMemo(() => { + return book?.product?.filter((product) => product?.productType === 4)[0]; + }, [book]); + const videoAvailabileInCart = React.useMemo(() => { return userProducts?.filter( - (product) => product?.productId === book?.product[2]?.id - )[0]; + (product) => + product?.productId === videoProduct?.id && product?.condition < 2 + )?.length; + }, [userProducts, book]); + + const videoBuyed = React.useMemo(() => { + return userProducts?.filter( + (product) => + product?.productId === videoProduct?.id && product?.condition >= 2 + )?.length; }, [userProducts, book]); + + const videoAvailableForSell = React.useMemo(() => { + return availableForSell?.filter((product) => product === 4)?.length; + }, [availableForSell]); + const addToCart = React.useCallback( async (action) => { setAddedFlag(true); @@ -170,9 +191,13 @@ function Product({ @@ -207,7 +234,7 @@ function Product({ {seasons ?.sort((a, b) => a[0]?.categoryId - b[0]?.categoryId) ?.map((season, index) => ( - + ))} @@ -235,10 +262,12 @@ const mapStateToProps = (state) => ({ loading: state.userProduct.loading, mobile: state.publicApi.mobile, theme: state.publicApi.theme, + availableForSell: state.config.availableForSell, }); const mapDispatchToProps = { getBook: publicApi.bookInfo, pushToCart: userProduct.add, + getAvailableForSell: config.getAvailableForSell, }; export default connect(mapStateToProps, mapDispatchToProps)(Product); diff --git a/src/screens/VideoDisplay/components/Season/index.js b/src/screens/VideoDisplay/components/Season/index.js index beebbfe..48ae9cf 100644 --- a/src/screens/VideoDisplay/components/Season/index.js +++ b/src/screens/VideoDisplay/components/Season/index.js @@ -30,6 +30,7 @@ const Season = ({ setVideoActive, mobile, theme, + videoBuyed, }) => { const navigation = useNavigation(); diff --git a/src/screens/VideoDisplay/index.js b/src/screens/VideoDisplay/index.js index 783f274..6eef38e 100644 --- a/src/screens/VideoDisplay/index.js +++ b/src/screens/VideoDisplay/index.js @@ -28,7 +28,6 @@ import Colors from "../../constants/Colors"; const ios = Platform.OS === "ios"; - function VideoDisplay({ route, mobile, theme }) { const video = React.useRef(null); const [width, setWidth] = useState(Dimensions.get("window").width); @@ -42,7 +41,9 @@ function VideoDisplay({ route, mobile, theme }) { const onFullscreenUpdate = async ({ fullscreenUpdate }) => { if (fullscreenUpdate === Video.FULLSCREEN_UPDATE_PLAYER_DID_PRESENT) { await ScreenOrientation.unlockAsync(); - } else if (fullscreenUpdate === Video.FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS) { + } else if ( + fullscreenUpdate === Video.FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS + ) { await ScreenOrientation.lockAsync( ScreenOrientation.OrientationLock.PORTRAIT ); @@ -95,7 +96,7 @@ function VideoDisplay({ route, mobile, theme }) { style={{ fontSize: fontSize.xl, fontFamily: "bold", - marginTop: mobile ? 8 : 12, + marginTop: mobile ? 20 : 12, color: theme === "light" ? Colors.theme1.gray20 : Colors.theme1.white, textAlign: "right", @@ -113,11 +114,14 @@ function VideoDisplay({ route, mobile, theme }) { > - + {route?.params?.videoBuyed ? ( + + ) : null} diff --git a/src/screens/Videos/components/MostViewedVideo.js b/src/screens/Videos/components/MostViewedVideo.js index 8079207..a940f9d 100644 --- a/src/screens/Videos/components/MostViewedVideo.js +++ b/src/screens/Videos/components/MostViewedVideo.js @@ -52,9 +52,7 @@ function MostViewedVideo({ videos, grades, mobile, theme }) { source={{ uri: `https://dnvn.ir/api/v1/file/${video.fileIds}` }} resizeMode="contain" style={[ - tw( - `rounded-sm h-full absolute left-2` - ), + tw(`rounded-sm h-full absolute left-2`), { width: mobile ? 70 : 105, height: mobile ? 110 : 150, @@ -110,7 +108,11 @@ function MostViewedVideo({ videos, grades, mobile, theme }) { }, ]} > - {separate(video?.product?.filter((product) => product?.productType === 4)[0]?.price)} + {separate( + video?.product?.filter( + (product) => product?.productType === 4 + )[0]?.price + )} @@ -136,16 +138,18 @@ function MostViewedVideo({ videos, grades, mobile, theme }) { return ( -
+ +
+