update 5 files

master
Reza_ashrafi 2 years ago
parent 30cc3dfa9b
commit 6bab87262e
  1. 17
      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. 203
      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,6 +21,9 @@ export const ButtonBetween = ({
onClick={() => onClick()} onClick={() => onClick()}
style={{ width, padding: "18px 8px" }} style={{ width, padding: "18px 8px" }}
> >
{loading ? (
<Loading size={2} color="bg-green-500" />
) : (
<strong <strong
className={`text-tiny ${ className={`text-tiny ${
active ? "text-green-700" : "text-gray-700" active ? "text-green-700" : "text-gray-700"
@ -24,6 +31,8 @@ export const ButtonBetween = ({
> >
{item} {item}
</strong> </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,36 +161,91 @@ 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 ? (
<div className="w-full flex justify-between items-center mt-5 gap-2">
<ButtonBetween <ButtonBetween
width="100%" width="72%"
item={"خرید نسخه فیزیکی کتاب"} item={"خرید نسخه فیزیکی کتاب"}
status={separate(book?.product[1]?.price) + " " + "تومان"} status={separate(physicalProduct?.price) + " " + "تومان"}
onClick={() => onClick={() => {
userId if (userId) {
? pushToCart({ if (physicalAvailabileInCart) {
productId: book?.product[1]?.id, setDialog({
userId, text: window.t(
"این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("physical");
pushToCart({
productId: physicalProduct?.id,
userId: userId,
count: 1, count: 1,
}) });
: toast.info("ابتدا وارد حساب کاربری خود شوید.") }
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
} }
}}
loading={userProductLoading && whichTypeAdded === "physical"}
/> />
<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> </div>
) : null}
{digitalProduct && digitalAvailableForSell ? (
<div className="w-full flex justify-between items-center mt-4 gap-2"> <div className="w-full flex justify-between items-center mt-4 gap-2">
<ButtonBetween <ButtonBetween
width="72%" width="72%"
item={"خرید نسخه دیجیتال کتاب"} item={"خرید نسخه دیجیتال کتاب"}
status={separate(book?.product[0]?.price) + " " + "تومان"} status={separate(digitalProduct?.price) + " " + "تومان"}
onClick={() => onClick={() => {
userId if (userId) {
? pushToCart({ if (digitalAvailabileInCart) {
productId: book?.product[0]?.id, setDialog({
userId, text: window.t(
"این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("digital");
pushToCart({
productId: digitalProduct?.id,
userId: userId,
count: 1, count: 1,
}) });
: toast.info("ابتدا وارد حساب کاربری خود شوید.")
} }
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
}
}}
loading={userProductLoading && whichTypeAdded === "digital"}
/> />
<a <a
href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`} href={`https://dnvn.ir/xpdf/${book?.sampleFileId}`}
@ -142,20 +255,44 @@ export const Product = ({
مشاهده نمونه مشاهده نمونه
</a> </a>
</div> </div>
) : null}
{videoProduct && videoAvailableForSell ? (
<div className="w-full flex justify-between items-center mt-4"> <div className="w-full flex justify-between items-center mt-4">
<ButtonBetween <ButtonBetween
width="72%" width="72%"
item={"خرید نسخه ویدئویی کتاب"} item={"خرید نسخه ویدئویی کتاب"}
status={separate(book?.product[2]?.price) + " " + "تومان"} status={separate(videoProduct?.price) + " " + "تومان"}
onClick={() => onClick={() => {
userId if (userId) {
? pushToCart({ if (videoAvailabileInCart) {
productId: book?.product[2]?.id, setDialog({
userId, text: window.t(
"این محصول قبلا به سبد خرید شما اضافه شده است."
),
type: "confirm",
accept: () => navigation("/cart"),
open: true,
});
} else {
setWhichTypeAdded("video");
pushToCart({
productId: videoProduct?.id,
userId: userId,
count: 1, count: 1,
}) });
: toast.info("ابتدا وارد حساب کاربری خود شوید.") }
} else {
setDialog({
text: window.t(
"ابتدا میبایست وارد حساب کاربری خود شوید."
),
type: "confirm",
accept: () => navigation("/login"),
open: true,
});
} }
}}
loading={userProductLoading && whichTypeAdded === "video"}
/> />
<ButtonBetween <ButtonBetween
width="25%" width="25%"
@ -163,6 +300,8 @@ export const Product = ({
onClick={() => navigation("/videos/" + book?.id)} onClick={() => navigation("/videos/" + book?.id)}
/> />
</div> </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