reza added Product

temp
Reza_ashrafi 3 years ago
parent afbf0cb2b4
commit 8a98e53e4d
  1. 1
      package.json
  2. BIN
      src/assets/images/user.png
  3. 22
      src/components/Button/index.js
  4. 32
      src/components/Header/index.js
  5. 2
      src/components/Progress/index.js
  6. 16
      src/components/StarRating/index.js
  7. 12
      src/components/index.js
  8. 5
      src/redux/actions/book.js
  9. 2
      src/redux/reducers/book.js
  10. 2
      src/redux/reducers/public.js
  11. 4
      src/router.js
  12. 15
      src/views/Home/Portrait/Private/Shop/index.js
  13. 26
      src/views/Product/Comment/index.js
  14. 55
      src/views/Product/Rate/index.js
  15. 138
      src/views/Product/index.js
  16. 2
      src/views/Products/index.js
  17. 15
      yarn.lock

@ -17,6 +17,7 @@
"react-redux": "^7.2.6", "react-redux": "^7.2.6",
"react-router-dom": "^6.0.2", "react-router-dom": "^6.0.2",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"react-star-rating-component": "^1.4.1",
"react-toastify": "^8.1.0", "react-toastify": "^8.1.0",
"react-wavesurfer": "^0.8.6", "react-wavesurfer": "^0.8.6",
"redux": "^4.1.2", "redux": "^4.1.2",

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@ -0,0 +1,22 @@
import React from "react";
export default function Button({
title,
backgroundColor,
color,
border,
width,
bgOpacity,
}) {
return (
<button
className={`rounded-md py-3 justify-center text-xs ${backgroundColor} ${color} ${bgOpacity}`}
style={{
border: `${border.width} solid ${border.color}`,
width: width,
}}
>
{title}
</button>
);
}

@ -0,0 +1,32 @@
import React from "react";
import { Link } from "react-router-dom";
import {connect} from 'react-redux';
import arrowBlueIcon from "../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../assets/icons/arrow-left-white.svg";
function Header({ title, link, isDark }) {
return (
<header className="w-full flex flex-row justify-between items-center pl-0">
<strong className="text-blueC0 dark:text-white font-semibold text-sm">
{title}
</strong>
<Link to={link}>
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt=""
className={`transform ${isDark ? "w-5" : "w-5 rotate-180"}`}
/>
</Link>
</header>
);
}
const mapStateToProps = (state) => ({
isDark: state.publicApi.isDark
})
const mapDispatchToProps = {
}
export default connect(mapStateToProps, mapDispatchToProps)(Header);

@ -8,7 +8,7 @@ function Progress({ percent }) {
}, 1000); }, 1000);
}, [percent]); }, [percent]);
return ( return (
<div className="w-full h-1.5 rounded-full overflow-hidden my-3" style={{ backgroundColor: '#D3E9FF' }}> <div className="flex-1 h-1.5 rounded-full overflow-hidden my-3" style={{ backgroundColor: '#D3E9FF' }}>
<div <div
className="h-full bg-blueEB transition-all duration-500" className="h-full bg-blueEB transition-all duration-500"
style={{ width: delayPercent + "%" }} style={{ width: delayPercent + "%" }}

@ -0,0 +1,16 @@
import React, { useState } from "react";
import StarRatingComponent from "react-star-rating-component";
function StarRating() {
const [rate, setRating] = useState(2);
return (
<StarRatingComponent
name="rate1"
starCount={5}
value={rate}
onStarHover={(value) => setRating(value)}
/>
);
}
export default StarRating;

@ -0,0 +1,12 @@
export {default as BG} from './BG';
export {default as Button} from './Button';
export {default as Dots} from './Dots';
export {default as FloatWithMouse} from './FloatWidthMouse';
export {default as JolPlayer} from './JolPlayer';
export {default as Navbar} from './Navbar';
export {default as Progress} from './Progress';
export {default as Search} from './Search';
export {default as Select} from './Select';
// export {default as Wave} from './Wave';

@ -4,12 +4,17 @@ const book = {
(data = {}) => (data = {}) =>
async (dispatch) => async (dispatch) =>
await proxy.get("book/list", data, { dispatch }), await proxy.get("book/list", data, { dispatch }),
info:
(data = {}) =>
async (dispatch) =>
await proxy.get("book/info", data, { dispatch }),
setLessonActive: (data) => async (dispatch) => setLessonActive: (data) => async (dispatch) =>
await dispatch({ type: "book/lesson/active", data: data }), await dispatch({ type: "book/lesson/active", data: data }),
gradeFilter: (data) => async (dispatch) => gradeFilter: (data) => async (dispatch) =>
await dispatch({ type: "book/gradeFilter", data: data }), await dispatch({ type: "book/gradeFilter", data: data }),
sortFilter: (data) => async (dispatch) => sortFilter: (data) => async (dispatch) =>
await dispatch({ type: "book/sortFilter", data: data }), await dispatch({ type: "book/sortFilter", data: data }),
// update: // update:
// (data = {}, data2 = {}) => // (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => { // async (dispatch : Dispatch) => {

@ -59,6 +59,8 @@ export default function book(state = initialState, action) {
filterResult: data, filterResult: data,
error: null, error: null,
}; };
case "book/info":
return { ...state, loading: false, info: data, error: null };
case "book/lesson/active": case "book/lesson/active":
return { return {
...state, ...state,

@ -1,7 +1,7 @@
import location from "../../utils/location"; import location from "../../utils/location";
const initialState = { const initialState = {
isDark: localStorage.getItem("isDark") || false, isDark: localStorage.getItem("isDark") || true,
homeData: [], homeData: [],
newProducts: [], newProducts: [],
levels: [], levels: [],

@ -7,6 +7,7 @@ import BG from "./components/BG";
import _ from "lodash"; import _ from "lodash";
import Home from "./views/Home"; import Home from "./views/Home";
import Products from "./views/Products"; import Products from "./views/Products";
import Product from "./views/Product";
// import VideoTube from "./views/Home/VideoTube"; // import VideoTube from "./views/Home/VideoTube";
function Router({ isDark }) { function Router({ isDark }) {
@ -15,7 +16,7 @@ function Router({ isDark }) {
<div <div
className={_.join( className={_.join(
[ [
"min-h-screen min-w-screen rtl overflow-x-hidden pt-20 lg:pt-0", "min-h-screen min-w-screen rtl overflow-x-hidden py-20 lg:py-0",
isDark ? "" : "bg-white", isDark ? "" : "bg-white",
], ],
" " " "
@ -27,6 +28,7 @@ function Router({ isDark }) {
<Routes> <Routes>
<Route path="/" exact element={<Home />} /> <Route path="/" exact element={<Home />} />
<Route path="/products" exact element={<Products />} /> <Route path="/products" exact element={<Products />} />
<Route path="/products/:id" exact element={<Product />} />
<Route <Route
path="*" path="*"
element={ element={

@ -2,6 +2,8 @@ import React, { useEffect } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { book } from "../../../../../redux/actions"; import { book } from "../../../../../redux/actions";
import Header from '../../../../../components/Header'
// assets
import arrowBlueIcon from "../../../../../assets/icons/arrow-right-blue.svg"; import arrowBlueIcon from "../../../../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../../../../assets/icons/arrow-left-white.svg"; import arrowWhiteIcon from "../../../../../assets/icons/arrow-left-white.svg";
@ -12,16 +14,7 @@ function Shop({ list, getList, grades, isDark }) {
return ( return (
<div className="w-full pr-4"> <div className="w-full pr-4">
<div className="w-full flex flex-col rounded-md py-4 overflow-hidden"> <div className="w-full flex flex-col rounded-md py-4 overflow-hidden">
<header className="w-full flex flex-row justify-between items-center pl-4"> <Header title="فروشگاه" link="/products" />
<strong className="text-blueC0 dark:text-white font-bold text-lg">
فروشگاه
</strong>
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt=""
className={`transform ${isDark ? 'w-7' : 'rotate-180'}`}
/>
</header>
<ul <ul
className="list-none w-full overflow-x-scroll pt-3 flex flex-col flex-wrap" className="list-none w-full overflow-x-scroll pt-3 flex flex-col flex-wrap"
style={{ style={{
@ -45,7 +38,7 @@ function Shop({ list, getList, grades, isDark }) {
const Book = ({ book, index }) => { const Book = ({ book, index }) => {
return ( return (
<li className="flex flex-col ml-2"> <li className="flex flex-col ml-2">
<Link to={"/products/" + book.name}> <Link to={"/products/" + book.id}>
{index === 0 ? ( {index === 0 ? (
<img <img
src={`https://dnvn.ir/api/v1/file/${book.fileIds}`} src={`https://dnvn.ir/api/v1/file/${book.fileIds}`}

@ -0,0 +1,26 @@
import React from "react";
import userImage from "../../../assets/images/user.png";
function Comment({ comment }) {
return (
<div className="flex flex-col py-3 px-2 rounded-sm border border-gray-200 border-solid dark:border-opacity-10 ml-4 w-auto" style={{minWidth: '250px'}}>
<header className="flex flex-row justify-between">
<div className="flex flex-row items-center">
<img src={userImage} alt="" className="h-10 w-10 rounded-full" />
<strong className="text-blue5F text-md mr-1 dark:text-white">{comment?.name}</strong>
</div>
<div className=""></div>
</header>
<p className="text-xs text-gray70 mt-2 dark:text-white">{comment?.text}</p>
</div>
);
}
export default Comment;
Comment.defaultProps = {
comment: {
name: "سورنا عابدی",
text: "خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ” ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ” ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻭ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ ﻫﺮﮔﺰ ﺩﺳﺖ ﮐﺞ ﻧﺪﺍﺷﺘﻪ ﭘﺪﺭ ﺑﻪ ﻧﮕﺎﻩ ﻣﺘﻌﺠﺐ ﻓﺮﺯﻧﺪ ﻟﺒﺨﻨﺪﯼ ﺯﺩ ﻭ ﺍﺩﺍﻣﻪ ",
},
};

@ -0,0 +1,55 @@
import React from "react";
import StarRating from "../../../components/StarRating";
import Progress from "../../../components/Progress";
function Rate({ avarage, all, fields }) {
return (
<div className="w-full flex flex-row justify-between items-center mt-2">
<div className="flex flex-col items-center justify-center h-full ml-4">
<strong className="text-3xl text-blue5F mb-2 font-bold dark:text-white">
{avarage}
</strong>
<StarRating />
<span className="text-xs text-gray70 mt-2 dark:text-white">{all}</span>
</div>
<ul className="p-0 m-0 list-none flex flex-col flex-1">
{fields.map((item, index) => (
<li key={index} className="w-full flex flex-row-reverse items-center justify-between">
<span className="mr-2 text-xs text-blue5F dark:text-white">{item.name}</span>
<Progress percent={item.percent} />
<span className="ml-2 text-xs text-blue5F dark:text-white">{item.percent + "%"}</span>
</li>
))}
</ul>
</div>
);
}
export default Rate;
Rate.defaultProps = {
avarage: 4.8,
all: 4780,
fields: [
{
name: "5 ستاره",
percent: 50,
},
{
name: "4 ستاره",
percent: 50,
},
{
name: "3 ستاره",
percent: 50,
},
{
name: "2 ستاره",
percent: 50,
},
{
name: "1 ستاره",
percent: 50,
},
],
};

@ -0,0 +1,138 @@
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { book } from "../../redux/actions";
import location from "../../utils/location";
import Button from "../../components/Button";
import Header from "../../components/Header";
import Comment from "./Comment";
import Rate from "./Rate";
export const Product = ({ productType, getInfo, book, grades, isDark }) => {
useEffect(() => {
getInfo({ id: location.getId() });
}, []);
return (
<>
{/* Portrait */}
<div className="w-full flex flex-col bg-transparent px-4">
<header
className={`w-full flex ${
productType === "book" ? "flex-row" : "flex-col"
}`}
>
<img
src={`https://dnvn.ir/api/v1/file/${book?.fileIds}`}
alt=""
className="w-5/12 rounded-md"
/>
<div className="flex flex-1 flex-col pr-2 pt-2">
<h1 className="text-blue5F mb-3 font-semibold text-sm dark:text-white">
{book?.name}
</h1>
<div className="text-blueC0 text-xs dark:text-greenBA">
{"پایه" + " " + grades[book?.gradeId]}
</div>
</div>
</header>
<ul
className="list-none flex flex-row divide-x items-center mt-4"
style={{ direction: "ltr" }}
>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-xs font-medium text-blueC0 dark:text-white">
{book?.pagesNum} <br /> صفحه
</li>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-xs font-medium text-blueC0 dark:text-white">
{"فیزیکی - دیجیتالی"} <br /> در دسترس
</li>
<li className="border-solid border-blueFE flex-1 flex-shrink-0 text-center text-xs font-medium text-blueC0 dark:text-white">
{book?.rate} <br /> امتیاز
</li>
</ul>
<h2 className="text-blueC0 text-sm font-light mt-5 dark:text-greenBA">
نسخه محصول را انتخاب کنید
</h2>
<div className="w-full flex flex-row justify-between items-center mt-4">
<Button
title="نسخه فیزیکی"
backgroundColor={isDark ? "bg-transparent" : "bg-white"}
border={{ color: isDark ? "#ffffff55" : "#196EC055", width: "1px" }}
width="49%"
color={isDark ? "text-white" : "text-blueC0"}
/>
<Button
title="نسخه دیجیتال"
backgroundColor={isDark ? "bg-transparent" : "bg-white"}
border={{ color: isDark ? "#ffffff55" : "#196EC055", width: "1px" }}
width="49%"
color={isDark ? "text-white" : "text-blueC0"}
/>
</div>
<div className="w-full flex flex-row justify-between items-center mt-4">
<Button
title="خرید با قیمت 245.000 تومان"
backgroundColor="bg-blueC0"
border={{ color: "#196EC055", width: "1px" }}
width="65%"
color="text-white"
/>
<Button
title="مشاهده نمونه"
backgroundColor={isDark ? "bg-transparent" : "bg-white"}
border={{ color: isDark ? "#ffffff55" : "#196EC055", width: "1px" }}
width="33%"
color={isDark ? "text-white" : "text-blueC0"}
/>
</div>
<div className="w-full flex flex-row justify-between items-center mt-4">
<Button
title="مشاهده دوره ویدئویی این محصول"
backgroundColor="bg-blueC0"
border={{ color: "#196EC055", width: "0px" }}
bgOpacity="bg-opacity-10"
width="100%"
color={isDark ? "text-white" : "text-blueC0"}
/>
</div>
<div className="w-full flex flex-col justify-between items-center mt-4">
<Header title="توضیحات" link="#" />
<p className="text-xs text-gray1 mt-2 dark:text-white">
خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ
ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ ﻫﺮﮔﺰ
ﺩﺯﺩﯼ ﻧﮑﻦ ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ ﻫﺮﮔﺰ
ﺩﺳﺖ ﮐﺞ ﻧﺪﺍﺷﺘﻪ ﭘﺪﺭ ﺑﻪ ﻧﮕﺎﻩ ﻣﺘﻌﺠﺐ ﻓﺮﺯﻧﺪ ﻟﺒﺨﻨﺪﯼ ﺯﺩ ﺍﺩﺍﻣﻪ ﺩﺍﺩ : ﺩﺭ
ﺯﻧﺪﮔﯽ ﺩﺭﻭﻍ ﻧﮕﻮ ﭼﺮﺍ ﮐﻪ ﺍﮔﺮ ﮔﻔﺘﯽ ﺻﺪﺍﻗﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺧﯿﺎﻧﺖ ﻧﮑﻦ ﮐﻪ ﺍﮔﺮ
ﮐﺮﺩﯼ ﻋﺸﻖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺧﺸﻮﻧﺖ ﻧﮑﻦ ﺍﮔﺮ ﮐﺮﺩﯼ ﻣﺤﺒﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﻧﺎ ﺣﻖ
ﻧﮕﻮ ﺍﮔﺮ ﮔﻔﺘﯽ ﺣﻖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺑﯽ ﺣﯿﺎﯾﯽ ﻧﮑﻦ ﺍﮔﺮ ﮐﺮﺩﯼ ﺷﺮﺍﻓﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ
ﺍی... ﭘﺲ ﺩﺭ ﺯﻧﺪﮔﯽ ﻓﻘﻂ ﺩﺯﺩﯼ نکن{" "}
</p>
</div>
<div className="w-full flex flex-col justify-between items-center mt-4">
<Header title="امتیازات و نظرات" link="#" />
<Rate />
</div>
<div
className="flex flex-row w-full pb-4 mt-6"
style={{ overflowX: "scroll" }}
>
{[0, 1, 2, 2].map((comment, index) => (
<Comment key={index} />
))}
</div>
</div>
</>
);
};
const mapStateToProps = (state) => ({
book: state.book.info,
grades: state.publicApi.grades,
isDark: state.publicApi.isDark,
});
const mapDispatchToProps = { getInfo: book.info };
export default connect(mapStateToProps, mapDispatchToProps)(Product);
Product.defaultProps = {
productType: "book",
};

@ -13,7 +13,7 @@ const Product = ({ productsType, product, index, grades }) => {
<> <>
{productsType === "کتاب" && ( {productsType === "کتاب" && (
<Link <Link
to={"/products" + product?.name} to={"/products/" + product?.id}
className={`w-1/2 flex flex-col border-t border-grayDB dark:border-gray45 p-3 border-solid ${ className={`w-1/2 flex flex-col border-t border-grayDB dark:border-gray45 p-3 border-solid ${
index % 2 === 0 ? "border-l" : "" index % 2 === 0 ? "border-l" : ""
}`} }`}

@ -3318,6 +3318,11 @@ class-utils@^0.3.5:
isobject "^3.0.0" isobject "^3.0.0"
static-extend "^0.1.1" static-extend "^0.1.1"
classnames@^2.2.5:
version "2.3.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
clean-css@^4.2.3: clean-css@^4.2.3:
version "4.2.4" version "4.2.4"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178"
@ -9096,7 +9101,7 @@ prompts@^2.0.1:
kleur "^3.0.3" kleur "^3.0.3"
sisteransi "^1.0.5" sisteransi "^1.0.5"
prop-types@^15.7.2: prop-types@^15.6.1, prop-types@^15.7.2:
version "15.8.0" version "15.8.0"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.0.tgz#d237e624c45a9846e469f5f31117f970017ff588" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.0.tgz#d237e624c45a9846e469f5f31117f970017ff588"
integrity sha512-fDGekdaHh65eI3lMi5OnErU6a8Ighg2KjcjQxO7m8VHyWjcPyj5kiOgV1LQDOOOgVy3+5FgjXvdSSX7B8/5/4g== integrity sha512-fDGekdaHh65eI3lMi5OnErU6a8Ighg2KjcjQxO7m8VHyWjcPyj5kiOgV1LQDOOOgVy3+5FgjXvdSSX7B8/5/4g==
@ -9434,6 +9439,14 @@ react-scripts@4.0.3:
optionalDependencies: optionalDependencies:
fsevents "^2.1.3" fsevents "^2.1.3"
react-star-rating-component@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/react-star-rating-component/-/react-star-rating-component-1.4.1.tgz#74dc1c73493f088013331c234190b8cccad31f6b"
integrity sha512-i0YEvQzToS0s0GDkxn01Jy4EeLpVEyh023NXJTJ+/1+xkvhpACyD4d1YeBhYWZab53ppUnUxs5gmp75gJr3khA==
dependencies:
classnames "^2.2.5"
prop-types "^15.6.1"
react-toastify@^8.1.0: react-toastify@^8.1.0:
version "8.1.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-8.1.0.tgz#acaca4e8c4415c8474562dd84a14e6f390ed7f17" resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-8.1.0.tgz#acaca4e8c4415c8474562dd84a14e6f390ed7f17"

Loading…
Cancel
Save