@ -0,0 +1,41 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import { connect } from 'react-redux'; |
||||||
|
import { createStructuredSelector } from "reselect"; |
||||||
|
import { withRouter } from 'react-router-dom'; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import { selectCartItems } from "../../redux/cart/cart.selectors"; |
||||||
|
import { toggleCartHidden } from '../../redux/cart/cart.actions'; |
||||||
|
|
||||||
|
|
||||||
|
import './cart-dropdown.styles.scss'; |
||||||
|
|
||||||
|
const CartDropdown = ({ cartItems, history, dispatch }) => ( |
||||||
|
<div className='cart-dropdown'> |
||||||
|
<div className='cart-items'> |
||||||
|
{ |
||||||
|
cartItems.length ? ( |
||||||
|
cartItems.map(cartItem => ( |
||||||
|
<CartItem key={cartItem.id} item={cartItem}/>
|
||||||
|
)) |
||||||
|
):( |
||||||
|
<span className='empty-message'>سبد خرید شما خالیست.</span> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
<center><button |
||||||
|
onClick={() => { |
||||||
|
history.push('/checkout'); |
||||||
|
dispatch(toggleCartHidden()) |
||||||
|
}}>
|
||||||
|
تسویه حساب |
||||||
|
</button> |
||||||
|
</center> |
||||||
|
</div> |
||||||
|
) |
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({ |
||||||
|
cartItems: selectCartItems |
||||||
|
}) |
||||||
|
|
||||||
|
export default withRouter(connect(mapStateToProps)(CartDropdown)); |
After Width: | Height: | Size: 868 B |
After Width: | Height: | Size: 86 KiB |
@ -0,0 +1,276 @@ |
|||||||
|
import React, { useState } from "react"; |
||||||
|
|
||||||
|
// import Tag from "../Tag";
|
||||||
|
// import ReactTooltip from "react-tooltip";
|
||||||
|
|
||||||
|
import book from "./goldon.png"; |
||||||
|
import watermelon from "./watermelon.png"; |
||||||
|
import heart from "./vuesax-linear-heart.svg"; |
||||||
|
import discountImg from "./discount.png"; |
||||||
|
import YellowDotIcon from "./yellowDotIcon.svg"; |
||||||
|
import RedDotIcon from "./redDotIcon.svg"; |
||||||
|
import PurpleDotIcon from "./purpleDotIcon.svg"; |
||||||
|
import LightBlueDotIcon from "./lightBlueDotIcon.svg"; |
||||||
|
|
||||||
|
|
||||||
|
const ProductDesign = ({ |
||||||
|
colors, |
||||||
|
likeBtn, |
||||||
|
discount, |
||||||
|
discountPricePercent, |
||||||
|
discountPrice, |
||||||
|
productContent, |
||||||
|
star, |
||||||
|
productTags, |
||||||
|
priceDirection, |
||||||
|
productTitleAlignment, |
||||||
|
priceHolder, |
||||||
|
productHolderBorder, |
||||||
|
productHolderBorderColor, |
||||||
|
productTitleColor, |
||||||
|
productExcerptTextColor, |
||||||
|
productCat, |
||||||
|
productCatTextColor, |
||||||
|
rangeHolder, |
||||||
|
verticalImg, |
||||||
|
horizontalImg, |
||||||
|
rangeWidth, |
||||||
|
addToCartHolder, |
||||||
|
productName, |
||||||
|
productPrice, |
||||||
|
productImg, |
||||||
|
writeGHEIMAT, |
||||||
|
numberOfRegards, |
||||||
|
productHolderHoverBorder, |
||||||
|
hoverMode, |
||||||
|
big, |
||||||
|
starRate |
||||||
|
}) => { |
||||||
|
const [isHovering, setIsHovering] = useState(false); |
||||||
|
return ( |
||||||
|
<div className={`flex flex-wrap sm:flex-nowrap justify-around ${big ? 'm' : 'w-48 m-2'} `} |
||||||
|
style={big ? {width: '300px'} : {}} |
||||||
|
|
||||||
|
> |
||||||
|
<div className="w-full flex flex-wrap items-center justify-around my-5 px-4" > |
||||||
|
<div |
||||||
|
className={`w-full sm:w-60 md:w-72 ${big ? '' : 'mx-5'} rounded-lg transition-all p-2 my-3 ${productHolderBorder} ${hoverMode == 'blue' ? 'hover:bg-grayF4' : null} ${productHolderBorderColor} hover:${productHolderHoverBorder} hover:` } |
||||||
|
onMouseEnter={() => setIsHovering(true)} |
||||||
|
onMouseLeave={() => setIsHovering(false)} |
||||||
|
> |
||||||
|
{/* product image */} |
||||||
|
<div className="w-full relative"> |
||||||
|
{/* icons on image */} |
||||||
|
<div className="absolute left-0 top-10"> |
||||||
|
{discountPricePercent && ( |
||||||
|
<div className="bg-discountPriceBg bg-white w-full p-2 px-3"> |
||||||
|
<p className="text-discountPriceTitle font-bold text-md text-blueC0"> |
||||||
|
23<span>%</span> |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
{likeBtn && ( |
||||||
|
<div className="bg-likeBtnBg rounded-md flex justify-center my-2"> |
||||||
|
<img src={heart} alt="" className="w-5" /> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
{discount && ( |
||||||
|
<div className="rounded-md"> |
||||||
|
<img src={discountImg} alt="" className="w-full" /> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
{/* img */} |
||||||
|
<div className={`w-full ${big ? 'h-60' : 'h-48'} flex bg-grayF4 p-0 justify-center rounded-lg`}> |
||||||
|
{verticalImg && ( |
||||||
|
<img |
||||||
|
src={productImg} |
||||||
|
alt="" |
||||||
|
className="h-full rounded-lg cursor-pointer py-5" |
||||||
|
|
||||||
|
/> |
||||||
|
)} |
||||||
|
{horizontalImg && ( |
||||||
|
<img src={watermelon} alt="" className="w-full rounded-lg" /> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
{/* select Color */} |
||||||
|
{/* {colors && ( |
||||||
|
<div className="flex items-center absolute right-2 bottom-2"> |
||||||
|
<img |
||||||
|
src={YellowDotIcon} |
||||||
|
alt="" |
||||||
|
data-tip="زرد" |
||||||
|
className="w-3 h-3 ml-1 cursor-pointer" |
||||||
|
/> |
||||||
|
<ReactTooltip place="top" type="dark" effect="float" /> |
||||||
|
<img |
||||||
|
src={RedDotIcon} |
||||||
|
alt="" |
||||||
|
data-tip="قرمز" |
||||||
|
className="w-3 h-3 ml-1 cursor-pointer" |
||||||
|
/> |
||||||
|
<ReactTooltip place="top" type="dark" effect="float" /> |
||||||
|
<img |
||||||
|
src={PurpleDotIcon} |
||||||
|
alt="" |
||||||
|
data-tip="بنفش" |
||||||
|
className="w-3 h-3 ml-1 cursor-pointer" |
||||||
|
/> |
||||||
|
<ReactTooltip place="top" type="dark" effect="float" /> |
||||||
|
<img |
||||||
|
src={LightBlueDotIcon} |
||||||
|
alt="" |
||||||
|
data-tip="آبی" |
||||||
|
className="w-3 h-3 ml-1 cursor-pointer" |
||||||
|
/> |
||||||
|
<ReactTooltip place="top" type="dark" effect="float" /> |
||||||
|
</div> |
||||||
|
)} */} |
||||||
|
|
||||||
|
</div> |
||||||
|
{/* product content */} |
||||||
|
<div className="px-2"> |
||||||
|
<div className="mt-4"> |
||||||
|
<h2 |
||||||
|
className={`leading-4 text-xl font-black py-2 ${productTitleColor} ${productTitleAlignment}`} |
||||||
|
> |
||||||
|
{productName} |
||||||
|
</h2> |
||||||
|
{productContent && ( |
||||||
|
<p |
||||||
|
className={`text-justify mt-2 text-xs leading-6 ${productExcerptTextColor}`} |
||||||
|
> |
||||||
|
این کتاب شامل گلدان و گیاه و خاک می باشد و همچنین آپشن های خوب |
||||||
|
دیگری نیز دارد. |
||||||
|
</p> |
||||||
|
)} |
||||||
|
{productCat && ( |
||||||
|
<span className={`text-md py-1 font-light ${productCatTextColor}`}> |
||||||
|
{productCat} |
||||||
|
</span> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
{/* star */} |
||||||
|
{/* price */} |
||||||
|
{priceHolder && ( |
||||||
|
<div |
||||||
|
className={`flex items-center justify-between ${priceDirection}`} |
||||||
|
> |
||||||
|
<div className="mt-2"> |
||||||
|
<div |
||||||
|
className={`${priceDirection.indexOf("col") !== -1 ? "inline" : "flex" |
||||||
|
}`}
|
||||||
|
> |
||||||
|
{writeGHEIMAT && <span className="text-xs text-borderColor ml-2">قیمت</span>} |
||||||
|
{/* price with line on it */} |
||||||
|
{discountPrice && ( |
||||||
|
<p className="line-through text-xs text-borderColor mr-2"> |
||||||
|
145<span>تومان</span> |
||||||
|
</p> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
<p className="text-xl text-productPrice font-semibold inline text-blue5F"> |
||||||
|
{productPrice} <span>تومان</span> |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
{/* add to cart */} |
||||||
|
{addToCartHolder && ( |
||||||
|
<button |
||||||
|
className={`rounded-2xl px-2 py-3 border text-xs text-productPrice mt-2 hover:bg-darkCrimsonBgColor hover:text-white active:bg-rangeFillBgColor transition duration-500 hover:-translate-y-2 ${priceDirection.indexOf("col") !== -1 ? "w-full" : "" |
||||||
|
}`}
|
||||||
|
> |
||||||
|
اضافه کردن به سبد خرید |
||||||
|
</button> |
||||||
|
|
||||||
|
)} |
||||||
|
|
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
)} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{hoverMode == 'blue' ?<div className="w-full flex justify-center mt-4"> |
||||||
|
<div |
||||||
|
className={`bg-blueC0 text-white rounded p-4 text-xs justify-center ${isHovering ? "" : "hidden" |
||||||
|
}`}
|
||||||
|
> |
||||||
|
<button>افزودن به سبد خرید</button> |
||||||
|
</div> |
||||||
|
</div> : null} |
||||||
|
|
||||||
|
{/* {productTags && ( |
||||||
|
<div className="mt-2 flex flex-wrap"> |
||||||
|
{ |
||||||
|
productTags.map((item, index) => <Tag title={item} key={index} />) |
||||||
|
} |
||||||
|
</div> |
||||||
|
)} */} |
||||||
|
{rangeHolder && ( |
||||||
|
<div className="bg-rangeBgColor h-3 w-full rounded mt-2"> |
||||||
|
<div |
||||||
|
className={`bg-rangeFillBgColor h-3 rounded ${rangeWidth}`} |
||||||
|
></div> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default ProductDesign; |
||||||
|
|
||||||
|
// text colors i used for product title:
|
||||||
|
// text-darkCrimsonTextColor
|
||||||
|
// text-productTitle
|
||||||
|
|
||||||
|
// text color i used for product excerpt:
|
||||||
|
// text-productContent
|
||||||
|
|
||||||
|
// text color i used for product cat:
|
||||||
|
// text-darkCrimsonTextColor
|
||||||
|
|
||||||
|
ProductDesign.defaultProps = { |
||||||
|
// icons on product image
|
||||||
|
colors: false, |
||||||
|
likeBtn: false, |
||||||
|
discount: false, |
||||||
|
discountPricePercent: false, |
||||||
|
// product price
|
||||||
|
discountPrice: false, |
||||||
|
priceHolder: true, |
||||||
|
|
||||||
|
productContent: false, |
||||||
|
star: true, |
||||||
|
productTags: [], |
||||||
|
productCat: true, |
||||||
|
rangeHolder: true, |
||||||
|
|
||||||
|
// دو مدل عکس طراحی کردم که یکی عرض بیشتری دارد یکی ارتفاع
|
||||||
|
verticalImg: true, |
||||||
|
horizontalImg: false, |
||||||
|
|
||||||
|
addToCartHolder: false, |
||||||
|
|
||||||
|
productTitleColor: "text-productTitle", |
||||||
|
|
||||||
|
productExcerptTextColor: "text-productContent", |
||||||
|
|
||||||
|
productCatTextColor: "text-darkCrimsonTextColor", |
||||||
|
// برای درصد دادن به عرض رنج
|
||||||
|
rangeWidth: "w-44", |
||||||
|
//دی ای وی که محصول داخلش است میتونیم بهش بوردر بدیم
|
||||||
|
productHolderBorder: "border", |
||||||
|
productHolderBorderColor: "border-grayBorderColor", |
||||||
|
|
||||||
|
productTitleAlignment: "text-justify", |
||||||
|
//میتونیم تعیین کنیم که قیمت و دکمه اضاف به سبد خرید کنار یکدیگر باشند یا زیر هم
|
||||||
|
priceDirection: "flex-row", |
||||||
|
productImg: book, |
||||||
|
writeGHEIMAT: false |
||||||
|
}; |
After Width: | Height: | Size: 177 B |
After Width: | Height: | Size: 177 B |
After Width: | Height: | Size: 177 B |
After Width: | Height: | Size: 675 B |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 177 B |
@ -1,18 +1,28 @@ |
|||||||
import React from "react"; |
import React from 'react'; |
||||||
const Class = ({ |
import { connect } from 'react-redux'; |
||||||
title, |
|
||||||
description, |
import { addItem }from '../../../redux/cart/cart.actions.js'; |
||||||
teacher, |
|
||||||
group, |
|
||||||
price, |
|
||||||
}) => { |
const Class = ({item, addItem}) => { |
||||||
return( |
const {name, price, imageUrl} = item; |
||||||
<div> |
return ( |
||||||
<h1>{title}</h1> |
<div className="collection-item"> |
||||||
<p>{description}</p> |
|
||||||
{teacher} {group} {price} |
<img src={imageUrl} className='image'/> |
||||||
|
<div className="collection-footer"> |
||||||
|
<span className="name"> {name} </span> |
||||||
|
<span className="price"> {price} </span> |
||||||
</div> |
</div> |
||||||
) |
|
||||||
}; |
|
||||||
|
|
||||||
export default Class |
<button onClick={ () => addItem(item)} inverted>افزودن به سبد خرید</button> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({ |
||||||
|
addItem: item => dispatch(addItem(item)) |
||||||
|
}) |
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps) (Class); |
@ -0,0 +1,36 @@ |
|||||||
|
// gray |
||||||
|
$gray : #aaa; |
||||||
|
$gray1 : #383838; |
||||||
|
$gray2 : #6c6c6c; |
||||||
|
$gray3 : rgb(143, 142, 142); |
||||||
|
$gray4 : #666666; |
||||||
|
$gray5 : #555; |
||||||
|
$gray6 : #ddd; |
||||||
|
$gray7 : #797979; |
||||||
|
$gray8 : #272727; |
||||||
|
$gray9 : #b3b3b3; |
||||||
|
$gray10 : #cccccc; |
||||||
|
$gray11 : #969696; |
||||||
|
$gray12 : #e9e9e9; |
||||||
|
$gray13 : #f6f6f6; |
||||||
|
// green |
||||||
|
$green : #4dd35b; |
||||||
|
$green1 : #81C342; |
||||||
|
$green2 : #6cbe44; |
||||||
|
$green3 : #00cc69; |
||||||
|
$green4 : #84de56; |
||||||
|
$green5 : #9cdf52; |
||||||
|
$green6 : #08793d; |
||||||
|
// blue |
||||||
|
$blue : #a2b4cb; |
||||||
|
$blue1 : #505a82; |
||||||
|
$blue2 : #00FFF8; |
||||||
|
// red |
||||||
|
$red : red; |
||||||
|
$red1 : rgb(255, 115, 115); |
||||||
|
|
||||||
|
//yellow |
||||||
|
$yellow : #FFD70F; |
||||||
|
|
||||||
|
//orange |
||||||
|
$orange : orange; |
@ -0,0 +1,9 @@ |
|||||||
|
export const ApiConfig = { |
||||||
|
apiKey: 'AIzaSyBBksq-Asxq2M4Ot-75X19IyrEYJqNBPcg', |
||||||
|
authDomain: 'dnvn.ir', |
||||||
|
baseUrl: 'https://dnvn.ir/api/v1', |
||||||
|
//baseUrl: 'http://localhost:3030/api/v1',
|
||||||
|
loginURL: 'user/login', |
||||||
|
otploginURL: 'user/otp/login', |
||||||
|
logoutURL: 'user/logout', |
||||||
|
}; |
@ -0,0 +1,8 @@ |
|||||||
|
$xs : 320px; |
||||||
|
$sm : 640px; |
||||||
|
$md : 768px; |
||||||
|
$lg : 1024px; |
||||||
|
$xl : 1280px; |
||||||
|
$xxl : 1536px; |
||||||
|
|
||||||
|
$maxWidth : calc(100% - 120px); |
@ -0,0 +1,27 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const blog = { |
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("public/blogList", data, { dispatch }), |
||||||
|
// update:
|
||||||
|
// (data = {}, data2 = {}) =>
|
||||||
|
// async (dispatch : Dispatch) => {
|
||||||
|
// await proxy.put("blog/update", data);
|
||||||
|
// await proxy.get("blog/list", data2, { dispatch });
|
||||||
|
// },
|
||||||
|
// add:
|
||||||
|
// (data = {}, data2 = {}) =>
|
||||||
|
// async (dispatch : Dispatch) => {
|
||||||
|
// await proxy.post("blog/add", data);
|
||||||
|
// await proxy.get("blog/list", data2, { dispatch });
|
||||||
|
// },
|
||||||
|
// del:
|
||||||
|
// (data = {}, data2 = {}) =>
|
||||||
|
// async (dispatch : Dispatch) => {
|
||||||
|
// await proxy.delete("blog/delete", data);
|
||||||
|
// await proxy.get("blog/list", data2, { dispatch });
|
||||||
|
// },
|
||||||
|
}; |
||||||
|
|
||||||
|
export default blog; |
@ -0,0 +1,44 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const book = { |
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("book/list", data, { dispatch }), |
||||||
|
info: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("book/info", data, { dispatch }), |
||||||
|
setLessonActive: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "book/lesson/active", data: data }), |
||||||
|
gradeFilter: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "book/gradeFilter", data: data }), |
||||||
|
sortFilter: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "book/sortFilter", data: data }), |
||||||
|
|
||||||
|
// update:
|
||||||
|
// (data = {}, data2 = {}) =>
|
||||||
|
// async (dispatch : Dispatch) => {
|
||||||
|
// await proxy.put("book/update", data);
|
||||||
|
// await proxy.get("book/list", data2, { dispatch });
|
||||||
|
// },
|
||||||
|
// add:
|
||||||
|
// (data = {}, data2 = {}) =>
|
||||||
|
// async (dispatch) => {
|
||||||
|
// await proxy.post("book/add", data);
|
||||||
|
// await proxy.get("book/list", data2, { dispatch });
|
||||||
|
// },
|
||||||
|
// del:
|
||||||
|
// (data = {}, data2 = {}) =>
|
||||||
|
// async (dispatch) => {
|
||||||
|
// await proxy.delete("book/delete", data);
|
||||||
|
// await proxy.get("book/list", data2, { dispatch });
|
||||||
|
// },
|
||||||
|
// searchBook: (data) => async (dispatch) => {
|
||||||
|
// dispatch({ type: "book/search", data: data });
|
||||||
|
// },
|
||||||
|
// filterBook: (data) => async (dispatch) => {
|
||||||
|
// dispatch({ type: "book/filter", data: data });
|
||||||
|
// },
|
||||||
|
}; |
||||||
|
|
||||||
|
export default book; |
@ -0,0 +1,14 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
import { Dispatch } from "redux"; |
||||||
|
const content = { |
||||||
|
listVOD: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("content/listVOD", data, { dispatch }), |
||||||
|
infoVOD: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("content/infoVOD", data, { dispatch }), |
||||||
|
}; |
||||||
|
|
||||||
|
export default content; |
@ -0,0 +1,20 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
import { Dispatch } from "redux"; |
||||||
|
const faq = { |
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("faq/list", data, { dispatch }), |
||||||
|
add: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.post("faq/add", data, { dispatch }), |
||||||
|
selectFaq: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await dispatch({ type: "faq/selectFaq", data: data }), |
||||||
|
searchFaq: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "faq/search", data: data }), |
||||||
|
}; |
||||||
|
|
||||||
|
export default faq; |
@ -0,0 +1,22 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const file = { |
||||||
|
upload: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
var formData = new FormData(); |
||||||
|
for (let key in data) formData.append(key, data[key]); |
||||||
|
return await proxy.post( |
||||||
|
"file/upload", |
||||||
|
formData, |
||||||
|
{ |
||||||
|
dispatch, |
||||||
|
headers: { |
||||||
|
"Content-Type": "multipart/form-data", |
||||||
|
}, |
||||||
|
}, |
||||||
|
data |
||||||
|
); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default file; |
@ -0,0 +1,18 @@ |
|||||||
|
// @create-index
|
||||||
|
export { default as publicApi } from "./public"; |
||||||
|
export { default as user } from "./user"; |
||||||
|
export { default as book } from "./book"; |
||||||
|
export { default as blog } from "./blog"; |
||||||
|
export { default as product } from "./product"; |
||||||
|
export { default as userFactor } from "./userFactor"; |
||||||
|
export { default as userProduct } from "./userProduct"; |
||||||
|
export { default as content } from "./content"; |
||||||
|
export { default as faq } from "./faq"; |
||||||
|
export { default as file } from "./file"; |
||||||
|
export {default as scrollAction} from "./scroll"; |
||||||
|
export {default as qr} from "./qr"; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,30 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const product = { |
||||||
|
getSimilar: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("product/similar", data, { dispatch }), |
||||||
|
listVOD: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("product/listVOD", data, { dispatch }), |
||||||
|
addVOD: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("product/addVOD", data); |
||||||
|
await proxy.get("product/listVOD", data2, { dispatch }); |
||||||
|
}, |
||||||
|
deleteVOD: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.delete("product/deleteVOD", data); |
||||||
|
await proxy.get("product/listVOD", data2, { dispatch }); |
||||||
|
}, |
||||||
|
selectVOD: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "product/selectVOD", data }); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default product; |
@ -0,0 +1,56 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const publicApi = { |
||||||
|
setDesktopContentTransform: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "public/setDesktopContentTransform", data }), |
||||||
|
setHeaderOptions: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "public/setHeaderOptions", data }), |
||||||
|
setIsDark: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "public/setIsDark", data }), |
||||||
|
getHomeData: (data) => async (dispatch) => |
||||||
|
await proxy.get("public/homePage", data, { dispatch }), |
||||||
|
|
||||||
|
setFaqActive: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "public/faq/activate", data }), |
||||||
|
bookInfo: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("public/vod/bookCourse", data, { dispatch }), |
||||||
|
bookSection: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("public/vod/bookSection", data, { dispatch }), |
||||||
|
getContactData: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("public/contact", data, { dispatch }), |
||||||
|
|
||||||
|
getBlogList: (data) => async (dispatch) => |
||||||
|
await proxy.get("public/blogList", data, { dispatch }), |
||||||
|
|
||||||
|
getBlogInfo: (data) => async (dispatch) => |
||||||
|
await proxy.get("public/blogInfo", data, { dispatch }), |
||||||
|
setSubscribe: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "public/setSubscribe", data }), |
||||||
|
getProvince: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("public/province", data, { dispatch }), |
||||||
|
getCity: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("public/city", data, { dispatch }), |
||||||
|
selectMenu: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "public/selectMenu", data }), |
||||||
|
getHeader: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("public/VOD/homePage", data, { dispatch }), |
||||||
|
activeCategory: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "active/category", data }), |
||||||
|
setVideoActive: (data) => async (dispatch) => |
||||||
|
await dispatch({ type: "active/video", data }), |
||||||
|
getArList: (data, history) => async (dispatch) => |
||||||
|
await proxy.get("public/ar", data, { history, dispatch }), |
||||||
|
}; |
||||||
|
|
||||||
|
export default publicApi; |
@ -0,0 +1,32 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const qr = { |
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("qr/list", data, { dispatch }), |
||||||
|
info: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.get("qr/info", data, { dispatch }); |
||||||
|
}, |
||||||
|
add: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("qr/add", data); |
||||||
|
await proxy.get("qr/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
del: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.delete("ar/delete", data); |
||||||
|
await proxy.get("ar/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
update: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.put("ar/update", data); |
||||||
|
await proxy.get("ar/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default qr; |
@ -0,0 +1,74 @@ |
|||||||
|
const scrollAction = { |
||||||
|
floatMouseToggle: |
||||||
|
(data = null) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page1/floatMouse", data }); |
||||||
|
}, |
||||||
|
handlePage1TopPosition: |
||||||
|
(data = null) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page1/top", data }); |
||||||
|
}, |
||||||
|
handlePage2TopPosition: |
||||||
|
(data = null) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page2/top", data }); |
||||||
|
}, |
||||||
|
handlePage2RotateX: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page2/rotateX", data }); |
||||||
|
}, |
||||||
|
handlePage2BoxPosition: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page2/boxPosition", data }); |
||||||
|
}, |
||||||
|
handlePage2MobilePosition: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page2/mobilePosition", data }); |
||||||
|
}, |
||||||
|
handlePage2VideoPosition: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page2/videoPosition", data }); |
||||||
|
}, |
||||||
|
handlePage2VideoTopPosition: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page2/videoTopPosition", data }); |
||||||
|
}, |
||||||
|
handlePage2MobileUnit: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page2/mobileUnit", data }); |
||||||
|
}, |
||||||
|
handleVideoTubeTopPosition: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/videoTube/top", data }); |
||||||
|
}, |
||||||
|
handleTestTranslateY: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/test/translateY", data }); |
||||||
|
}, |
||||||
|
handlePage3TopPosition: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page3/top", data }); |
||||||
|
}, |
||||||
|
handlePage3TestTranslateY: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page3/testTranslateY", data }); |
||||||
|
}, |
||||||
|
handlePage4TopPosition: |
||||||
|
(data = window.scrollY) => |
||||||
|
async (dispatch) => { |
||||||
|
await dispatch({ type: "scroll/page4/top", data }); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default scrollAction; |
@ -0,0 +1,63 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
|
||||||
|
const user = { |
||||||
|
otp: (data) => async (dispatch) => |
||||||
|
await proxy.post("public/sendOTP", data, { dispatch }), |
||||||
|
|
||||||
|
otp_login: (data) => async (dispatch) => |
||||||
|
await proxy.login("user/otp/login", data, { dispatch }), |
||||||
|
|
||||||
|
login: (data) => async (dispatch) => |
||||||
|
await proxy.login("user/login", data, { dispatch }), |
||||||
|
|
||||||
|
// register: (data : undefined) => async (dispatch : Dispatch) =>
|
||||||
|
// await proxy.login("user/register", data, { dispatch }),
|
||||||
|
|
||||||
|
// switchRole: (data : String) => async (dispatch : Dispatch) =>
|
||||||
|
// await proxy.login("user/switchRole", data, { dispatch }),
|
||||||
|
|
||||||
|
logout: (data) => async (dispatch) => |
||||||
|
await proxy.logout("user/logout", data, { dispatch }), |
||||||
|
|
||||||
|
getUserRole: (data) => async (dispatch) => |
||||||
|
await proxy.get("user/getUserRole", data, { dispatch }), |
||||||
|
|
||||||
|
// list:
|
||||||
|
// (data = {}) =>
|
||||||
|
// async (dispatch : Dispatch) =>
|
||||||
|
// await proxy.get("user/list", data, { dispatch }),
|
||||||
|
// domains:
|
||||||
|
// (data = {}) =>
|
||||||
|
// async (dispatch : Dispatch) =>
|
||||||
|
// await proxy.get("user/domains", data, { dispatch }),
|
||||||
|
// getmothers:
|
||||||
|
// (data = {}) =>
|
||||||
|
// async (dispatch : Dispatch) =>
|
||||||
|
// await proxy.get("mothers/list", data, {
|
||||||
|
// dispatch,
|
||||||
|
// }),
|
||||||
|
getProfile: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("user/getProfile", data, { dispatch }), |
||||||
|
setProfile: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.put("user/setProfile", data, { dispatch }); |
||||||
|
await proxy.get("user/getProfile", data2, { dispatch }); |
||||||
|
}, |
||||||
|
add: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("user/add", data); |
||||||
|
await proxy.get("user/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
del: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.delete("user/delete", data); |
||||||
|
await proxy.get("user/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default user; |
@ -0,0 +1,55 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const userFactor = { |
||||||
|
//dnvn
|
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("userFactor/list", data, { dispatch }), |
||||||
|
payment: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("userFactor/payment", data, { dispatch }); |
||||||
|
}, |
||||||
|
add: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("userFactor/add", data, { dispatch }); |
||||||
|
await proxy.get("userFactor/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
del: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.delete("userFactor/delete", data); |
||||||
|
await proxy.get("userFactor/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
|
||||||
|
//vod
|
||||||
|
payment: |
||||||
|
(data1 = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("userProduct/addVOD", data1, { dispatch }); |
||||||
|
await proxy.post("userFactor/paymentVOD", data2, { dispatch }); |
||||||
|
}, |
||||||
|
verify: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.post("userFactor/verifyVOD", data, { dispatch }), |
||||||
|
info: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("userFactor/info", data, { dispatch }), |
||||||
|
update: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.put("userFactor/update", data, { dispatch }); |
||||||
|
await proxy.get("userFactor/info", data2, { dispatch }); |
||||||
|
}, |
||||||
|
deleteUserOffCode: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.delete("userFactor/deleteUserOffCode", data, { dispatch }); |
||||||
|
await proxy.get("userFactor/info", data2, { dispatch }); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default userFactor; |
@ -0,0 +1,33 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const userProduct = { |
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.get("userProduct/list", data, { dispatch }); |
||||||
|
}, |
||||||
|
info: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await proxy.get("userProduct/info", data, { dispatch }), |
||||||
|
update: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.put("userProduct/update", data); |
||||||
|
await proxy.get("userProduct/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
add: |
||||||
|
(data = {}, data2 = {}, data3 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("userProduct/add", data, { dispatch }); |
||||||
|
await proxy.get("userProduct/list", data2, { dispatch }); |
||||||
|
await proxy.get("userFactor/info", data3, { dispatch }); |
||||||
|
}, |
||||||
|
del: |
||||||
|
(data = {}, data2 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.delete("userProduct/delete", data); |
||||||
|
await proxy.get("userProduct/list", data2, { dispatch }); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default userProduct; |
@ -0,0 +1,8 @@ |
|||||||
|
const CartActionTypes = { |
||||||
|
TOGGLE_CART_HIDDEN: "TOGGLE_CART_HIDDEN", |
||||||
|
ADD_ITEM: "ADD_ITEM", |
||||||
|
REMOVE_ITEM: "REMOVE_ITEM", |
||||||
|
CLEAR_ITEM_FROM_CART: "CLEAR_ITEM_FROM_CART" |
||||||
|
}; |
||||||
|
|
||||||
|
export default CartActionTypes; |
@ -0,0 +1,20 @@ |
|||||||
|
import CartActionTypes from './card.types' |
||||||
|
|
||||||
|
export const toggleCartHidden = () => ({ |
||||||
|
type: CartActionTypes.TOGGLE_CART_HIDDEN |
||||||
|
}) |
||||||
|
|
||||||
|
export const addItem = item =>({ |
||||||
|
type: CartActionTypes.ADD_ITEM, |
||||||
|
payload: item
|
||||||
|
}) |
||||||
|
|
||||||
|
export const removeItem = item =>({ |
||||||
|
type: CartActionTypes.REMOVE_ITEM, |
||||||
|
payload: item |
||||||
|
}) |
||||||
|
|
||||||
|
export const clearItemFromCart = item => ({ |
||||||
|
type: CartActionTypes.CLEAR_ITEM_FROM_CART, |
||||||
|
payload: item |
||||||
|
}) |
@ -0,0 +1,43 @@ |
|||||||
|
import CartActionTypes from './card.types.js'; |
||||||
|
import {addItemsToCart, removeItemFromCart} from './cart.utils.js'; |
||||||
|
|
||||||
|
const INITIAL_STATE = { |
||||||
|
hidden: true, |
||||||
|
cartItems: [] |
||||||
|
} |
||||||
|
|
||||||
|
const cartReducer = (state = INITIAL_STATE, action) => { |
||||||
|
switch (action.type){ |
||||||
|
|
||||||
|
case CartActionTypes.TOGGLE_CART_HIDDEN: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
hidden: !state.hidden |
||||||
|
} |
||||||
|
|
||||||
|
case CartActionTypes.ADD_ITEM: |
||||||
|
return{ |
||||||
|
...state, |
||||||
|
cartItems: addItemsToCart(state.cartItems, action.payload ) |
||||||
|
} |
||||||
|
|
||||||
|
case CartActionTypes.REMOVE_ITEM: |
||||||
|
return{ |
||||||
|
...state, |
||||||
|
cartItems: removeItemFromCart(state.cartItems, action.payload) |
||||||
|
} |
||||||
|
|
||||||
|
case CartActionTypes.CLEAR_ITEM_FROM_CART: |
||||||
|
return{ |
||||||
|
...state, |
||||||
|
cartItems: state.cartItems.filter( |
||||||
|
cartItem => cartItem.id !== action.payload.id |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default cartReducer; |
@ -0,0 +1,34 @@ |
|||||||
|
import { createSelector } from 'reselect'; |
||||||
|
|
||||||
|
const selectCart = state => state.cart; |
||||||
|
|
||||||
|
export const selectCartItems = createSelector( |
||||||
|
[selectCart], |
||||||
|
cart => cart.cartItems |
||||||
|
) |
||||||
|
|
||||||
|
export const selectCartHidden = createSelector( |
||||||
|
[selectCart], |
||||||
|
cart => cart.hidden |
||||||
|
) |
||||||
|
|
||||||
|
export const selectCartItemsCount = createSelector( |
||||||
|
[selectCartItems], |
||||||
|
cartItems => |
||||||
|
cartItems.reduce( |
||||||
|
(accumulatedQuantity, cartItem) => |
||||||
|
accumulatedQuantity + cartItem.quantity, |
||||||
|
0 |
||||||
|
) |
||||||
|
) |
||||||
|
|
||||||
|
export const selectCartTotal = createSelector( |
||||||
|
[selectCartItems], |
||||||
|
cartItems => |
||||||
|
cartItems.reduce( |
||||||
|
(accumulatedQuantity, cartItem) => |
||||||
|
accumulatedQuantity + cartItem.quantity * cartItem.price, |
||||||
|
0 |
||||||
|
) |
||||||
|
|
||||||
|
) |
@ -0,0 +1,31 @@ |
|||||||
|
export const addItemsToCart = (cartItems, cartItemToAdd) => { |
||||||
|
const existingCartItem = cartItems.find( |
||||||
|
cartItem => cartItem.id === cartItemToAdd.id
|
||||||
|
) |
||||||
|
|
||||||
|
if(existingCartItem){ |
||||||
|
return cartItems.map(cartItem => |
||||||
|
cartItem.id === cartItemToAdd.id |
||||||
|
? { ...cartItem, quantity: cartItem.quantity + 1 } |
||||||
|
: cartItem |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
return [...cartItems, { ...cartItemToAdd, quantity: 1 }] |
||||||
|
} |
||||||
|
|
||||||
|
export const removeItemFromCart = (cartItems, cartItemToRemove) => { |
||||||
|
const existingCartItem = cartItems.find( |
||||||
|
cartItem => cartItem.id === cartItemToRemove.id |
||||||
|
) |
||||||
|
|
||||||
|
if(existingCartItem.quantity === 1){ |
||||||
|
return cartItems.filter(cartItem => cartItem.id !== cartItemToRemove.id) |
||||||
|
} |
||||||
|
|
||||||
|
return cartItems.map(cartItem => |
||||||
|
cartItem.id === cartItemToRemove.id |
||||||
|
? {...cartItem, quantity: cartItem.quantity -1 } |
||||||
|
:cartItem |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
const INITIAL_STATE = { |
||||||
|
sections: [ |
||||||
|
{ |
||||||
|
title: "موس (موشواره)", |
||||||
|
imageUrl: "https://www.pngkey.com/png/full/957-9575055_redragon-m908-impact-mmo-gaming-mouse-up-to.png", |
||||||
|
id: 1, |
||||||
|
linkUrl: "shop/hats" |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "کیبورد", |
||||||
|
imageUrl: "https://www.pngplay.com/wp-content/uploads/13/Gaming-Keyboard-Transparent-Free-PNG.png", |
||||||
|
id: 2, |
||||||
|
linkUrl: "shop/jackets" |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "وبکم", |
||||||
|
imageUrl: "https://www.pngkey.com/png/full/246-2465497_webcam-transparent-images-trust-exis-webcam-17003.png", |
||||||
|
id: 3, |
||||||
|
linkUrl: "shop/sneakers" |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "اسپیکر", |
||||||
|
imageUrl: "https://www.pngarts.com/files/12/Portable-Bluetooth-Speaker-Transparent-Images.png", |
||||||
|
size: "large", |
||||||
|
id: 4, |
||||||
|
linkUrl: "shop/womens" |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "مانیتور", |
||||||
|
imageUrl: "https://static.acer.com/up/Resource/Acer/Monitors/BE0/Image/20160503/BE240Y_sku_preview.png", |
||||||
|
size: "large", |
||||||
|
id: 5, |
||||||
|
linkUrl: "shop/mens" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
const directoryReducer = (state = INITIAL_STATE, action) => { |
||||||
|
switch(action.type){ |
||||||
|
default: |
||||||
|
return state |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default directoryReducer |
@ -0,0 +1,8 @@ |
|||||||
|
import { createSelector } from 'reselect' |
||||||
|
|
||||||
|
const selectDirectory = state => state.directory |
||||||
|
|
||||||
|
export const selectDirectorySections = createSelector( |
||||||
|
[selectDirectory], |
||||||
|
directory => directory.sections |
||||||
|
) |
@ -0,0 +1,7 @@ |
|||||||
|
// @create-index
|
||||||
|
|
||||||
|
export { default as actions } from './actions'; |
||||||
|
export { default as proxy } from './proxy.js'; |
||||||
|
export { default as reducers } from './reducers'; |
||||||
|
export { default as store } from './store.js'; |
||||||
|
|
@ -0,0 +1,120 @@ |
|||||||
|
import { ApiConfig } from "../constants/defaultValues"; |
||||||
|
import axios from "axios"; |
||||||
|
|
||||||
|
let { baseUrl } = ApiConfig; |
||||||
|
let access = window.localStorage.getItem("access"); |
||||||
|
baseUrl = baseUrl + "/"; |
||||||
|
|
||||||
|
const Axios = axios.create({ |
||||||
|
withCredentials: true, |
||||||
|
validateStatus: null, |
||||||
|
baseURL: baseUrl, |
||||||
|
//headers: access ? { Authorization: `Bearer ${access}` } : {},
|
||||||
|
}); |
||||||
|
class Proxy { |
||||||
|
get = async (url, params, opt, data) => |
||||||
|
await this.check( |
||||||
|
url, |
||||||
|
opt, |
||||||
|
async () => await Axios.get(url, { params, ...opt }), |
||||||
|
data || params |
||||||
|
); |
||||||
|
post = async (url, params, opt, data ) => |
||||||
|
await this.check( |
||||||
|
url, |
||||||
|
opt, |
||||||
|
async () => await Axios.post(url, params, opt), |
||||||
|
data || params |
||||||
|
); |
||||||
|
put = async (url , params , opt , data ) => |
||||||
|
await this.check( |
||||||
|
url, |
||||||
|
opt, |
||||||
|
async () => await Axios.put(url, params, opt), |
||||||
|
data || params |
||||||
|
); |
||||||
|
delete = async (url , params , opt , data ) => { |
||||||
|
await this.check( |
||||||
|
url, |
||||||
|
opt, |
||||||
|
async () => await Axios.delete(url, { ...opt, data: params }), |
||||||
|
data || params |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
check = async (url , { dispatch } , fetch , params ) => { |
||||||
|
dispatch = dispatch || (() => {}); |
||||||
|
dispatch({ type: url.split("/")[0] + "/" + "loading" }); |
||||||
|
let response = await fetch(); |
||||||
|
switch (response.status) { |
||||||
|
case 200: |
||||||
|
dispatch({ type: url, data: response.data.data, params }); |
||||||
|
return response.data.data; |
||||||
|
case 401: |
||||||
|
if (await this.refresh()) { |
||||||
|
let response = await fetch(); |
||||||
|
dispatch({ type: url, data: response.data.data, params }); |
||||||
|
return response.data.data; |
||||||
|
} |
||||||
|
break; |
||||||
|
default: |
||||||
|
dispatch({ |
||||||
|
type: url.split("/")[0] + "/" + "error", |
||||||
|
data: response.data, |
||||||
|
params, |
||||||
|
}); |
||||||
|
} |
||||||
|
return false; |
||||||
|
}; |
||||||
|
|
||||||
|
refresh = async () => { |
||||||
|
let refresh = localStorage.getItem("refresh"); |
||||||
|
if (!refresh) window.location.href = "/"; |
||||||
|
let login = await this.login( |
||||||
|
"user/login", |
||||||
|
{}, |
||||||
|
{ headers: { Authorization: `Bearer ${refresh}` } } |
||||||
|
); |
||||||
|
return login ? true : false; |
||||||
|
}; |
||||||
|
login = async (url , params , { dispatch } ) => |
||||||
|
this.post(url, params, { |
||||||
|
dispatch: (obj ) => { |
||||||
|
let login = obj.data; |
||||||
|
if (!login || !login.refreshToken) return false; |
||||||
|
localStorage.setItem("refresh", login.refreshToken); |
||||||
|
localStorage.setItem("access", login.accessToken); |
||||||
|
delete login.refreshToken; |
||||||
|
delete login.accessToken; |
||||||
|
localStorage.setItem("userData", JSON.stringify(login.profile)); |
||||||
|
dispatch(obj); |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
logout = async (url , params , { dispatch } ) => { |
||||||
|
this.post(url, params, { |
||||||
|
dispatch: (obj ) => { |
||||||
|
localStorage.removeItem("refresh"); |
||||||
|
localStorage.removeItem("access"); |
||||||
|
localStorage.removeItem("userData"); |
||||||
|
dispatch(obj); |
||||||
|
}, |
||||||
|
}); |
||||||
|
}; |
||||||
|
status = () => { |
||||||
|
let refresh = localStorage.getItem("refresh"); |
||||||
|
let userData = localStorage.getItem("userData"); |
||||||
|
if (!refresh) return false; |
||||||
|
if (refresh == "undefined") { |
||||||
|
localStorage.removeItem("refresh"); |
||||||
|
localStorage.removeItem("access"); |
||||||
|
localStorage.removeItem("userData"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return JSON.parse(userData || ''); |
||||||
|
}; |
||||||
|
} |
||||||
|
const _proxy = new Proxy(); |
||||||
|
|
||||||
|
export default _proxy; |
@ -0,0 +1,28 @@ |
|||||||
|
import { toast } from "react-toastify"; |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: [], |
||||||
|
}; |
||||||
|
export default function blog(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "public/blogList": |
||||||
|
return { ...state, loading: false, list: data, error: null }; |
||||||
|
// case "blog/update":
|
||||||
|
// return { ...state, loading: false, error: null };
|
||||||
|
// case "blog/add":
|
||||||
|
// return { ...state, loading: false, error: null };
|
||||||
|
// case "blog/delete":
|
||||||
|
// return { ...state, loading: false, error: null };
|
||||||
|
/////////////
|
||||||
|
case "blog/loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "blog/error": |
||||||
|
toast.error(data.message); |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
import { toast } from "react-toastify"; |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: [], |
||||||
|
searchResult: [], |
||||||
|
search: null, |
||||||
|
}; |
||||||
|
export default function faq(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "faq/list": |
||||||
|
return { ...state, loading: false, list: data, error: null }; |
||||||
|
case "faq/add": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "faq/selectFaq": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: !state.search |
||||||
|
? state.list.map((item) => |
||||||
|
item.id === data |
||||||
|
? { ...item, active: !item.active } |
||||||
|
: { ...item, active: false } |
||||||
|
) |
||||||
|
: state.list, |
||||||
|
searchResult: state.search |
||||||
|
? state.searchResult.map((item) => |
||||||
|
item.id === data |
||||||
|
? { ...item, active: !item.active } |
||||||
|
: { ...item, active: false } |
||||||
|
) |
||||||
|
: state.searchResult, |
||||||
|
}; |
||||||
|
case "faq/search": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
search: data, |
||||||
|
searchResult: state.list.filter( |
||||||
|
(item) => |
||||||
|
item.title.indexOf(data) !== -1 || |
||||||
|
item.description.indexOf(data) !== -1 |
||||||
|
), |
||||||
|
}; |
||||||
|
case "faq/loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "faq/error": |
||||||
|
toast.error(data.message); |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
uploads: {}, |
||||||
|
lastUpload: null, |
||||||
|
}; |
||||||
|
|
||||||
|
export default function file(state = initialState, action) { |
||||||
|
let { type, data, params } = action; |
||||||
|
switch (type) { |
||||||
|
case "file/upload": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
uploads: { ...state.uploads, [params?.target || "last"]: data.id }, |
||||||
|
lastUpload: data.id, |
||||||
|
}; |
||||||
|
case "file/loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "file/error": |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
// @create-index
|
||||||
|
export { default as publicApi } from "./public"; |
||||||
|
export { default as user } from "./user"; |
||||||
|
export { default as book } from "./book"; |
||||||
|
export { default as blog } from "./blog"; |
||||||
|
export { default as product } from "./product"; |
||||||
|
export { default as faq } from "./faq"; |
||||||
|
export { default as file } from "./file"; |
||||||
|
export { default as userFactor } from "./userFactor"; |
||||||
|
export { default as userProduct } from "./userProduct"; |
||||||
|
export {default as scrollAction} from "./scroll"; |
||||||
|
export {default as qr} from "./qr"; |
@ -0,0 +1,31 @@ |
|||||||
|
import { toast } from "react-toastify"; |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
listVOD: [], |
||||||
|
selectedVOD: null, |
||||||
|
similarList : [], |
||||||
|
}; |
||||||
|
export default function product(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "product/listVOD": |
||||||
|
return { ...state, loading: false, listVOD: data, error: null }; |
||||||
|
case "product/similar": |
||||||
|
return { ...state, loading: false, similarList: data, error: null }; |
||||||
|
case "product/addVOD": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "product/deleteVOD": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "product/selectVOD": |
||||||
|
return { ...state, selectedVOD: data }; |
||||||
|
case "product/loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "product/error": |
||||||
|
toast.error(data.message); |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: null, |
||||||
|
}; |
||||||
|
export default function qr(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "qr/list": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "qr/update": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "qr/add": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "qr/delete": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "qr/info": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
list: data, |
||||||
|
error: null, |
||||||
|
}; |
||||||
|
/////////////
|
||||||
|
case "loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "error": |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,185 @@ |
|||||||
|
import scroll from "../../utils/scroll"; |
||||||
|
const height = window.innerHeight; |
||||||
|
const width = window.innerWidth; |
||||||
|
const prevScroll = localStorage.getItem("prevScroll"); |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
page1TopPosition: scroll.homeScrollHandler(1), |
||||||
|
page2TopPosition: scroll.homeScrollHandler(2), |
||||||
|
page2RotateX: scroll.linearFormula( |
||||||
|
scroll.linearFormula( |
||||||
|
prevScroll > height ? height : prevScroll, |
||||||
|
45, |
||||||
|
0, |
||||||
|
0, |
||||||
|
height |
||||||
|
) |
||||||
|
), |
||||||
|
page2BoxPosition: scroll.initializeBoxPosition(prevScroll), |
||||||
|
page2MobilePosition: scroll.linearFormula( |
||||||
|
prevScroll > 2.5 * height ? 2.5 * height : prevScroll, |
||||||
|
-(((height * 10) / 20 / width) * 100), |
||||||
|
6, |
||||||
|
2 * height, |
||||||
|
2.5 * height |
||||||
|
), |
||||||
|
page2VideoPosition: |
||||||
|
window.scrollY > 4 * height |
||||||
|
? scroll.videoLinearFormula(4 * height) |
||||||
|
: window.scrollY > height |
||||||
|
? scroll.videoLinearFormula(window.scrollY) |
||||||
|
: null, |
||||||
|
page2VideoTopPosition: |
||||||
|
prevScroll > 3 * height |
||||||
|
? scroll.linearFormula(3 * height, 70, 50, 2.8 * height, 3 * height) |
||||||
|
: scroll.linearFormula(prevScroll, 70, 50, 2.8 * height, 3 * height), |
||||||
|
page2MobileUnit: scroll.initializeMobileUnit(prevScroll), |
||||||
|
videoTubeTopPosition: scroll.homeScrollHandler(3), |
||||||
|
testTranslateY: scroll.linearFormula( |
||||||
|
prevScroll > 5 * window.innerHeight ? 5 * window.innerHeight : prevScroll, |
||||||
|
0, |
||||||
|
-101, |
||||||
|
4.5 * height, |
||||||
|
5 * height |
||||||
|
), |
||||||
|
page3TopPosition: scroll.homeScrollHandler(4), |
||||||
|
page3TestTranslateY: |
||||||
|
prevScroll < 6.3 * height |
||||||
|
? 0 |
||||||
|
: scroll.linearFormula( |
||||||
|
prevScroll > 7 * height ? 7 * height : prevScroll, |
||||||
|
0, |
||||||
|
100, |
||||||
|
6.3 * height, |
||||||
|
7 * height |
||||||
|
), |
||||||
|
page4TopPosition: scroll.homeScrollHandler(5), |
||||||
|
}; |
||||||
|
|
||||||
|
export default function scrollAction(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "scroll/page1/floatMouse": |
||||||
|
return { ...state, floatMouseToggle: data }; |
||||||
|
case "scroll/page1/top": |
||||||
|
return { ...state, page1TopPosition: scroll.homeScrollHandler(1) }; |
||||||
|
case "scroll/page2/top": |
||||||
|
return { ...state, page2TopPosition: scroll.homeScrollHandler(2) }; |
||||||
|
case "scroll/page2/rotateX": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page2RotateX: scroll.linearFormula(window.scrollY, 45, 0, 0, height), |
||||||
|
}; |
||||||
|
case "scroll/page2/boxPosition": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page2BoxPosition: { |
||||||
|
translateY: scroll.linearFormula( |
||||||
|
data.scrollY, |
||||||
|
data.translateY.pos1, |
||||||
|
data.translateY.pos2, |
||||||
|
data.start, |
||||||
|
data.end |
||||||
|
), |
||||||
|
translateX: scroll.linearFormula( |
||||||
|
data.scrollY, |
||||||
|
data.translateX.pos1, |
||||||
|
data.translateX.pos2, |
||||||
|
data.start, |
||||||
|
data.end |
||||||
|
), |
||||||
|
rotate: scroll.linearFormula( |
||||||
|
data.scrollY, |
||||||
|
data.rotate.pos1, |
||||||
|
data.rotate.pos2, |
||||||
|
data.start, |
||||||
|
data.end |
||||||
|
), |
||||||
|
}, |
||||||
|
page2TopPosition: 0, |
||||||
|
page2RotateX: 0, |
||||||
|
}; |
||||||
|
case "scroll/page2/mobilePosition": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page2MobilePosition: scroll.linearFormula( |
||||||
|
window.scrollY, |
||||||
|
-(((height * 10) / 20 / width) * 100), |
||||||
|
6, |
||||||
|
2 * height, |
||||||
|
2.5 * height |
||||||
|
), |
||||||
|
page2BoxPosition: { translateX: 32, translateY: 10, rotate: 0 }, |
||||||
|
}; |
||||||
|
case "scroll/page2/videoPosition": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page2VideoPosition: scroll.videoLinearFormula(window.scrollY), |
||||||
|
page2VideoTopPosition: 50, |
||||||
|
}; |
||||||
|
case "scroll/page2/videoTopPosition": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page2VideoTopPosition: scroll.linearFormula( |
||||||
|
window.scrollY, |
||||||
|
70, |
||||||
|
50, |
||||||
|
2.8 * height, |
||||||
|
3 * height |
||||||
|
), |
||||||
|
page2MobilePosition: 6, |
||||||
|
}; |
||||||
|
case "scroll/page2/mobileUnit": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page2MobileUnit: scroll.initializeMobileUnit(window.scrollY), |
||||||
|
}; |
||||||
|
case "scroll/videoTube/top": |
||||||
|
return { ...state, videoTubeTopPosition: scroll.homeScrollHandler(3) }; |
||||||
|
case "scroll/test/translateY": |
||||||
|
const joiRect = JSON.parse(localStorage.getItem("joiRect")); |
||||||
|
return { |
||||||
|
...state, |
||||||
|
testTranslateY: scroll.linearFormula( |
||||||
|
window.scrollY, |
||||||
|
0, |
||||||
|
-101, |
||||||
|
4.5 * height, |
||||||
|
5 * height |
||||||
|
), |
||||||
|
videoTubeTopPosition: 0, |
||||||
|
page2VideoPosition: { |
||||||
|
width: joiRect.width, |
||||||
|
height: joiRect.height, |
||||||
|
top: joiRect.top, |
||||||
|
left: joiRect.left, |
||||||
|
}, |
||||||
|
}; |
||||||
|
case "scroll/page3/top": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page3TopPosition: scroll.homeScrollHandler(4), |
||||||
|
testTranslateY: -101, |
||||||
|
}; |
||||||
|
case "scroll/page3/testTranslateY": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page3TestTranslateY: scroll.linearFormula( |
||||||
|
window.scrollY, |
||||||
|
0, |
||||||
|
100, |
||||||
|
6.3 * height, |
||||||
|
7 * height |
||||||
|
), |
||||||
|
page3TopPosition: 0, |
||||||
|
}; |
||||||
|
case "scroll/page4/top": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
page4TopPosition: scroll.homeScrollHandler(5), |
||||||
|
page3TestTranslateY: 100, |
||||||
|
}; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
import { toast } from "react-toastify"; |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
status: proxy.status(), |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: null, |
||||||
|
domains: [], |
||||||
|
mothers: [], |
||||||
|
profileStatus: false, |
||||||
|
setDone: false, |
||||||
|
setLogin : false,
|
||||||
|
}; |
||||||
|
export default function user(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
// case "user/login":
|
||||||
|
// case "user/register":
|
||||||
|
// case "user/switchRole":
|
||||||
|
case "public/sendOTP": |
||||||
|
return { ...state, loading: false, status: data.profile, error: null }; |
||||||
|
case "user/login": |
||||||
|
case "user/otp/login": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
status: data.profile, |
||||||
|
error: null, |
||||||
|
setLogin: !state.setLogin, |
||||||
|
}; |
||||||
|
case "user/getProfile": |
||||||
|
localStorage.setItem("userData", JSON.stringify(data)); |
||||||
|
return { ...state, loading: false, status: data, error: null, setDone : false, }; |
||||||
|
case "user/logout": |
||||||
|
return { ...state, loading: false, status: proxy.status(), error: null }; |
||||||
|
case "user/getUserRole": |
||||||
|
return { ...state, loading: false, userRoles: data, error: null }; |
||||||
|
case "user/setProfile": |
||||||
|
toast.success("تغییرات اعمال شد."); |
||||||
|
return { ...state, loading: false, error: null, setDone : true }; |
||||||
|
case "loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "error": |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
import { toast } from "react-toastify"; |
||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: null, |
||||||
|
info: null, |
||||||
|
sum: null, |
||||||
|
checkEmpty: false, |
||||||
|
isVerified: null, |
||||||
|
}; |
||||||
|
export default function userFactor(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
//dnvn
|
||||||
|
case "userFactor/list": |
||||||
|
const checkEmpty = data.filter( |
||||||
|
(item) => item.condition === 2 && item.product.productType === (1 || 3) |
||||||
|
); |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
list: data, |
||||||
|
checkEmpty: checkEmpty.length > 0 ? false : true, |
||||||
|
error: null, |
||||||
|
}; |
||||||
|
case "userFactor/info": |
||||||
|
return { ...state, loading: false, info: data, error: null }; |
||||||
|
case "userFactor/add": |
||||||
|
toast.success("درخواست شما با موفقیت انجام شد."); |
||||||
|
return { ...state, loading: false, error: null, sum: data.payPrice }; |
||||||
|
case "userFactor/delete": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "userFactor/payment": |
||||||
|
window.location.replace(data); |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
//vod
|
||||||
|
case "userFactor/myList": |
||||||
|
return { ...state, loading: false, list: data, error: null }; |
||||||
|
case "userFactor/update": |
||||||
|
toast.success("درخواست شما با موفقیت انجام شد."); |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "userFactor/deleteUserOffCode": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "userFactor/paymentVOD": |
||||||
|
window.location.replace(data); |
||||||
|
return { ...state, loading: false, error: null, isVerified: false }; |
||||||
|
case "userFactor/verifyVOD": |
||||||
|
return { ...state, loading: false, error: null, isVerified: true }; |
||||||
|
case "userFactor/loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "userFactor/error": |
||||||
|
toast.error(data.message); |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
import { toast } from "react-toastify"; |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: [], |
||||||
|
info: null, |
||||||
|
sum: null, |
||||||
|
checkEmpty: false, |
||||||
|
hasPhysical: false, |
||||||
|
}; |
||||||
|
export default function userFactor(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "userProduct/list": |
||||||
|
const checkEmpty = data.filter( |
||||||
|
(item) => item.condition === 2 && item.product.productType === (1 || 3) |
||||||
|
); |
||||||
|
const hasPhysical = |
||||||
|
data.filter((item) => item.product.productType === 2).length > 0 |
||||||
|
? true |
||||||
|
: false; |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
list: data, |
||||||
|
checkEmpty: checkEmpty.length > 0 ? false : true, |
||||||
|
error: null, |
||||||
|
hasPhysical: hasPhysical, |
||||||
|
}; |
||||||
|
case "userProduct/info": |
||||||
|
return { ...state, loading: false, info: data, error: null }; |
||||||
|
case "userProduct/update": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "userProduct/add": |
||||||
|
if (window.location.pathname.indexOf("products") !== -1) { |
||||||
|
toast.success("درخواست شما با موفقیت انجام شد."); |
||||||
|
} |
||||||
|
return { ...state, loading: false, error: null, sum: data.payPrice }; |
||||||
|
case "userProduct/delete": |
||||||
|
return { ...state, loading: false, error: null }; |
||||||
|
case "userProduct/loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "userProduct/error": |
||||||
|
toast.error(data.message); |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
import { combineReducers } from 'redux' |
||||||
|
import { persistReducer } from 'redux-persist' |
||||||
|
import storage from 'redux-persist/lib/storage' |
||||||
|
|
||||||
|
import userReducer from './user/user.reducer.js' |
||||||
|
import cartReducer from './cart/cart.reducer.js' |
||||||
|
import directoryReducer from './directory/directory.reducer' |
||||||
|
import shopReducer from './shop/shop.reducer' |
||||||
|
|
||||||
|
|
||||||
|
const persistConfig = { |
||||||
|
key: 'root', |
||||||
|
storage, |
||||||
|
whitelist: ['cart'] |
||||||
|
} |
||||||
|
|
||||||
|
const rootReducer = combineReducers({ |
||||||
|
user: userReducer, |
||||||
|
cart: cartReducer, |
||||||
|
directory: directoryReducer, |
||||||
|
shop: shopReducer, |
||||||
|
}) |
||||||
|
|
||||||
|
export default persistReducer(persistConfig, rootReducer) |
@ -0,0 +1,254 @@ |
|||||||
|
const SHOP_DATA = [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
title: "mouse", |
||||||
|
routeName: "mouse", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: "ماوس ریزر مدل DEATHADDER ESSENTIAL RZ01", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/114510799.jpg", |
||||||
|
price: 73000, |
||||||
|
adress: '/products/razor-mouse-deathadder-rz01', |
||||||
|
description: { |
||||||
|
content: 'لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.', |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
name: "ماوس مخصوص بازی مدل V8", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/eddb26c7043d4092e17ba4e05a19f5b49f20f0dc_1633724598.jpg", |
||||||
|
price: 290000 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 3, |
||||||
|
name: "ماوس مخصوص بازی زویا مدل MMR1", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/2c9f4388ced87e860a9c9d0fccc595f3b64a55a2_1610015683.jpg", |
||||||
|
price: 210000 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 4, |
||||||
|
name: "ماوس مخصوص بازی تسکو مدل TSCO TM 764 GA", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/d0cc25319e2fce02acb42f679ff282b59182ed54_1597813753.jpg", |
||||||
|
price: 186000 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 5, |
||||||
|
name: "ماوس مخصوص بازی مدل GM02", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/33b0985d01fe4b1ec2542bd03f3b7998e68981ed_1636141537.jpg", |
||||||
|
price: 297270 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 6, |
||||||
|
name: "ماوس بی سیم ریزر مدل Basilisk Ultimate", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/81ad2dd69067d43c967ed76faf928837629ece45_1630752955.jpg", |
||||||
|
price: 5250000 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 7, |
||||||
|
name: "ماوس مخصوص بازی ریزر مدل Viper Mini", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/878005cff2b58c0d0d0ac4e9ca7eaa21d3987c2c_1600681192.jpg", |
||||||
|
price: 1460000 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 8, |
||||||
|
name: "ماوس تسکو مدل TM 291", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/27e2b2852f53615b577fc9130b97675cb77067ba_1628667044.jpg", |
||||||
|
price: 83800 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 9, |
||||||
|
name: "ماوس آرمو مدل M25", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/4b757355ca6dcae804f34d4c6af66305903b379c_1596460030.jpg", |
||||||
|
price: 160000 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
title: "وبکم", |
||||||
|
routeName: "webcam", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: 10, |
||||||
|
name: "وب کم ایکس اچ سی مدل 48O", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/6f167d1f3b0aa40e19760d5f5240912e00e31dc9_1632987698.jpg", |
||||||
|
price: '340,000' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 11, |
||||||
|
name: "وب کم مدل PGR-008", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/3fa4c49aed640c53560fd32a117c7685923123db_1615139913.jpg", |
||||||
|
price: '2,070,000' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 12, |
||||||
|
name: "وب کم مایکروسافت مدل لایف کم سینما", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/32558.jpg", |
||||||
|
price: 110 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 13, |
||||||
|
name: "وب کم ای فورتک مدل PK-635G", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/2190153c71b9fd3ba9f191f23fa767d8b2cd9200_1601221909.jpg", |
||||||
|
price: '630,000' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 14, |
||||||
|
name: "وب کم HD مایکروسافت مدل لایف کم HD-3000", |
||||||
|
imageUrl: "https://dkstatics-public.digikala.com/digikala-products/15382.jpg", |
||||||
|
price: '1,300,000' |
||||||
|
}, |
||||||
|
// {
|
||||||
|
// id: 15,
|
||||||
|
// name: "Nike Brown High Tops",
|
||||||
|
// imageUrl: "https://i.ibb.co/fMTV342/nike-brown.png",
|
||||||
|
// price: 160
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: 16,
|
||||||
|
// name: "Air Jordan Limited",
|
||||||
|
// imageUrl: "https://i.ibb.co/w4k6Ws9/nike-funky.png",
|
||||||
|
// price: 190
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: 17,
|
||||||
|
// name: "Timberlands",
|
||||||
|
// imageUrl: "https://i.ibb.co/Mhh6wBg/timberlands.png",
|
||||||
|
// price: 200
|
||||||
|
// }
|
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 3, |
||||||
|
title: "Jackets", |
||||||
|
routeName: "jackets", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: 18, |
||||||
|
name: "Black Jean Shearling", |
||||||
|
imageUrl: "https://i.ibb.co/XzcwL5s/black-shearling.png", |
||||||
|
price: 125 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 19, |
||||||
|
name: "Blue Jean Jacket", |
||||||
|
imageUrl: "https://i.ibb.co/mJS6vz0/blue-jean-jacket.png", |
||||||
|
price: 90 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 20, |
||||||
|
name: "Grey Jean Jacket", |
||||||
|
imageUrl: "https://i.ibb.co/N71k1ML/grey-jean-jacket.png", |
||||||
|
price: 90 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 21, |
||||||
|
name: "Brown Shearling", |
||||||
|
imageUrl: "https://i.ibb.co/s96FpdP/brown-shearling.png", |
||||||
|
price: 165 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 22, |
||||||
|
name: "Tan Trench", |
||||||
|
imageUrl: "https://i.ibb.co/M6hHc3F/brown-trench.png", |
||||||
|
price: 185 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 4, |
||||||
|
title: "Womens", |
||||||
|
routeName: "womens", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: 23, |
||||||
|
name: "Blue Tanktop", |
||||||
|
imageUrl: "https://i.ibb.co/7CQVJNm/blue-tank.png", |
||||||
|
price: 25 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 24, |
||||||
|
name: "Floral Blouse", |
||||||
|
imageUrl: "https://i.ibb.co/4W2DGKm/floral-blouse.png", |
||||||
|
price: 20 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 25, |
||||||
|
name: "Floral Dress", |
||||||
|
imageUrl: "https://i.ibb.co/KV18Ysr/floral-skirt.png", |
||||||
|
price: 80 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 26, |
||||||
|
name: "Red Dots Dress", |
||||||
|
imageUrl: "https://i.ibb.co/N3BN1bh/red-polka-dot-dress.png", |
||||||
|
price: 80 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 27, |
||||||
|
name: "Striped Sweater", |
||||||
|
imageUrl: "https://i.ibb.co/KmSkMbH/striped-sweater.png", |
||||||
|
price: 45 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 28, |
||||||
|
name: "Yellow Track Suit", |
||||||
|
imageUrl: "https://i.ibb.co/v1cvwNf/yellow-track-suit.png", |
||||||
|
price: 135 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 29, |
||||||
|
name: "White Blouse", |
||||||
|
imageUrl: "https://i.ibb.co/qBcrsJg/white-vest.png", |
||||||
|
price: 20 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 5, |
||||||
|
title: "Mens", |
||||||
|
routeName: "mens", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
id: 30, |
||||||
|
name: "Camo Down Vest", |
||||||
|
imageUrl: "https://i.ibb.co/xJS0T3Y/camo-vest.png", |
||||||
|
price: 325 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 31, |
||||||
|
name: "Floral T-shirt", |
||||||
|
imageUrl: "https://i.ibb.co/qMQ75QZ/floral-shirt.png", |
||||||
|
price: 20 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 32, |
||||||
|
name: "Black & White Longsleeve", |
||||||
|
imageUrl: "https://i.ibb.co/55z32tw/long-sleeve.png", |
||||||
|
price: 25 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 33, |
||||||
|
name: "Pink T-shirt", |
||||||
|
imageUrl: "https://i.ibb.co/RvwnBL8/pink-shirt.png", |
||||||
|
price: 25 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 34, |
||||||
|
name: "Jean Long Sleeve", |
||||||
|
imageUrl: "https://i.ibb.co/VpW4x5t/roll-up-jean-shirt.png", |
||||||
|
price: 40 |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 35, |
||||||
|
name: "Burgundy T-shirt", |
||||||
|
imageUrl: "https://i.ibb.co/mh3VM1f/polka-dot-shirt.png", |
||||||
|
price: 25 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
]; |
||||||
|
|
||||||
|
export default SHOP_DATA; |
||||||
|
|
@ -0,0 +1,14 @@ |
|||||||
|
import SHOP_DATA from './shop.data'; |
||||||
|
|
||||||
|
const INITIAL_STATE = { |
||||||
|
collections: SHOP_DATA |
||||||
|
}; |
||||||
|
|
||||||
|
const shopReducer = (state = INITIAL_STATE, action) => { |
||||||
|
switch (action.type) { |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default shopReducer; |
@ -0,0 +1,8 @@ |
|||||||
|
import { createSelector } from 'reselect' |
||||||
|
|
||||||
|
const selectShop = state => state.shop |
||||||
|
|
||||||
|
export const selectCollections = createSelector( |
||||||
|
[selectShop], |
||||||
|
shop => shop.collections |
||||||
|
); |
@ -0,0 +1,14 @@ |
|||||||
|
import { createStore, applyMiddleware } from 'redux'; |
||||||
|
import { composeWithDevTools } from 'redux-devtools-extension'; |
||||||
|
import { combineReducers } from 'redux'; |
||||||
|
import * as reducers from './reducers'; |
||||||
|
import thunk from 'redux-thunk'; |
||||||
|
const initialState = {}; |
||||||
|
const middleware = [thunk]; |
||||||
|
const store = createStore( |
||||||
|
combineReducers(reducers), |
||||||
|
initialState, |
||||||
|
composeWithDevTools(applyMiddleware(...middleware)) |
||||||
|
); |
||||||
|
export default store; |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
import { UserActionTypes } from './user.types.js' |
||||||
|
|
||||||
|
export const setCurrentUser = user => ({ |
||||||
|
type: UserActionTypes.SET_CURRENT_USER, |
||||||
|
payload: user |
||||||
|
}) |
@ -0,0 +1,19 @@ |
|||||||
|
import { UserActionTypes } from './user.types.js' |
||||||
|
|
||||||
|
const INITIAL_STATE = { |
||||||
|
currentUser: null |
||||||
|
} |
||||||
|
|
||||||
|
const userReducer = (state = INITIAL_STATE, action ) => { |
||||||
|
switch(action.type){ |
||||||
|
case UserActionTypes.SET_CURRENT_USER: |
||||||
|
return{ |
||||||
|
...state, |
||||||
|
currentUser: action.payload |
||||||
|
} |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default userReducer; |
@ -0,0 +1,9 @@ |
|||||||
|
import { createSelector } from 'reselect'; |
||||||
|
|
||||||
|
const selectUser = state => state.user; |
||||||
|
|
||||||
|
export const selectCurrentUser = createSelector( |
||||||
|
[selectUser], |
||||||
|
user => user.currentUser |
||||||
|
) |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
export const UserActionTypes = { |
||||||
|
SET_CURRENT_USER: "SET_CURRENT_USER" |
||||||
|
}; |
@ -0,0 +1,22 @@ |
|||||||
|
export const connectToParent = (list) => { |
||||||
|
let comments = []; |
||||||
|
for (let item of list) { |
||||||
|
comments.push({ ...item, child: [] }); |
||||||
|
} |
||||||
|
|
||||||
|
for (let comment1 of comments) { |
||||||
|
if (comment1.pid !== null) { |
||||||
|
const index = comments.indexOf( |
||||||
|
comments.filter((comment2) => comment2.id === comment1.pid)[0] |
||||||
|
); |
||||||
|
comments[index] = { |
||||||
|
...comments[index], |
||||||
|
child: [...comments[index].child, comment1], |
||||||
|
}; |
||||||
|
} else { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
// comments = comments.filter((comment) => comment.pid === null);
|
||||||
|
console.log(comments); |
||||||
|
}; |
@ -0,0 +1,11 @@ |
|||||||
|
|
||||||
|
class location { |
||||||
|
getId = () => { |
||||||
|
const pathname = window.location.pathname; |
||||||
|
return pathname.slice(pathname.lastIndexOf('/') + 1, pathname.length); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const _location = new location(); |
||||||
|
|
||||||
|
export default _location; |
@ -0,0 +1,213 @@ |
|||||||
|
class scroll { |
||||||
|
goToTop = () => { |
||||||
|
window.scrollTo(0, 0); |
||||||
|
}; |
||||||
|
|
||||||
|
homeScrollHandler = (index) => { |
||||||
|
const prevScroll = Number(localStorage.getItem('prevScroll')); |
||||||
|
const height = Number(window.innerHeight); |
||||||
|
const scrollY = Number(window.scrollY); |
||||||
|
if (index === 1) { |
||||||
|
if (scrollY === 0) { |
||||||
|
return 0; |
||||||
|
}else |
||||||
|
if (scrollY > 0 && scrollY <= height) { |
||||||
|
return -scrollY; |
||||||
|
} |
||||||
|
if (scrollY > height) { |
||||||
|
return -height; |
||||||
|
} |
||||||
|
} else if (index === 2) { |
||||||
|
if (scrollY === 0) { |
||||||
|
return height; |
||||||
|
} |
||||||
|
if (scrollY > 0 && scrollY <= height) { |
||||||
|
return height - scrollY; |
||||||
|
} |
||||||
|
if (scrollY > 10 * height) { |
||||||
|
return -1 * height; |
||||||
|
} |
||||||
|
} else if (index === 3) { |
||||||
|
if (scrollY <= 3.5 * height) { |
||||||
|
return height; |
||||||
|
} |
||||||
|
if (scrollY > 3.5 * height && scrollY <= 4 * height) { |
||||||
|
return 4 * height - scrollY; |
||||||
|
} |
||||||
|
if (scrollY > 10 * height) { |
||||||
|
return -height; |
||||||
|
} |
||||||
|
} else if (index === 4) { |
||||||
|
if (scrollY <= 5 * height) { |
||||||
|
return height; |
||||||
|
} else if (scrollY > 5 * height && scrollY < 6 * height) { |
||||||
|
return 6 * height - scrollY; |
||||||
|
} |
||||||
|
if (scrollY === 10 * height) { |
||||||
|
return -height; |
||||||
|
} |
||||||
|
} else if (index === 5) { |
||||||
|
if (scrollY <= 7.3 * height) { |
||||||
|
return height; |
||||||
|
} else if (scrollY > 7.3 * height && scrollY < 8.3 * height) { |
||||||
|
return 8.3 * height - scrollY; |
||||||
|
} |
||||||
|
if (scrollY === 10 * height) { |
||||||
|
return -height; |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
linearFormula = (currentScroll, position1, position2, scroll1, scroll2) => { |
||||||
|
const alpha = (currentScroll - scroll1) / (scroll2 - scroll1); |
||||||
|
const deltaPosition = position2 - position1; |
||||||
|
const currentPosition = position1 + deltaPosition * alpha; |
||||||
|
return currentPosition; |
||||||
|
}; |
||||||
|
|
||||||
|
videoLinearFormula = (currentScroll) => { |
||||||
|
if (!localStorage.getItem("htmlRect")) { |
||||||
|
localStorage.setItem( |
||||||
|
"htmlRect", |
||||||
|
JSON.stringify(document.getElementById("video").getBoundingClientRect()) |
||||||
|
); |
||||||
|
} |
||||||
|
const htmlRect = |
||||||
|
JSON.parse(localStorage.getItem("htmlRect")) || |
||||||
|
document.getElementById("video").getBoundingClientRect(); |
||||||
|
const joiRect = JSON.parse(localStorage.getItem("joiRect")); |
||||||
|
|
||||||
|
const currentWidth = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
htmlRect.width, |
||||||
|
joiRect.width, |
||||||
|
3.5 * window.innerHeight, |
||||||
|
4 * window.innerHeight |
||||||
|
); |
||||||
|
const currentHeight = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
htmlRect.height, |
||||||
|
joiRect.height, |
||||||
|
3.5 * window.innerHeight, |
||||||
|
4 * window.innerHeight |
||||||
|
); |
||||||
|
const currentLeft = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
htmlRect.left, |
||||||
|
joiRect.left, |
||||||
|
3.5 * window.innerHeight, |
||||||
|
4 * window.innerHeight |
||||||
|
); |
||||||
|
|
||||||
|
const currentTop = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
htmlRect.top, |
||||||
|
joiRect.top - window.innerHeight, |
||||||
|
3.5 * window.innerHeight, |
||||||
|
4 * window.innerHeight |
||||||
|
); |
||||||
|
return { |
||||||
|
width: currentWidth, |
||||||
|
height: currentHeight, |
||||||
|
top: currentTop, |
||||||
|
left: currentLeft, |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
testLinearFolmula = (currentScroll) => { |
||||||
|
const testRect = JSON.parse(localStorage.getItem("testRect")); |
||||||
|
const currentWidth = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
testRect.width, |
||||||
|
window.innerWidth, |
||||||
|
4.5 * window.innerHeight, |
||||||
|
5 * window.innerHeight |
||||||
|
); |
||||||
|
const currentHeight = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
testRect.height, |
||||||
|
window.innerHeight, |
||||||
|
4.5 * window.innerHeight, |
||||||
|
5 * window.innerHeight |
||||||
|
); |
||||||
|
const currentLeft = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
testRect.left, |
||||||
|
0, |
||||||
|
4.5 * window.innerHeight, |
||||||
|
5 * window.innerHeight |
||||||
|
); |
||||||
|
|
||||||
|
const currentTop = this.linearFormula( |
||||||
|
currentScroll, |
||||||
|
testRect.top, |
||||||
|
0, |
||||||
|
4.5 * window.innerHeight, |
||||||
|
5 * window.innerHeight |
||||||
|
); |
||||||
|
|
||||||
|
return { |
||||||
|
width: currentWidth, |
||||||
|
height: currentHeight, |
||||||
|
top: currentTop, |
||||||
|
left: currentLeft, |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
initializeBoxPosition = (currentScroll) => { |
||||||
|
const height= window.innerHeight; |
||||||
|
if(currentScroll < height){ |
||||||
|
console.log(currentScroll); |
||||||
|
return { |
||||||
|
translateX: -5,
|
||||||
|
translateY: -5, |
||||||
|
rotate: 5 |
||||||
|
} |
||||||
|
} |
||||||
|
if(currentScroll > height && currentScroll < 2 * height){ |
||||||
|
return { |
||||||
|
translateX: this.linearFormula(currentScroll, -5, 32, height, 2 * height),
|
||||||
|
translateY: this.linearFormula(currentScroll, -5, 10, height, 2 * height), |
||||||
|
rotate: this.linearFormula(currentScroll, 5, 0, height, 2 * height) |
||||||
|
} |
||||||
|
} |
||||||
|
if(currentScroll > 2 * height && currentScroll <= 2.5 * height){ |
||||||
|
return { |
||||||
|
translateX: 32, |
||||||
|
translateY: 10, |
||||||
|
rotate: 0 |
||||||
|
} |
||||||
|
} |
||||||
|
if(currentScroll > 2.5 * height && currentScroll <= 3 * height){ |
||||||
|
return { |
||||||
|
translateX: this.linearFormula(currentScroll, 32, 32, 2.5 * height, 3 * height),
|
||||||
|
translateY: this.linearFormula(currentScroll, 10, -30, 2.5 * height, 3 * height), |
||||||
|
rotate: this.linearFormula(currentScroll, 0, 0, 2.5 * height, 3 * height) |
||||||
|
} |
||||||
|
} |
||||||
|
if(currentScroll > 3 * height){ |
||||||
|
return { |
||||||
|
translateX: 32, |
||||||
|
translateY: -30, |
||||||
|
rotate: 0 |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
initializeMobileUnit = (currentScroll) => { |
||||||
|
const height = window.innerHeight; |
||||||
|
if (currentScroll > 2 * height && currentScroll <= 2.3 * height) { |
||||||
|
return 1; |
||||||
|
} else if (currentScroll > 2.3 * height && currentScroll <= 2.7 * height) { |
||||||
|
return 2; |
||||||
|
} else if (currentScroll > 2.7 * height && currentScroll <= 2.8 * height) { |
||||||
|
return 3; |
||||||
|
} else if (currentScroll > 2.8 * height && currentScroll < 3.5 * height) { |
||||||
|
return 4; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const _scroll = new scroll(); |
||||||
|
|
||||||
|
export default _scroll; |
@ -1,18 +1,83 @@ |
|||||||
import React from "react"; |
import React, {useEffect, useState} from "react"; |
||||||
import Class from "../../components/products/classes"; |
import Class from "../../components/products/classes"; |
||||||
import PLATFORM_DATA from "../../store"; |
import { book, publicApi } from "../../redux/actions"; |
||||||
const Services = () => { |
import { connect } from 'react-redux'; |
||||||
|
import { Link } from "react-router-dom"; |
||||||
|
import Product from '../../components/Product'; |
||||||
|
const Services = ({ isMobile, |
||||||
|
books, |
||||||
|
getList, |
||||||
|
grades, |
||||||
|
gradeFilter, |
||||||
|
selectedGrade, |
||||||
|
gradeFilterBooks, |
||||||
|
setHeaderOptions, |
||||||
|
headerOptions, |
||||||
|
videos, |
||||||
|
}) => { |
||||||
|
|
||||||
|
const [filter, setFilter] = useState({ |
||||||
|
search: "", |
||||||
|
grade: "", |
||||||
|
productsType: "کتاب", |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
const onChange = (name, value) => { |
||||||
|
setFilter({ ...filter, [name]: value }); |
||||||
|
}; |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
getList(); |
||||||
|
setHeaderOptions(headerOptions); |
||||||
|
}, []); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
gradeFilter(filter.grade); |
||||||
|
}, [filter]); |
||||||
|
|
||||||
|
|
||||||
return( |
return( |
||||||
<div className="flex" style={{width: '93.5%', marginRight: '6.5%', marginTop: '8.5%'}}> |
<div className="flex" style={{width: '93.5%', marginRight: '6.5%', marginTop: '8.5%'}}> |
||||||
|
<button onClick={() => console.log(book)}>asdasd</button> |
||||||
{ |
{ books?.map((product, index) => ( |
||||||
PLATFORM_DATA.classes.map((item, idx) => ( |
<Link to={"/products/" + product?.id}> |
||||||
<Class title={item.title} description={item.description} price={item.price} group={item.group} teacher={item.teacher} /> |
<Product |
||||||
)) |
key={index} |
||||||
} |
productsType={filter.productsType} |
||||||
|
product={product} |
||||||
|
index={Number(index)} |
||||||
|
productName={`کتاب ${product?.name}`} |
||||||
|
productCat={`پایه ${grades[product?.gradeId]}`} |
||||||
|
productPrice={100000} |
||||||
|
productImg={"https://dnvn.ir/api/v1/file/" + product?.fileIds} |
||||||
|
numberOfRegards={160} |
||||||
|
|
||||||
|
productHolderBorder='' |
||||||
|
productHolderHoverBorder='shadow-md' |
||||||
|
|
||||||
|
/> |
||||||
|
</Link> |
||||||
|
))} |
||||||
|
|
||||||
</div> |
</div> |
||||||
); |
); |
||||||
}; |
}; |
||||||
|
|
||||||
export default Services; |
const mapStateToProps = (state) => ({ |
||||||
|
isDark: state.publicApi.isDark, |
||||||
|
isMobile: state.publicApi.isMobile, |
||||||
|
books: state.book.list, |
||||||
|
grades: state.publicApi.grades, |
||||||
|
gradeFilterBooks: state.book.gradeFilterBooks, |
||||||
|
selectedGrade: state.book.selectedGrade, |
||||||
|
}); |
||||||
|
|
||||||
|
const mapDispatchToProps = { |
||||||
|
getList: book.list, |
||||||
|
gradeFilter: book.gradeFilter, |
||||||
|
setHeaderOptions: publicApi.setHeaderOptions, |
||||||
|
}; |
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Services); |
||||||
|
|