reza connected userVote to product

temp
Reza_ashrafi 3 years ago
parent 8be8dfe377
commit b9552ffbb5
  1. 69
      src/components/StarRating/index.js
  2. 1
      src/redux/actions/index.js
  3. 26
      src/redux/actions/userVote.js
  4. 1
      src/redux/reducers/index.js
  5. 2
      src/redux/reducers/userFavorite.js
  6. 2
      src/redux/reducers/userProduct.js
  7. 31
      src/redux/reducers/userVote.js
  8. 2
      src/views/Product/index.js
  9. 15
      src/views/Video/index.js
  10. 80
      src/views/Videos/components/MostViewedVideo.js
  11. 71
      src/views/Videos/components/NewestVideo.js

@ -1,28 +1,65 @@
import React, { useState } from "react"; import React from "react";
import StarRatingComponent from "react-star-rating-component"; import StarRatingComponent from "react-star-rating-component";
import starGrayIcon from '../../assets/icons/starGray.svg'; import { userVote, userProduct } from "../../redux/actions";
import starYellowIcon from '../../assets/icons/starYellow.svg'; import { connect } from "react-redux";
import location from "../../utils/location";
//assets
import starGrayIcon from "../../assets/icons/starGray.svg";
import starYellowIcon from "../../assets/icons/starYellow.svg";
function StarRating({ value, size, addVote, userProducts, getUserProducts }) {
const [rate, setRating] = React.useState(null);
React.useEffect(() => {
getUserProducts();
}, []);
React.useEffect(() => {
if (rate) {
addVote({ productId: location.getId(), rate });
}
}, [rate]);
const isBuyer =
userProducts?.filter(
(product) => product?.condition > 1 && product?.id === location.getId()
).length > 0;
function StarRating({value, size}) {
const [rate, setRating] = useState(value);
return ( return (
<StarRatingComponent <StarRatingComponent
name="rate1" name="rate1"
onStarClick={(value) =>
renderStarIcon={(index, value)=> { isBuyer
if (index <= value){ ? setRating(value)
: addVote({ productId: location.getId(), rate: value })
}
renderStarIcon={(index, value) => {
if (index <= value) {
return (
<img
src={starYellowIcon}
className={size == "small" ? "w-3" : "w-5"}
/>
);
}
return ( return (
<img src={starYellowIcon} className={size == 'small' ? 'w-3' : 'w-5'}/> <img src={starGrayIcon} className={size == "small" ? "w-3" : "w-5"} />
); );
} }}
return (<img src={starGrayIcon} className={size == 'small' ? 'w-3' : 'w-5'}/>); value={isBuyer ? rate || value : value || 0}
}}
value={rate}
size='35'
// onStarHover={(value) => setRating(value)} // onStarHover={(value) => setRating(value)}
/> />
); );
} }
export default StarRating; const mapStateToProps = (state) => ({
userProducts: state.userProduct.list,
});
const mapDispatchToProps = {
addVote: userVote.add,
getUserProducts: userProduct.list,
};
export default connect(mapStateToProps, mapDispatchToProps)(StarRating);

@ -8,6 +8,7 @@ export { default as userFactor } from "./userFactor";
export { default as userProduct } from "./userProduct"; export { default as userProduct } from "./userProduct";
export { default as userAddress } from "./userAddress"; export { default as userAddress } from "./userAddress";
export { default as userFavorite } from "./userFavorite"; export { default as userFavorite } from "./userFavorite";
export { default as userVote } from "./userVote";
export { default as transport } from "./transport"; export { default as transport } from "./transport";
export { default as content } from "./content"; export { default as content } from "./content";
export { default as faq } from "./faq"; export { default as faq } from "./faq";

@ -0,0 +1,26 @@
import proxy from "../proxy";
const userVote = {
list:
(data = {}) =>
async (dispatch) => {
await proxy.post("userVote/list", data, { dispatch });
},
update:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.put("userVote/update", data);
},
add:
(data = {}, data2 = {}, data3 = {}) =>
async (dispatch) => {
await proxy.post("userVote/add", data, { dispatch });
},
del:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.delete("userVote/delete", data);
},
};
export default userVote;

@ -7,6 +7,7 @@ export { default as product } from "./product";
export { default as content } from "./content"; export { default as content } from "./content";
export { default as userAddress } from "./userAddress"; export { default as userAddress } from "./userAddress";
export { default as userFavorite } from "./userFavorite"; export { default as userFavorite } from "./userFavorite";
export { default as userVote } from "./userVote";
export { default as transport } from "./transport"; export { default as transport } from "./transport";
export { default as faq } from "./faq"; export { default as faq } from "./faq";
export { default as file } from "./file"; export { default as file } from "./file";

@ -5,7 +5,7 @@ const initialState = {
error: null, error: null,
list: [], list: [],
}; };
export default function userAddress(state = initialState, action) { export default function userFavorite(state = initialState, action) {
let { type, data } = action; let { type, data } = action;
switch (type) { switch (type) {
case "userFavorite/list": case "userFavorite/list":

@ -10,7 +10,7 @@ const initialState = {
checkEmpty: false, checkEmpty: false,
hasPhysical: false, hasPhysical: false,
}; };
export default function userFactor(state = initialState, action) { export default function userProduct(state = initialState, action) {
let { type, data } = action; let { type, data } = action;
switch (type) { switch (type) {
case "userProduct/myList": case "userProduct/myList":

@ -0,0 +1,31 @@
import {toast} from 'react-toastify';
const initialState = {
loading: false,
error: null,
};
export default function userVote(state = initialState, action) {
let { type, data } = action;
switch (type) {
case "userVote/list":
return {
...state,
loading: false,
error: null,
};
case "userVote/update":
return { ...state, loading: false, error: null };
case "userVote/add":
toast.success('رای شما با موفقیت ثبت شد.');
return { ...state, loading: false, error: null };
case "userVote/delete":
return { ...state, loading: false, error: null };
case "userVote/loading":
return { ...state, loading: true };
case "userVote/error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -170,7 +170,7 @@ export const Product = ({
</div> </div>
<div className="w-full flex flex-col justify-between items-center mt-10"> <div className="w-full flex flex-col justify-between items-center mt-10">
<Header title="امتیازات و نظرات" link="#" /> <Header title="امتیازات و نظرات" link="#" />
<Rate /> <Rate value={book?.rate || 0} />
</div> </div>
<div <div
className="flex flex-row w-full pb-4 mt-10 no-scrollbar" className="flex flex-row w-full pb-4 mt-10 no-scrollbar"

@ -14,6 +14,8 @@ import Button from "../../components/Button";
import ProductTab from "../../components/ProductTab"; import ProductTab from "../../components/ProductTab";
import Table from "./components/Desktop/Table"; import Table from "./components/Desktop/Table";
import Comments from "../../components/Comments"; import Comments from "../../components/Comments";
import Loading from "../../components/Loading";
//assets //assets
import tickIcon from "../../components/ProductStatusCard/tick-circle.svg"; import tickIcon from "../../components/ProductStatusCard/tick-circle.svg";
@ -39,6 +41,11 @@ function Video({
return isMobile ? ( return isMobile ? (
<div className="w-full flex flex-col px-4 pb-24"> <div className="w-full flex flex-col px-4 pb-24">
{(!book) && (
<div className="w-full h-screen flex justify-center items-center bg-white bg-opacity-20 backdrop-filter backdrop-blur-xl fixed left-0 top-0 z-50">
<Loading size={4} color="bg-green-400" />
</div>
)}
<div className="w-full flex flex-col"> <div className="w-full flex flex-col">
<div <div
className="w-full flex flex-row flex-1 = relative overflow-hidden" className="w-full flex flex-row flex-1 = relative overflow-hidden"
@ -46,17 +53,13 @@ function Video({
> >
<img <img
src={`https://dnvn.ir/api/v1/file/${book?.fileIds}`} src={`https://dnvn.ir/api/v1/file/${book?.fileIds}`}
className="rounded-md" className="rounded-sm w-5/12 object-contain"
style={{
width: "calc(100vh / 7)",
height: "calc(100vh / 7 * 4 / 3)",
}}
/> />
<div className="flex flex-col py-1 pr-3"> <div className="flex flex-col py-1 pr-3">
<strong className="text-blue5F text-lg dark:text-white font-black"> <strong className="text-blue5F text-lg dark:text-white font-black">
{"دوره ویدئویی" + " " + book?.product[2]?.name} {"دوره ویدئویی" + " " + book?.product[2]?.name}
</strong> </strong>
<span className="text-blueC0 text-base dark:text-greenBA mt-3 mb-5"> <span className="text-blueC0 text-base dark:text-greenBA font-semibold mt-3 mb-5">
{"پایه" + " " + (grades[book?.gradeId] || "پایه دوازدهم")} {"پایه" + " " + (grades[book?.gradeId] || "پایه دوازدهم")}
</span> </span>
</div> </div>

@ -5,55 +5,55 @@ import Header from "../../../components/Header";
import posterImage from "../../../assets/images/poster.svg"; import posterImage from "../../../assets/images/poster.svg";
function MostViewedVideo({ videos, grades }) { function MostViewedVideo({ videos, grades }) {
const Video = ({ video }) => {
return (
<Link
to={"/videos/" + video.id}
className="flex flex-col rounded-md ml-4 shadow-md p-2 border border-solid border-gray-200 dark:border-opacity-30 mt-3"
>
<div
className="w-full flex flex-row flex-1 justify-between items-center relative overflow-hidden"
style={{
backgroundImage: `url(${posterImage})`,
backgroundSize: "100% 100%",
repeat: "no-repeat",
minWidth: "calc(100vw / 1.4)",
minHeight: "calc(100vw / 1.4 * 10 / 16)",
}}
>
<img
src={`https://dnvn.ir/api/v1/file/${video.fileIds}`}
className="rounded-md h-full absolute left-2 top-1/2 transform -translate-y-1/2"
style={{
width: "calc(100vw / 7)",
height: "calc(100vw / 8 * 15 / 9)",
}}
/>
</div>
<strong className="text-base mt-0 text-blue5F dark:text-white font-bold">
{"دوره ویدئویی" + " " + video.name}
</strong>
<div className="w-full flex flex-row justify-between items-center mt-3">
<strong className="text-black text-tiny dark:text-greenBA">
{separate(video?.product[2]?.price) + " " + "تومان"}
</strong>
<span className="text-green7B text-sm dark:text-white">
{"پایه" + " " + grades[video.gradeId]}
</span>
</div>
</Link>
);
};
return ( return (
<div className="w-full flex flex-col"> <div className="w-full flex flex-col">
<Header title="پربازدیدترین" link="/videos/video" /> <Header title="پربازدیدترین" link="/videos/video" />
<div className="w-full flex flex-row overflow-x-scroll pb-4 no-scrollbar"> <div className="w-full flex flex-row overflow-x-scroll pb-4 no-scrollbar">
{videos.map((video, index) => ( {videos.map((video, index) => (
<Video key={index} video={video} /> <Video key={index} video={video} grades={grades} />
))} ))}
</div> </div>
</div> </div>
); );
} }
const Video = ({ video, grades }) => {
return (
<Link
to={"/videos/" + video.id}
className="flex flex-col rounded-md ml-4 shadow-md p-2 border border-solid border-gray-200 dark:border-opacity-30 mt-3"
>
<div
className="w-full flex flex-row flex-1 justify-between items-center relative overflow-hidden"
style={{
backgroundImage: `url(${posterImage})`,
backgroundSize: "100% 100%",
repeat: "no-repeat",
minWidth: "calc(100vw / 1.4)",
minHeight: "calc(100vw / 1.4 * 10 / 16)",
}}
>
<img
src={`https://dnvn.ir/api/v1/file/${video.fileIds}`}
className="rounded-sm h-full absolute left-2 top-1/2 transform -translate-y-1/2 object-contain"
style={{
width: "calc(100vw / 7)",
}}
/>
</div>
<strong className="text-base mt-0 text-blue5F dark:text-white font-bold">
{"دوره ویدئویی" + " " + video.name}
</strong>
<div className="w-full flex flex-row justify-between items-center mt-3">
<span className="text-green7B text-sm dark:text-white">
{"پایه" + " " + grades[video.gradeId]}
</span>
<strong className="text-black text-tiny dark:text-greenBA">
{separate(video?.product[2]?.price) + " " + "تومان"}
</strong>
</div>
</Link>
);
};
export default MostViewedVideo; export default MostViewedVideo;

@ -1,52 +1,53 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import Header from "../../../components/Header";
import separate from "../../../utils/separate"; import separate from "../../../utils/separate";
//components
import Header from "../../../components/Header";
const NewestVideo = ({ videos, grades }) => { const NewestVideo = ({ videos, grades }) => {
const Video = ({ video }) => {
return (
<Link
to={"/videos/" + video.id}
className="flex flex-col items-start mb-4 shadow-md p-2 rounded-md overflow-hidden"
style={{ width: "calc(100vw / 2.2)" }}
>
<div className="w-full bg-gray-200 py-2 rounded-t-md">
<img
src={`https://dnvn.ir/api/v1/file/${video.fileIds}`}
className="rounded-md mx-auto"
style={{
height: "calc(100vh / 7)",
width: "calc(100vh / 7 * 2 / 3)",
}}
/>
</div>
<strong className="text-base mt-2 text-blue5F dark:text-white font-normal">
{video.name}
</strong>
<div className="flex items-center justify-between w-full mt-2">
<span className="text-green7B text-sm dark:text-greenBA">
{"پایه" + " " + grades[video.gradeId]}
</span>
<strong className="text-black text-tiny dark:text-greenBA">
{separate(video?.product[2]?.price) + " " + "تومان"}
</strong>
</div>
</Link>
);
};
return ( return (
<div className="w-full flex flex-col"> <div className="w-full flex flex-col">
<Header title="جدیدترین دورهها" link="/videos/video" /> <Header title="جدیدترین دورهها" link="/videos/video" />
<div className="w-full flex flex-row flex-wrap justify-between overflow-x-scroll mt-3"> <div className="w-full flex flex-row flex-wrap justify-between overflow-x-scroll mt-3">
{videos.slice(0, 5).map((video, index) => ( {videos.slice(0, 4).map((video, index) => (
<Video key={index} video={video} /> <Video key={index} video={video} grades={grades} />
))} ))}
</div> </div>
</div> </div>
); );
}; };
const Video = ({ video, grades }) => {
return (
<Link
to={"/videos/" + video.id}
className="flex flex-col items-start mb-4 shadow-md p-2 rounded-md overflow-hidden"
style={{ width: "calc(100vw / 2.2)" }}
>
<div className="w-full bg-gray-200 py-2 rounded-t-md">
<img
src={`https://dnvn.ir/api/v1/file/${video.fileIds}`}
className="rounded-sm mx-auto object-contain"
style={{
width: "calc(100vh / 7 * 2 / 3)",
}}
/>
</div>
<strong className="text-base mt-2 text-blue5F dark:text-white font-normal">
{video.name}
</strong>
<div className="flex items-center justify-between w-full mt-2">
<span className="text-green7B text-sm dark:text-greenBA">
{"پایه" + " " + grades[video.gradeId]}
</span>
<strong className="text-black text-tiny dark:text-greenBA">
{separate(video?.product[2]?.price) + " " + "تومان"}
</strong>
</div>
</Link>
);
};
export default NewestVideo; export default NewestVideo;

Loading…
Cancel
Save