reza added cart api

master
RezaAshrafi77 3 years ago
parent 3cd90d8e03
commit 75016e9540
  1. 1
      src/App.js
  2. 7
      src/AppRouter.js
  3. 4
      src/Redux/actions/public.js
  4. 2
      src/Redux/actions/userProduct.js
  5. 6
      src/Redux/reducers/public.js
  6. 10
      src/Redux/reducers/userProduct.js
  7. 125
      src/views/Cart/Table/index.js
  8. 66
      src/views/Cart/index.js
  9. 57
      src/views/Contact/index.js
  10. 45
      src/views/Product/AddToCart/index.js
  11. 19
      src/views/Product/AddToCart/index.scss
  12. 4
      src/views/Product/Comment/index.js
  13. 153
      src/views/Product/Gallery/index.js
  14. 264
      src/views/Product/index.js
  15. 28
      src/views/Products/Product/index.js
  16. 12
      src/views/Products/Product/index.scss
  17. 6
      src/views/Products/index.js

@ -3,6 +3,7 @@ import AppRouter from "./AppRouter";
import store from "./Redux/store";
import { Provider } from "react-redux";
import "bootstrap/dist/css/bootstrap.min.css";
import "react-toastify/dist/ReactToastify.css";
class App extends Component {
render() {

@ -89,8 +89,11 @@ class AppRouter extends Component {
<Route exact path={"/products"}>
<Products />
</Route>
<Route exact path={"/products/:id"}>
<Product />
<Route exact path={"/products/digital/:id"}>
<Product page="digital" />
</Route>
<Route exact path={"/products/physical/:id"}>
<Product page="physical" />
</Route>
<Route exact path={"/qr"}>
<QR />

@ -8,6 +8,10 @@ const publicApi = {
await dispatch({ type: "public/faq/activate", data: data }),
searchFaq: (data) => async (dispatch) =>
await dispatch({ type: "public/faq/search", data: data }),
getContactData:
(data = {}, history) =>
async (dispatch) =>
await proxy.get("public/contact", data, { history, dispatch }),
};
export default publicApi;

@ -17,7 +17,7 @@ const userProduct = {
add:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.post("userProduct/add", data);
await proxy.post("userProduct/add", data, { dispatch });
await proxy.get("userProduct/list", data2, { dispatch });
},
del:

@ -1,9 +1,10 @@
const initialState = {
homeData: [],
faqList: [],
loading: false,
loading: true,
error: null,
searchResult: [],
contactData: null,
};
export default function publicApi(state = initialState, action) {
let { type, data } = action;
@ -35,10 +36,13 @@ export default function publicApi(state = initialState, action) {
item.description.indexOf(data) !== -1
),
};
case "public/contact":
return { ...state, loading: false, error: null, contactData: data };
case "loading":
return { ...state, loading: true };
case "error":
return { ...state, loading: false, error: data.message };
default:
return state;
}

@ -1,11 +1,14 @@
import { toast } from "react-toastify";
const initialState = {
loading: false,
error: null,
list: null,
info: null,
sum: null,
};
export default function userProduct(state = initialState, action) {
let { type, data } = action;
let { type, data, message } = action;
switch (type) {
case "userProduct/list":
return { ...state, loading: false, list: data, error: null };
@ -14,13 +17,16 @@ export default function userProduct(state = initialState, action) {
case "userProduct/update":
return { ...state, loading: false, error: null };
case "userProduct/add":
return { ...state, loading: false, error: null };
console.log(data);
toast.success("درخواست شما با موفقیت انجام شد.");
return { ...state, loading: false, error: null, sum: data.payPrice };
case "userProduct/delete":
return { ...state, loading: false, error: null };
/////////////
case "loading":
return { ...state, loading: true };
case "error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;

@ -1,4 +1,7 @@
import React from "react";
import { connect } from "react-redux";
import { userProduct } from "~/Redux/actions";
import { makeStyles } from "@material-ui/core/styles";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
@ -56,7 +59,7 @@ const fontSize = {
},
};
export default function BasicTable(props) {
function BasicTable(props) {
const classes = useStyles();
const { list, handleCounter, handleDelete } = props;
const sum = () => {
@ -91,7 +94,10 @@ export default function BasicTable(props) {
<Item
data={row}
key={i}
handleCounter={handleCounter}
// handleCounter={handleCounter}
pushToCart={props.pushToCart}
info={props.info}
id={props.id}
handleDelete={handleDelete}
/>
))}
@ -100,7 +106,9 @@ export default function BasicTable(props) {
<span style={{ color: "grey" }}>{sum()} محصول</span>
</TableCell>
<TableCell align="center">
<span style={{ color: "grey" }}>مبلغ کل {totalPrice()}</span>
<span style={{ color: "grey" }}>
مبلغ کل {props.payPrice}
</span>
</TableCell>
</TableRow>
</TableBody>
@ -123,7 +131,10 @@ export default function BasicTable(props) {
<Item
data={row}
key={i}
handleCounter={handleCounter}
// handleCounter={handleCounter}
pushToCart={props.pushToCart}
info={props.info}
id={props.id}
handleDelete={handleDelete}
/>
))}
@ -132,7 +143,9 @@ export default function BasicTable(props) {
<span style={{ color: "grey" }}></span>
</TableCell>
<TableCell align="center">
<span style={{ color: "grey" }}>مبلغ کل {totalPrice()}</span>
<span style={{ color: "grey" }}>
مبلغ کل {props.payPrice}
</span>
</TableCell>
<TableCell align="center" component="th" scope="row">
<span style={{ color: "grey" }}>{sum()} محصول</span>
@ -149,33 +162,31 @@ export default function BasicTable(props) {
);
}
// id: 1,
// title: "ریاضیات گسسته خیلی پیشرفته",
// subTitle: "در این قسمت توضیح بسیار کوتاهی قرار می گیرد",
// options: "بستههای الحاقی: کیف، کفش و کوله پشتی",
// image: book1,
// slicePrice: 300000,
// number: 1,
// price: 2500000,
const Item = (props) => {
const { data, handleCounter, handleDelete } = props;
const { data, pushToCart, handleDelete, info, id } = props;
return (
<>
{window.innerWidth < 1000 ? (
<TableRow key={data.name}>
<TableRow key={data.product.book.name}>
<TableCell align="right" component="th" scope="row">
<div className="mobile-cart-table-product d-flex align-items-center">
<img src={data.image} alt={data.title} />
<img
src={`https://dnvn.ir/api/v1/file/${data.product.book.fileIds}`}
alt={data.product.book.name}
/>
<div className="mobile-cart-table-product__info d-flex flex-column p-1">
<strong style={{ fontSize: fontSize.mobile.info.strong }}>
{data.title}
{`کتاب ${
data.product.productType === "1" ? "دیجیتال" : "فیزیکی"
}` +
" " +
data.product.book.name}
</strong>
<p style={{ fontSize: fontSize.mobile.info.p }}>
{data.subTitle}
{data.product.book.category}
</p>
<span style={{ fontSize: fontSize.mobile.info.span }}>
{data.options}
{data.product.book.item || "هیچی"}
</span>
<div className="mobile-cart-table-product__info--delete d-flex align-items-center align-self-end">
<DeleteOutlineOutlinedIcon
@ -199,27 +210,35 @@ const Item = (props) => {
<div className="mobile-cart-table-price d-flex flex-column align-items-center">
<div className="mobile-cart-table-price__price d-flex flex-column justify-content-center align-items-center">
<strong style={{ fontSize: fontSize.mobile.price.strong }}>
{data.price}
{data.product.book.price || "1000"}
</strong>
<span style={{ fontSize: fontSize.mobile.price.span }}>
{data.slicePrice} قیمت هر واحد
{data.product.book.subPrice || "100"} قیمت هر واحد
</span>
</div>
<div className="mobile-cart-table-price__counter d-flex justify-content-around align-items-center">
<button
onClick={() => handleCounter("increase", data.id)}
onClick={() =>
pushToCart({
productId: data.productId,
userId: id,
count: 1,
})
}
style={{ fontSize: fontSize.mobile.counter.button }}
>
+
</button>
<span style={{ fontSize: fontSize.mobile.counter.span }}>
{data.number}
{data.count}
</span>
<button
onClick={() =>
data.number > 1
? handleCounter("decrease", data.id)
: handleDelete(data.id)
pushToCart({
productId: data.productId,
userId: id,
count: -1,
})
}
style={{ fontSize: fontSize.mobile.counter.button }}
>
@ -231,19 +250,26 @@ const Item = (props) => {
</TableRow>
) : null}
{window.innerWidth > 1000 ? (
<TableRow key={data.name}>
<TableRow key={data.product.book.name}>
<TableCell align="right" component="th" scope="row">
<div className="cart-item__info d-flex">
<img src={data.image} alt={data.title} />
<img
src={`https://dnvn.ir/api/v1/file/${data.product.book.fileIds}`}
alt={data.product.book.name}
/>
<div className="d-flex flex-column justify-content-center">
<strong style={{ fontSize: fontSize.desktop.info.strong }}>
{data.title}
{`کتاب ${
data.product.productType === "1" ? "دیجیتال" : "فیزیکی"
}` +
" " +
data.product.book.name}
</strong>
<p style={{ fontSize: fontSize.desktop.info.p }}>
{data.subTitle}
{data.product.book.category}
</p>
<span style={{ fontSize: fontSize.desktop.info.span }}>
{data.options}بسته الحاقی:
{data.product.book.items || "چیزی وارد نشده"}بسته الحاقی:
</span>
</div>
</div>
@ -251,10 +277,10 @@ const Item = (props) => {
<TableCell>
<div className="cart-item__price d-flex flex-column justify-content-center align-items-center">
<strong style={{ fontSize: fontSize.desktop.price.strong }}>
{data.price} تومان
{data.product.book.price || "1000"} تومان
</strong>
<span style={{ fontSize: fontSize.desktop.price.span }}>
{data.slicePrice} قیمت هر واحد
{data.product.book.subPrice || "100"} قیمت هر واحد
</span>
</div>
</TableCell>
@ -262,19 +288,27 @@ const Item = (props) => {
<div className="cart-item__counter d-flex align-items-center">
<div className="cart-item__counter--box d-flex justify-content-around align-items-center">
<button
onClick={() => handleCounter("increase", data.id)}
onClick={() =>
pushToCart({
productId: data.productId,
userId: id,
count: 1,
})
}
style={{ fontSize: fontSize.desktop.counter.button }}
>
+
</button>
<span style={{ fontSize: fontSize.desktop.counter.span }}>
{data.number}
{data.count}
</span>
<button
onClick={() =>
data.number > 1
? handleCounter("decrease", data.id)
: handleDelete(data.id)
pushToCart({
productId: data.productId,
userId: id,
count: -1,
})
}
style={{ fontSize: fontSize.desktop.counter.button }}
>
@ -287,10 +321,10 @@ const Item = (props) => {
<div className="cart-item__delete d-flex align-items-center justify-content-center">
<DeleteOutlineOutlinedIcon
style={{ color: "#FC120A", fontSize: 30, marginLeft: 5 }}
onClick={() => handleDelete(data.id)}
// onClick={() => handleDelete(data.id)}
/>
<span
onClick={() => handleDelete(data.id)}
// onClick={() => handleDelete(data.id)}
style={{ fontSize: fontSize.desktop.delete.span }}
>
حذف
@ -302,3 +336,12 @@ const Item = (props) => {
</>
);
};
export default connect(
(state) => ({
loading: state.userProduct.loading,
info: state.book.info,
id: state.user.status.id,
}),
{ pushToCart: userProduct.add }
)(BasicTable);

@ -1,10 +1,15 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { userProduct } from "~/Redux/actions";
import { ToastContainer } from "react-toastify";
import Navbar from "../Home/Navbar/index";
import Footer from "../Home/Footer/index";
import Table from "./Table/index";
import DiscoutCode from "./Discount/index";
import DeliveryMethod from "./DeliveryMethod/index";
import Factor from "./Factor/index";
import Loader from "~/components/Loader/index";
import sciense_6 from "../../assets/images/sciense-6.png";
@ -33,7 +38,7 @@ const fontSize = {
input: window.innerWidth > maxMobileSize ? 16 : window.innerWidth / 20,
},
};
export default class Cart extends Component {
class Cart extends Component {
state = {
selectedDelivery: { name: "", price: 0 },
discount: 0,
@ -72,6 +77,10 @@ export default class Cart extends Component {
],
};
componentDidMount() {
this.props.getList();
}
handleCounter = (type, id) => {
if (type === "increase") {
this.setState((prevState) => ({
@ -104,9 +113,11 @@ export default class Cart extends Component {
};
render() {
const { list, payPrice } = this.props;
return (
<>
{window.innerWidth > 1000 ? (
list ? (
<>
<div className="cart d-flex flex-column">
<Navbar />
@ -116,21 +127,16 @@ export default class Cart extends Component {
>
<section className="cart__right d-flex flex-column">
<header>
<h1 style={{ fontSize: fontSize.desktop.h1 }}>سبد خرید</h1>
<h1 style={{ fontSize: fontSize.desktop.h1 }}>
سبد خرید
</h1>
</header>
<Table
list={this.state.list}
list={list}
handleCounter={this.handleCounter}
handleDelete={this.handleDelete}
payPrice={payPrice}
/>
{this.state.totalPrice ? (
<div className="cart__right--price d-flex justify-content-end">
<div className="d-flex ml-2">جمع کل سبد خرید</div>
<div className="d-flex">
<strong>{this.state.totalPrice} تومان </strong>
</div>
</div>
) : null}
</section>
<section className="cart__left d-flex flex-column p-3">
<header className="cart__left--header d-flex flex-column">
@ -153,7 +159,7 @@ export default class Cart extends Component {
</h3>
<div className="d-flex align-items-center">
<strong style={{ fontSize: fontSize.mobile.h1 }}>
{this.totalPrice()}
{payPrice}
</strong>
<span style={{ fontSize: fontSize.mobile.h3 }}>
تومان
@ -179,8 +185,17 @@ export default class Cart extends Component {
</div>
<Footer />
</>
) : (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "100vh", width: "100vw" }}
>
<Loader />
</div>
)
) : null}
{window.innerWidth < 1000 ? (
list ? (
<div className="mobile-cart d-flex flex-column">
<Navbar />
<h1 style={{ fontSize: fontSize.mobile.h1 }}>سبد خرید</h1>
@ -232,12 +247,39 @@ export default class Cart extends Component {
</div>
<button className="mobile-cart__submit">پرداخت</button>
</div>
) : (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "100vh", width: "100vw" }}
>
<Loader />
</div>
)
) : null}
<ToastContainer
position="bottom-right"
autoClose={1500}
hideProgressBar={true}
newestOnTop={true}
closeOnClick
rtl={true}
pauseOnFocusLoss
draggable
pauseOnHover
/>
</>
);
}
}
export default connect(
(state) => ({
list: state.userProduct.list,
payPrice: state.userProduct.sum,
}),
{ getList: userProduct.list }
)(Cart);
Cart.defaultProps = {
payMethods: [
{

@ -1,4 +1,7 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { publicApi } from "~/Redux/actions";
import Navbar from "../Home/Navbar/index";
import Footer from "../Home/Footer/index";
import Input from "./Input/index";
@ -7,6 +10,7 @@ import location from "../../assets/icons/location.png";
import home from "../../assets/icons/home.png";
import contact from "../../assets/icons/contact.png";
import Location from "./Location/Location";
import Loader from "~/components/Loader/index";
import "./index.scss";
@ -25,20 +29,30 @@ const fontSize = {
span: window.innerWidth > maxMobileSize ? 15 : window.innerWidth / 32,
},
};
export default class Contact extends Component {
class Contact extends Component {
componentDidMount() {
this.props.getContactData();
}
render() {
const { loading, contactData } = this.props;
return (
<>
{window.innerWidth > 1000 ? (
!loading ? (
<>
<div className="contact d-flex flex-column align-items-center">
<Navbar page={"contact"} />
<div className="contact__forms d-flex">
<div className="contact__forms--right d-flex flex-column">
<h1 style={{ fontSize: fontSize.desktop.h1 }}>تماس با ما</h1>
<h1 style={{ fontSize: fontSize.desktop.h1 }}>
تماس با ما
</h1>
<p style={{ fontSize: fontSize.desktop.p }}>
برای ارتباط با دنیای شگفت انگیز دانوین از فرم زیر استفاده
کنید و پس از انتخاب دپارتمان مد نظر پیام خود را ارسال کنید.
کنید و پس از انتخاب دپارتمان مد نظر پیام خود را ارسال
کنید.
</p>
<Input label={"نامونام خانوادگی"} name={"name"} />
<Input label={"شماره تماس"} name={"mobile"} />
@ -55,7 +69,7 @@ export default class Contact extends Component {
<div className="contact__location d-flex align-items-center">
<img src={location} alt="آدرس" className="m-1" />
<p style={{ fontSize: fontSize.desktop.p }}>
تهران خیابان انقلاب اسلامی بن بست سروش پلاک 2 طبقه چهار
{contactData.address}
</p>
</div>
<div
@ -64,13 +78,13 @@ export default class Contact extends Component {
>
<div className="d-flex align-items-center">
<span style={{ fontSize: fontSize.desktop.span }}>
02163462405
{contactData.cellphone}
</span>
<img src={contact} alt="تماس" className="m-1" />
</div>
<div className="d-flex align-items-center">
<span style={{ fontSize: fontSize.desktop.span }}>
Info@Danovin.ir
{contactData.email}
</span>
<img src={home} alt="خانه" className="m-1" />
</div>
@ -83,15 +97,24 @@ export default class Contact extends Component {
</div>
<Footer />
</>
) : (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "100vh", width: "100vw" }}
>
<Loader />
</div>
)
) : null}
{window.innerWidth < 1000 ? (
!loading ? (
<div className="mobile-contact d-flex flex-column align-items-center">
<Navbar page={"contact"} />
<div className="mobile-contact__form d-flex flex-column">
<h1 style={{ fontSize: fontSize.mobile.h1 }}>تماس با ما</h1>
<p style={{ fontSize: fontSize.mobile.p }}>
برای ارتباط با دنیای شگفت انگیز دانوین از فرم زیر استفاده کنید و
پس از انتخاب دپارتمان مد نظر پیام خود را ارسال کنید.
برای ارتباط با دنیای شگفت انگیز دانوین از فرم زیر استفاده کنید
و پس از انتخاب دپارتمان مد نظر پیام خود را ارسال کنید.
</p>
<Input label={"نامونام خانوادگی"} name={"name"} />
<Input label={"شماره تماس"} name={"mobile"} />
@ -129,12 +152,28 @@ export default class Contact extends Component {
</div>
</div>
<div className="mobile-contact__address--map d-flex align-items-center mt-3">
{/* <Location /> */}
<Location />
</div>
</div>
</div>
) : (
<div
className="d-flex justify-content-center align-items-center"
style={{ height: "100vh", width: "100vw" }}
>
<Loader />
</div>
)
) : null}
</>
);
}
}
export default connect(
(state) => ({
loading: state.publicApi.loading,
contactData: state.publicApi.contactData,
}),
{ getContactData: publicApi.getContactData }
)(Contact);

@ -1,4 +1,9 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { userProduct } from "~/Redux/actions";
import { Link } from "react-router-dom";
import Loader from "~/components/Loader/index";
import "./index.scss";
import document_red from "~/assets/icons/document-red.png";
@ -18,8 +23,8 @@ const fontSize = {
},
};
export default function AddToCart(props) {
const { price, off, supportItems } = props;
function AddToCart(props) {
const { price, off, supportItems, page, loading, info } = props;
return (
<>
{window.innerWidth > 1000 ? (
@ -43,16 +48,37 @@ export default function AddToCart(props) {
مشاهده نمونه کتاب
<img src={document_red} />
</button>
<button
<Link
to={`/products/${
page === "digital"
? `physical/${window.location.pathname.slice(
window.location.pathname.lastIndexOf("/") + 1,
window.location.pathname.length
)}`
: `digital/${window.location.pathname.slice(
window.location.pathname.lastIndexOf("/") + 1,
window.location.pathname.length
)}`
}`}
style={{ fontSize: fontSize.desktop.button }}
className="product-addtocart__box--digitalButton"
>
خرید نسخه دیجیتال
{page === "digital" ? "کتاب فیزیکی" : "نسخه دیجیتال"}
<img src={ebook_blue} />
</button>
</Link>
<button
style={{ fontSize: fontSize.desktop.button }}
className="product-addtocart__box--addButton"
onClick={() =>
props.pushToCart({
productId:
page === "digital"
? info.product[0].id
: info.product[1].id,
userId: props.id,
count: 1,
})
}
>
افزودن به سبد خرید
<img src={basket_white} />
@ -79,3 +105,12 @@ export default function AddToCart(props) {
</>
);
}
export default connect(
(state) => ({
loading: state.userProduct.loading,
info: state.book.info,
id: state.user.status.id,
}),
{ pushToCart: userProduct.add }
)(AddToCart);

@ -26,6 +26,22 @@
}
}
}
a {
font-family: numeralLight;
border-radius: 7px;
margin-bottom: 10px;
padding: 10px;
position: relative;
letter-spacing: -1px;
text-decoration: none;
text-align: center;
img {
position: absolute;
left: 13px;
top: 13px;
transform: scale(0.9);
}
}
button {
font-family: numeralLight;
border-radius: 7px;
@ -39,6 +55,9 @@
top: 13px;
transform: scale(0.9);
}
&:focus {
outline: none;
}
}
&--sampleButton {
color: #ff1616;

@ -26,7 +26,7 @@ export default function Comment(props) {
{window.innerWidth < 1000 ? (
<div className="mobile-comment d-flex flex-column">
<strong style={{ fontSize: fontSize.mobile.strong }}>
{comment.username}
{comment.username || "حسین"}
</strong>
<p style={{ fontSize: fontSize.mobile.p }}>{comment.text}</p>
<span style={{ fontSize: fontSize.mobile.span }}>
@ -40,7 +40,7 @@ export default function Comment(props) {
className="comment__user"
style={{ fontSize: fontSize.desktop.strong }}
>
{comment.username}
{comment.username || "حسین"}
</strong>
<p className="comment__text" style={{ fontSize: fontSize.desktop.p }}>
{comment.text}

@ -1,87 +1,112 @@
import React, { Component, useState } from 'react';
import MoreHorizIcon from '@material-ui/icons/MoreHoriz';
import Video from '../../QR/VideoBox/React-video-js-player/index';
import Modal from './Modal/index';
import React, { Component, useState } from "react";
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
import Video from "../../QR/VideoBox/React-video-js-player/index";
import Modal from "./Modal/index";
import './index.scss';
import "./index.scss";
export default function Gallery(props) {
const [selectedMedia,setSelectedMedia] = useState(props.gallery[1]);
const [selectedMedia, setSelectedMedia] = useState(props.gallery[0]);
const [modal, setModal] = useState(null);
return(
return (
<>
{
window.innerWidth > 1000 ?
{window.innerWidth > 1000 ? (
<section className="product-gallery d-flex flex-column">
<div className="product-gallery__top">
{
selectedMedia ?
{selectedMedia ? (
<>
{
selectedMedia.type === 'image' ?
<img src={selectedMedia.value} alt={'عکس'} /> : null
}
{
selectedMedia.type === 'film' ?
<Video /> : null
}
</> : null
}
{selectedMedia.type === "image" ? (
<img
src={`https://dnvn.ir/api/v1/file/${selectedMedia.id}`}
alt={"عکس"}
/>
) : null}
{selectedMedia.type === "film" ? <Video /> : null}
</>
) : null}
</div>
<div className="product-gallery__list d-flex">
{
props.gallery.length > 3 ?
{props.gallery.length > 3 ? (
<>
<Item active={selectedMedia === props.gallery[0]} item={props.gallery[0]} key={props.gallery[0].id} more={false} setSelectedMedia={setSelectedMedia} setModal={setModal} />
<Item active={selectedMedia === props.gallery[1]} item={props.gallery[1]} key={props.gallery[1].id} more={false} setSelectedMedia={setSelectedMedia} setModal={setModal} />
<Item active={selectedMedia === props.gallery[2]} item={props.gallery[2]} key={props.gallery[2].id} more={true} setSelectedMedia={setSelectedMedia} setModal={setModal} />
</> :
<Item
active={selectedMedia === props.gallery[0]}
item={props.gallery[0]}
key={props.gallery[0].id}
more={false}
setSelectedMedia={setSelectedMedia}
setModal={setModal}
/>
<Item
active={selectedMedia === props.gallery[1]}
item={props.gallery[1]}
key={props.gallery[1].id}
more={false}
setSelectedMedia={setSelectedMedia}
setModal={setModal}
/>
<Item
active={selectedMedia === props.gallery[2]}
item={props.gallery[2]}
key={props.gallery[2].id}
more={true}
setSelectedMedia={setSelectedMedia}
setModal={setModal}
/>
</>
) : (
<>
{
props.gallery.map((item, i) => (
<Item active={selectedMedia === item} item={item} key={item.id} more={false} setSelectedMedia={setSelectedMedia} setModal={setModal} />
))
}
{props.gallery.map((item, i) => (
<Item
active={selectedMedia === item}
item={item}
key={item.id}
more={false}
setSelectedMedia={setSelectedMedia}
setModal={setModal}
/>
))}
</>
}
)}
</div>
{
modal ?
<Modal first={modal} gallery={props.gallery} setModal={setModal} /> : null
}
</section> : null
}
{modal ? (
<Modal first={modal} gallery={props.gallery} setModal={setModal} />
) : null}
</section>
) : null}
</>
);
}
const Item = (props) => {
const {item, more, setSelectedMedia, setModal, active} = props;
return(
const { item, more, setSelectedMedia, setModal, active } = props;
return (
<>
{
window.innerWidth > 1000 ?
<div style={{ border: active ? '4px solid #1BBC6E' : ''}} className="product-gallery-item d-flex">
{
item.type === 'image' ?
<img src={item.value} alt={'عکس'} /> : null
}
{
item.type === 'film' ?
<Video /> : null
}
{
!more ?
<div className="product-gallery-item__cover" onClick={() => setSelectedMedia(item)}>
</div> :
<div className="product-gallery-item__cover product-gallery-item__more d-flex justify-content-center align-items-center" onClick={() => setModal(item)}>
<MoreHorizIcon style={{ fontSize: 60, color: 'white'}} />
{window.innerWidth > 1000 ? (
<div
style={{ border: active ? "4px solid #1BBC6E" : "" }}
className="product-gallery-item d-flex"
>
{item.type === "image" ? (
<img src={`https://dnvn.ir/api/v1/file/${item.id}`} alt={"عکس"} />
) : null}
{item.type === "film" ? (
<Video fileId={`https://dnvn.ir/api/v1/file/${item.id}`} />
) : null}
{!more ? (
<div
className="product-gallery-item__cover"
onClick={() => setSelectedMedia(item)}
></div>
) : (
<div
className="product-gallery-item__cover product-gallery-item__more d-flex justify-content-center align-items-center"
onClick={() => setModal(item)}
>
<MoreHorizIcon style={{ fontSize: 60, color: "white" }} />
</div>
}
</div> : null
}
)}
</div>
) : null}
</>
);
}
};

@ -1,4 +1,6 @@
import React, { Component } from "react";
import { ToastContainer } from "react-toastify";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { book } from "~/Redux/actions";
@ -14,12 +16,6 @@ import HomeScroll from "../Home/HomeScroll/index";
import HomeSlider from "../Home/HomeSlider/index";
import Loader from "~/components/Loader/index";
import sciense_7 from "~/assets/images/sciense-7.png";
import sciense_6 from "~/assets/images/sciense-6.png";
import sciense_8 from "~/assets/images/sciense-8.png";
import sciense_9 from "~/assets/images/sciense-9.png";
import zist_10 from "~/assets/images/zist-10.png";
import film from "~/assets/Video/film.mp4";
import product_shipping from "~/assets/icons/product-shipping.png";
import product_cash_back from "~/assets/icons/product-cash-back.png";
import product_support from "~/assets/icons/product-support.png";
@ -51,29 +47,40 @@ class Product extends Component {
window.location.pathname.length
),
});
this.props.getList();
}
render() {
const { product, sameProducts, supportItems, info } = this.props;
const { product, sameProducts, supportItems, info, page, loading, list } =
this.props;
return (
<>
{window.innerWidth > 1000 ? (
this.props.info ? (
info ? (
<>
<div className="product d-flex flex-column">
<Navbar />
<Breadcrumbs />
<header className="product__header d-flex mt-4">
<Gallery gallery={product.gallery} />
<Gallery gallery={info.files} />
<Info
subTitle={product.subTitle}
title={product.title}
description={product.description}
subTitle={info.category}
title={
page === "digital"
? info.product[0].name
: info.product[1].name
}
description={info.description || "توضیحات محصول خالیست"}
/>
<AddToCart
supportItems={supportItems}
price={product.price}
off={product.off}
price={
page === "digital"
? info.product[0].price
: info.product[1].price
}
// off={product.off}
page={page}
/>
</header>
<div className="product__comments d-flex flex-column">
@ -88,10 +95,12 @@ class Product extends Component {
</div>
<div className="product__comments--list d-flex flex-column">
<Comment comment={product.comments[0]} />
{info.comment.length > 0 ? (
<Comment comment={info.comment[0]} />
) : null}
</div>
</div>
<Identifier item={sameProducts} />
{0 ? <Identifier item={[]} /> : null}
</div>
<Footer />
</>
@ -105,7 +114,7 @@ class Product extends Component {
)
) : null}
{window.innerWidth < 1000 ? (
this.props.info ? (
info ? (
<>
<div className="mobile-product d-flex flex-column">
<Navbar />
@ -200,6 +209,17 @@ class Product extends Component {
</div>
)
) : null}
<ToastContainer
position="bottom-right"
autoClose={1500}
hideProgressBar={true}
newestOnTop={true}
closeOnClick
rtl={true}
pauseOnFocusLoss
draggable
pauseOnHover
/>
</>
);
}
@ -209,8 +229,10 @@ export default connect(
(state) => ({
info: state.book.info,
// status: state.user.status,
loading: state.book.loading,
list: state.book.list,
}),
{ getInfo: book.info }
{ getInfo: book.info, getList: book.list }
)(Product);
Product.defaultProps = {
@ -219,175 +241,6 @@ Product.defaultProps = {
{ title: "پشتیبانی 24 ساعته ", icon: product_support },
{ title: "ضمانت بازگشت ", icon: product_cash_back },
],
sameProducts: {
type: window.innerWidth > 1000 ? "slider" : "scroll",
title: "محصولات مرتبط",
moreText: "لیست کتابها",
height: window.innerWidth > 1000 ? 470 : 320,
design: window.innerWidth > 1000 ? "simple" : "product",
number: window.innerWidth > 1000 ? 4 : 2.8,
data: [
{
id: 0,
image: sciense_6,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه دهم ابتدایی",
price: "78.000",
oldPrice: "",
date: new Date(),
},
{
id: 1,
image: sciense_7,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه ششم ابتدایی",
price: "39.000",
oldPrice: "59.000",
date: new Date(),
},
{
id: 2,
image: sciense_8,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه ششم ابتدایی",
price: "21.000",
oldPrice: "",
},
{
id: 3,
image: sciense_9,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه دهم ابتدایی",
price: "",
oldPrice: "",
},
{
id: 4,
image: zist_10,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه هفتم ابتدایی",
price: "59.000",
oldPrice: "",
},
{
id: 5,
image: sciense_6,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه دهم ابتدایی",
price: "78.000",
oldPrice: "",
date: new Date(),
},
{
id: 6,
image: sciense_7,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه ششم ابتدایی",
price: "39.000",
oldPrice: "59.000",
date: new Date(),
},
{
id: 7,
image: sciense_8,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه ششم ابتدایی",
price: "21.000",
oldPrice: "",
date: new Date(),
},
{
id: 8,
image: sciense_9,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه دهم ابتدایی",
price: "",
oldPrice: "",
date: new Date(),
},
{
id: 9,
image: zist_10,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه هفتم ابتدایی",
price: "59.000",
oldPrice: "",
date: new Date(),
},
],
},
product: {
id: 1,
image: sciense_7,
title: "منفجر کردن مغز خود را به ما بسپارید",
subTitle: "پایه ششم ابتدایی",
price: "39.000",
off: "30%",
oldPrice: "59.000",
date: new Date(),
abstraction:
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشت",
modules: [
"پک هدیه شامل یک عدد جلد سخت",
"عینک واقعیت مجازی",
"کارت گرافیک مناسب جهت اجرای بازی",
],
tips: [
"پک هدیه شامل یک عدد جلد سخت",
"عینک واقعیت مجازی",
"کارت گرافیک مناسب جهت اجرای بازی",
],
gallery: [
{ id: 0, value: film, type: "film" },
{ id: 1, value: sciense_6, type: "image" },
{ id: 2, value: sciense_7, type: "image" },
{ value: sciense_8, type: "image" },
],
description:
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشت",
comments: [
{
id: 0,
username: "محمدرضا",
date: new Date(),
text: "عالی بود. ممنون از سایت زیباتون",
score: 4,
reply: "ممنون از شما که به ما اعتماد کردید",
},
{
id: 1,
username: "محمدرضا",
date: new Date(),
text: "عالی بود. ممنون از سایت زیباتون",
score: 2.5,
reply: "",
},
{
id: 2,
username: "محمدرضا",
date: new Date(),
text: "عالی بود. ممنون از سایت زیباتون",
score: 5,
reply: "",
},
{
id: 3,
username: "محمدرضا",
date: new Date(),
text: "عالی بود. ممنون از سایت زیباتون",
score: 3.7,
reply: "",
},
{
id: 4,
username: "محمدرضا",
date: new Date(),
text: "عالی بود. ممنون از سایت زیباتون",
score: 2,
reply: "",
},
],
},
};
const Item = (props) => {
@ -397,25 +250,36 @@ const Item = (props) => {
const Identifier = (props) => {
return (
<>
{props.item.type === "scroll" ? (
{window.innerWidth < 1000 ? (
<HomeScroll
number={props.item.number}
height={props.item.height}
title={props.item.title}
data={props.item.data}
designType={props.item.design}
moreText={props.item.moreText}
number={2.5}
// height={props.item.height}
title={"محصولات مشابه"}
data={props.item}
designType={"product"}
moreText={"ّبیشتر"}
/>
) : null}
{props.item.type === "slider" ? (
{window.innerWidth > 1000 ? (
<HomeSlider
designType={props.item.design}
number={props.item.number}
height={props.item.height}
title={props.item.title}
data={props.item.data}
designType={"simple"}
number={"4"}
// height={props.item.height}
title={"محصولات مشابه"}
data={props.item}
/>
) : null}
<ToastContainer
position="bottom-right"
autoClose={1500}
hideProgressBar={true}
newestOnTop={true}
closeOnClick
rtl={true}
pauseOnFocusLoss
draggable
pauseOnHover
/>
</>
);
};

@ -37,11 +37,21 @@ export default class Product extends Component {
</div>
<div className="mobile-products-product__links d-flex mt-2">
<Link
to={`/products/${product.id}`}
to={`/products/physical/${product.id}`}
style={{ fontSize: fontSize.mobile.a }}
className="mobile-products-product__links--physical"
>
اطلاعات بیشتر
کتاب
{/* {!product.status.digital ? (
<img src={basket} alt="افزودن به سبد خرید" />
) : null} */}
</Link>
<Link
to={`/products/digital/${product.id}`}
style={{ fontSize: fontSize.mobile.a }}
className="mobile-products-product__links--ar"
>
نسخه دیجیتال
{/* {!product.status.digital ? (
<img src={basket} alt="افزودن به سبد خرید" />
) : null} */}
@ -51,22 +61,30 @@ export default class Product extends Component {
) : null}
{window.innerWidth > 1000 ? (
<article className="products-product d-flex flex-column align-items-center">
<Link to={`/products/${product.id}`}>
<img
src={`https://dnvn.ir/api/v1/file/${product.fileIds}`}
alt={product.name}
/>
<h1 style={{ fontSize: fontSize.desktop.h1 }}>{product.name}</h1>
<Link
to={`/products/${product.id}`}
to={`/products/physical/${product.id}`}
style={{ fontSize: fontSize.mobile.a }}
className="products-product--physical"
>
اطلاعات بیشتر
کتاب
{/* {!product.status.digital ? (
<img src={basket} alt="افزودن به سبد خرید" />
) : null} */}
</Link>
<Link
to={`/products/digital/${product.id}`}
style={{ fontSize: fontSize.mobile.a }}
className="products-product--ar"
>
نسخه دیجیتال
{/* {!product.status.digital ? (
<img src={basket} alt="افزودن به سبد خرید" />
) : null} */}
</Link>
</article>
) : null}

@ -3,9 +3,7 @@
padding: 10px;
margin-bottom: 20px;
text-align: center;
a {
width: 100%;
text-decoration: none;
&:hover {
}
img {
@ -21,7 +19,6 @@
text-align: center;
margin-bottom: 15px;
}
}
&--physical {
background-color: #7fc75d;
color: white;
@ -30,6 +27,13 @@
font-family: numeralMedium;
text-decoration: none;
}
&--ar {
border: 1px solid #7fc75d;
padding: 5px 3px;
border-radius: 7px;
color: #7fc75d;
margin-top: 10px;
}
}
@media screen and (max-width: 350px) {

@ -58,11 +58,11 @@ class Products extends Component {
render() {
const { dateFilters, degreeFilters, firstFilters } = this.state;
const { loading, list } = this.props;
const { loading, list, page } = this.props;
return (
<>
{window.innerWidth > 1000 ? (
!loading ? (
list ? (
<>
<div className="products d-flex flex-column">
<Navbar page={"products"} />
@ -90,7 +90,7 @@ class Products extends Component {
)
) : null}
{window.innerWidth < 1000 ? (
!loading ? (
list ? (
<>
<div className="mobile-products d-flex flex-column">
<Navbar page={"products"} />

Loading…
Cancel
Save