update 5 files

master
Reza_ashrafi 2 years ago
parent 30cc3dfa9b
commit 6bab87262e
  1. 31
      src/components/ButtonBetween/index.js
  2. 6
      src/redux/actions/config.js
  3. 8
      src/redux/reducers/config.js
  4. 8
      src/router.js
  5. 271
      src/views/Product/index.js

@ -1,6 +1,9 @@
import React from "react"; import React from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
//components
import Loading from "../Loading";
export const ButtonBetween = ({ export const ButtonBetween = ({
item, item,
status, status,
@ -8,6 +11,7 @@ export const ButtonBetween = ({
width, width,
active, active,
toggle, toggle,
loading,
}) => { }) => {
return toggle ? ( return toggle ? (
<button <button
@ -17,13 +21,18 @@ export const ButtonBetween = ({
onClick={() => onClick()} onClick={() => onClick()}
style={{ width, padding: "18px 8px" }} style={{ width, padding: "18px 8px" }}
> >
<strong {loading ? (
className={`text-tiny ${ <Loading size={2} color="bg-green-500" />
active ? "text-green-700" : "text-gray-700" ) : (
} font-semibold`} <strong
> className={`text-tiny ${
{item} active ? "text-green-700" : "text-gray-700"
</strong> } font-semibold`}
>
{item}
</strong>
)}
{status && ( {status && (
<span <span
className={`pr-3 border-r border-solid ${ className={`pr-3 border-r border-solid ${
@ -42,7 +51,13 @@ export const ButtonBetween = ({
onClick={() => onClick()} onClick={() => onClick()}
style={{ width, padding: "18px 8px" }} style={{ width, padding: "18px 8px" }}
> >
<strong className="text-tiny text-green-700 font-semibold">{item}</strong> {loading ? (
<Loading size={2} color="bg-green-500" />
) : (
<strong className="text-tiny text-green-700 font-semibold">
{item}
</strong>
)}
{status && ( {status && (
<span className="pr-3 border-r border-solid border-green-600 text-tiny text-green-700 font-semibold"> <span className="pr-3 border-r border-solid border-green-600 text-tiny text-green-700 font-semibold">
{status} {status}

@ -1,6 +1,12 @@
import proxy from "../proxy";
const config = { const config = {
setDevice: (data) => async (dispatch) => setDevice: (data) => async (dispatch) =>
await dispatch({ type: "config/setDevice", data }), await dispatch({ type: "config/setDevice", data }),
getAvailableForSell:
(data = {}) =>
async (dispatch) =>
await proxy.get("config/availableForSell", data, { dispatch }),
}; };
export default config; export default config;

@ -1,5 +1,6 @@
const initialState = { const initialState = {
device: "mobile", device: "mobile",
availableForSell: [],
}; };
export default function config(state = initialState, action) { export default function config(state = initialState, action) {
@ -10,6 +11,13 @@ export default function config(state = initialState, action) {
...state, ...state,
device: data, device: data,
}; };
case "config/availableForSell":
return {
...state,
loading: false,
availableForSell: data.productTypes,
error: null,
};
default: default:
return state; return state;
} }

@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom"; import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Navigate } from "react-router-dom"; import { Navigate } from "react-router-dom";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { publicApi, menu, config } from "./redux/actions"; import { publicApi, menu, config, userProduct } from "./redux/actions";
import Navbar from "./components/Navbar"; import Navbar from "./components/Navbar";
import BG from "./components/BG"; import BG from "./components/BG";
import BottomNavigation from "./components/BottomNavigation"; import BottomNavigation from "./components/BottomNavigation";
@ -44,8 +44,12 @@ function Router({
setMenu, setMenu,
setDevice, setDevice,
device, device,
getAvailableForSell,
getUserProducts
}) { }) {
useEffect(() => { useEffect(() => {
getAvailableForSell();
getUserProducts();
const width = window.innerWidth; const width = window.innerWidth;
if (width <= 640) { if (width <= 640) {
setDevice("mobile"); setDevice("mobile");
@ -602,6 +606,8 @@ const mapDispatchToProps = {
setDesktopContentTransform: publicApi.setDesktopContentTransform, setDesktopContentTransform: publicApi.setDesktopContentTransform,
setMenu: menu.set, setMenu: menu.set,
setDevice: config.setDevice, setDevice: config.setDevice,
getAvailableForSell: config.getAvailableForSell,
getUserProducts: userProduct.list
}; };
export default connect(mapStateToProps, mapDispatchToProps)(Router); export default connect(mapStateToProps, mapDispatchToProps)(Router);

@ -1,7 +1,7 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { book, userProduct, publicApi } from "../../redux/actions"; import { book, userProduct, publicApi, dialog } from "../../redux/actions";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import proxy from "../../redux/proxy"; import proxy from "../../redux/proxy";
import location from "../../utils/location"; import location from "../../utils/location";
@ -22,6 +22,7 @@ import arrow from "../../assets/icons/dropdown-blue.svg";
export const Product = ({ export const Product = ({
isMobile, isMobile,
productType, productType,
userProducts,
getInfo, getInfo,
book, book,
grades, grades,
@ -29,13 +30,60 @@ export const Product = ({
userId, userId,
pushToCart, pushToCart,
headerOptions, headerOptions,
bookmarkLoading, userProductLoading,
setHeaderOptions, setHeaderOptions,
availableForSell,
setDialog,
}) => { }) => {
const [type, setType] = useState("physical"); const [whichTypeAdded, setWhichTypeAdded] = React.useState(null);
const [desktopContentTransform, setDesktopContentTransform] = useState(false); const [desktopContentTransform, setDesktopContentTransform] = useState(false);
const navigation = useNavigate(); const navigation = useNavigate();
const physicalAvailableForSell = React.useMemo(() => {
return availableForSell?.find((product) => product === 2);
}, [availableForSell]);
const digitalAvailableForSell = React.useMemo(() => {
return availableForSell?.find((product) => product === 1);
}, [availableForSell]);
const videoAvailableForSell = React.useMemo(() => {
return availableForSell?.find((product) => product === 4);
}, [availableForSell]);
const physicalProduct = React.useMemo(() => {
return book?.product?.find((product) => product?.productType === 2);
}, [book]);
const digitalProduct = React.useMemo(() => {
return book?.product?.find((product) => product?.productType === 1);
}, [book]);
const videoProduct = React.useMemo(() => {
return book?.product?.find((product) => product?.productType === 4);
}, [book]);
const physicalAvailabileInCart = React.useMemo(() => {
return userProducts?.find(
(product) =>
product?.productId === physicalProduct?.id && product?.condition < 2
);
}, [userProducts, book]);
const digitalAvailabileInCart = React.useMemo(() => {
return userProducts?.find(
(product) =>
product?.productId === digitalProduct?.id && product?.condition < 2
);
}, [userProducts, book]);
const videoAvailabileInCart = React.useMemo(() => {
return userProducts?.find(
(product) =>
product?.productId === videoProduct?.id && product?.condition < 2
);
}, [userProducts, book]);
useEffect(() => { useEffect(() => {
getInfo({ id: location.getId(), vod: true }); getInfo({ id: location.getId(), vod: true });
if (!isMobile) { if (!isMobile) {
@ -49,6 +97,12 @@ export const Product = ({
} }
}, []); }, []);
useEffect(() => {
if (!userProductLoading) {
setWhichTypeAdded(null);
}
}, [userProductLoading]);
useEffect(() => { useEffect(() => {
if (book) { if (book) {
setHeaderOptions({ ...headerOptions, productId: book?.id }); setHeaderOptions({ ...headerOptions, productId: book?.id });
@ -92,7 +146,11 @@ export const Product = ({
{book?.pagesNum} <br /> صفحه {book?.pagesNum} <br /> صفحه
</li> </li>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white"> <li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white">
{"فیزیکی - دیجیتالی"} <br /> در دسترس <span>{videoAvailableForSell ? "ویدئویی - " : ""}</span>
<span>{digitalAvailableForSell ? "دیجیتال - " : ""}</span>
<span>{physicalAvailableForSell ? "فیزیکی" : ""}</span>
<br /> در دسترس
</li> </li>
{book?.rate ? ( {book?.rate ? (
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white"> <li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-tiny leading-5 font-medium text-green7B dark:text-white">
@ -103,66 +161,147 @@ export const Product = ({
<h2 className="text-green7B text-base font-semibold mt-10 dark:text-greenBA"> <h2 className="text-green7B text-base font-semibold mt-10 dark:text-greenBA">
نسخه محصول را انتخاب کنید نسخه محصول را انتخاب کنید
</h2> </h2>
<div className="w-full flex justify-between items-center mt-5"> {physicalProduct && physicalAvailableForSell ? (
<ButtonBetween <div className="w-full flex justify-between items-center mt-5 gap-2">
width="100%" <ButtonBetween
item={"خرید نسخه فیزیکی کتاب"} width="72%"
status={separate(book?.product[1]?.price) + " " + "تومان"} item={"خرید نسخه فیزیکی کتاب"}
onClick={() => status={separate(physicalProduct?.price) + " " + "تومان"}
userId onClick={() => {
? pushToCart({ if (userId) {
productId: book?.product[1]?.id, if (physicalAvailabileInCart) {
userId, setDialog({
count: 1, text: window.t(
}) "این محصول قبلا به سبد خرید شما اضافه شده است."
: toast.info("ابتدا وارد حساب کاربری خود شوید.") ),
} type: "confirm",
/> accept: () => navigation("/cart"),
</div> open: true,
<div className="w-full flex justify-between items-center mt-4 gap-2"> });
<ButtonBetween } else {
width="72%" setWhichTypeAdded("physical");
item={"خرید نسخه دیجیتال کتاب"} pushToCart({
status={separate(book?.product[0]?.price) + " " + "تومان"} productId: physicalProduct?.id,
onClick={() => userId: userId,
userId count: 1,
? pushToCart({ });
productId: book?.product[0]?.id, }
userId, } else {
count: 1, setDialog({
}) text: window.t(
: toast.info("ابتدا وارد حساب کاربری خود شوید.") "ابتدا میبایست وارد حساب کاربری خود شوید."
} ),
/> type: "confirm",
<a accept: () => navigation("/login"),
href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`} open: true,
className="flex-1 border-2 border-solid text-sm border-green-500 bg-green-50 bg-opacity-70 rounded-sm font-bold text-green-700 text-center" });
style={{ padding: "18px 0px" }} }
> }}
مشاهده نمونه loading={userProductLoading && whichTypeAdded === "physical"}
</a> />
</div>
<div className="w-full flex justify-between items-center mt-4"> <a
<ButtonBetween href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`}
width="72%" className="flex-1 border-2 border-solid text-sm border-green-500 bg-green-50 bg-opacity-70 rounded-sm font-bold text-green-700 text-center"
item={"خرید نسخه ویدئویی کتاب"} style={{ padding: "18px 0px" }}
status={separate(book?.product[2]?.price) + " " + "تومان"} >
onClick={() => مشاهده نمونه
userId </a>
? pushToCart({ </div>
productId: book?.product[2]?.id, ) : null}
userId, {digitalProduct && digitalAvailableForSell ? (
count: 1, <div className="w-full flex justify-between items-center mt-4 gap-2">
}) <ButtonBetween
: toast.info("ابتدا وارد حساب کاربری خود شوید.") width="72%"
} item={"خرید نسخه دیجیتال کتاب"}
/> status={separate(digitalProduct?.price) + " " + "تومان"}
<ButtonBetween onClick={() => {
width="25%" if (userId) {
item={"پیش نمایش"} if (digitalAvailabileInCart) {
onClick={() => navigation("/videos/" + book?.id)} setDialog({
/> text: window.t(
</div> "این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("digital");
pushToCart({
productId: digitalProduct?.id,
userId: userId,
count: 1,
});
}
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
}
}}
loading={userProductLoading && whichTypeAdded === "digital"}
/>
<a
href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`}
className="flex-1 border-2 border-solid text-sm border-green-500 bg-green-50 bg-opacity-70 rounded-sm font-bold text-green-700 text-center"
style={{ padding: "18px 0px" }}
>
مشاهده نمونه
</a>
</div>
) : null}
{videoProduct && videoAvailableForSell ? (
<div className="w-full flex justify-between items-center mt-4">
<ButtonBetween
width="72%"
item={"خرید نسخه ویدئویی کتاب"}
status={separate(videoProduct?.price) + " " + "تومان"}
onClick={() => {
if (userId) {
if (videoAvailabileInCart) {
setDialog({
text: window.t(
"این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("video");
pushToCart({
productId: videoProduct?.id,
userId: userId,
count: 1,
});
}
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
}
}}
loading={userProductLoading && whichTypeAdded === "video"}
/>
<ButtonBetween
width="25%"
item={"پیش نمایش"}
onClick={() => navigation("/videos/" + book?.id)}
/>
</div>
) : null}
<div className="w-full flex flex-col justify-between items-center mt-8"> <div className="w-full flex flex-col justify-between items-center mt-8">
<Header title="توضیحات" link="#" /> <Header title="توضیحات" link="#" />
<p className="text-sm text-gray70 mt-2 dark:text-white leading-6"> <p className="text-sm text-gray70 mt-2 dark:text-white leading-6">
@ -205,12 +344,16 @@ const mapStateToProps = (state) => ({
isDark: state.publicApi.isDark, isDark: state.publicApi.isDark,
userId: state.user.status?.id, userId: state.user.status?.id,
bookmarkLoading: state.userFavorite.loading, bookmarkLoading: state.userFavorite.loading,
availableForSell: state.config.availableForSell,
userProduct: state.userProduct.list,
userProductLoading: state.userProduct.loading,
}); });
const mapDispatchToProps = { const mapDispatchToProps = {
getInfo: book.info, getInfo: book.info,
pushToCart: userProduct.add, pushToCart: userProduct.add,
setHeaderOptions: publicApi.setHeaderOptions, setHeaderOptions: publicApi.setHeaderOptions,
setDialog: dialog.set,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(Product); export default connect(mapStateToProps, mapDispatchToProps)(Product);

Loading…
Cancel
Save