Before Width: | Height: | Size: 966 B After Width: | Height: | Size: 996 B |
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 525 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 829 B After Width: | Height: | Size: 856 B |
Before Width: | Height: | Size: 864 B After Width: | Height: | Size: 882 B |
@ -1,6 +0,0 @@ |
|||||||
.specifications-li:hover div{ |
|
||||||
background-color: rgba(25,110,192,0.15); |
|
||||||
} |
|
||||||
.specifications-li div{ |
|
||||||
transition: all 0.2s; |
|
||||||
} |
|
@ -1,11 +1,11 @@ |
|||||||
import React from "react"; |
import React from "react"; |
||||||
import "./index.scss"; |
import "./index.scss"; |
||||||
|
|
||||||
export default function index() { |
export default function Switch({checked}) { |
||||||
return ( |
return ( |
||||||
<div className="switch"> |
<div className="switchbox transition-all"> |
||||||
<input type="checkbox" id="toggle" /> |
<input className="transition-all" type="checkbox" id="toggle" checked={checked} /> |
||||||
<label for="toggle"></label> |
<label className="transition-all" for="toggle"></label> |
||||||
</div> |
</div> |
||||||
); |
); |
||||||
} |
} |
||||||
|
@ -0,0 +1,17 @@ |
|||||||
|
import proxy from "../proxy"; |
||||||
|
const transport = { |
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.get("transport/list", data, { dispatch }); |
||||||
|
}, |
||||||
|
set: |
||||||
|
(data = {}, data2 = {}, data3 = {}) => |
||||||
|
async (dispatch) => { |
||||||
|
await proxy.post("transport/setTransport", data, { dispatch }); |
||||||
|
await proxy.get("userFactor/info", data2, { dispatch }); |
||||||
|
await proxy.get("transport/list", data3, { dispatch }); |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
export default transport; |
@ -0,0 +1,28 @@ |
|||||||
|
import { toast } from "react-toastify"; |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
loading: false, |
||||||
|
error: null, |
||||||
|
list: [], |
||||||
|
}; |
||||||
|
export default function transport(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "transport/list": |
||||||
|
return { |
||||||
|
...state, |
||||||
|
loading: false, |
||||||
|
list: data, |
||||||
|
error: null, |
||||||
|
}; |
||||||
|
case "transport/info": |
||||||
|
return { ...state, loading: false, error: null}; |
||||||
|
case "transport/loading": |
||||||
|
return { ...state, loading: true }; |
||||||
|
case "transport/error": |
||||||
|
toast.error(data.message); |
||||||
|
return { ...state, loading: false, error: data.message }; |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
const grades = [ |
||||||
|
"پیش دبستان", |
||||||
|
"اول", |
||||||
|
"دوم", |
||||||
|
"سوم", |
||||||
|
"چهارم", |
||||||
|
"پنجم", |
||||||
|
"ششم", |
||||||
|
"هفتم", |
||||||
|
"هشتم", |
||||||
|
"نهم", |
||||||
|
"دهم", |
||||||
|
"یازدهم", |
||||||
|
"دوازدهم", |
||||||
|
]; |
||||||
|
class filter { |
||||||
|
productsPage = (products, options) => { |
||||||
|
const { grade, subject, sort } = options; |
||||||
|
|
||||||
|
if (grade.length > 0 || subject.length > 0 || sort) { |
||||||
|
localStorage.setItem("filter", "ON"); |
||||||
|
} |
||||||
|
let finalSort; |
||||||
|
let byGradeFilter = []; |
||||||
|
if (grade.length > 0) { |
||||||
|
grade.map((item1) => { |
||||||
|
for (let i = 0; i < products.length; i++) { |
||||||
|
if (grades[products[i].gradeId] === item1) { |
||||||
|
byGradeFilter.push(products[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} else { |
||||||
|
byGradeFilter = products; |
||||||
|
} |
||||||
|
let bySubjectFilter = []; |
||||||
|
if (subject.length > 0) { |
||||||
|
subject.map((item1) => { |
||||||
|
for (let i = 0; i < byGradeFilter.length; i++) { |
||||||
|
if (byGradeFilter[i].name === item1) { |
||||||
|
bySubjectFilter.push(byGradeFilter[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} else { |
||||||
|
bySubjectFilter = byGradeFilter; |
||||||
|
} |
||||||
|
|
||||||
|
if (sort === "گران ترین") { |
||||||
|
finalSort = bySubjectFilter.sort((item1, item2) => { |
||||||
|
return item1.product[0].price - item2.product[0].price; |
||||||
|
}); |
||||||
|
} else { |
||||||
|
finalSort = bySubjectFilter; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
const _filter = new filter(); |
||||||
|
|
||||||
|
export default _filter; |
@ -1,36 +1,131 @@ |
|||||||
import React from "react"; |
import React, { useState, useMemo } from "react"; |
||||||
import { connect } from "react-redux"; |
import { connect } from "react-redux"; |
||||||
|
import { book } from "../../../redux/actions"; |
||||||
import Checkbox from "../../../components/Checkbox"; |
import Checkbox from "../../../components/Checkbox"; |
||||||
import VerticalExpandableProductFilter from "../../../components/VerticalExpandableProductFilter"; |
import Switch from "../../../components/Switch"; |
||||||
|
|
||||||
export const Sidebar = ({ onChange, grades }) => { |
//assets
|
||||||
const categories = [ |
import dropdownIcon from "../../../assets/icons/dropdown-blue.svg"; |
||||||
"کتاب فیزیکی", |
|
||||||
"کتاب دیجیتال", |
export const Sidebar = ({ |
||||||
"دوره ویدیویی", |
onChange, |
||||||
"بسته های آموزشی", |
levels, |
||||||
]; |
subjects, |
||||||
|
productTypes, |
||||||
|
setFilterOptions, |
||||||
|
filterOptions, |
||||||
|
}) => { |
||||||
|
const [toggleList, setToggleList] = useState({ |
||||||
|
subject: false, |
||||||
|
grade: false, |
||||||
|
productType: false, |
||||||
|
}); |
||||||
|
|
||||||
|
const Dropdown = ({ list, title, name, active }) => { |
||||||
return ( |
return ( |
||||||
<div className="flex flex-col w-1/4 p-4"> |
<div className="flex flex-col"> |
||||||
<VerticalExpandableProductFilter |
<div |
||||||
onChange={onChange} |
className="flex flex-row justify-between items-center py-5 cursor-pointer" |
||||||
|
onClick={() => |
||||||
|
setToggleList({ ...toggleList, [name]: !toggleList[name] }) |
||||||
|
} |
||||||
|
> |
||||||
|
<strong className="font-semibold text-tiny text-green4F"> |
||||||
|
{title} |
||||||
|
</strong> |
||||||
|
<img |
||||||
|
src={dropdownIcon} |
||||||
|
alt="" |
||||||
|
className={`w-4 transform transition-all ${ |
||||||
|
toggleList[name] ? "rotate-180" : "" |
||||||
|
}`}
|
||||||
|
/> |
||||||
|
</div> |
||||||
|
<ul |
||||||
|
className={`list-none p-0 mt-2 mb-0 mx-0 flex overflow-x-hidden flex-col transition-all`} |
||||||
|
style={{ |
||||||
|
maxHeight: !toggleList[name] ? 0 : "calc(100vh / 2.2)", |
||||||
|
overflowY: !toggleList[name] ? "hidden" : "scroll", |
||||||
|
}} |
||||||
|
> |
||||||
|
{list.map((item, index) => ( |
||||||
|
<li |
||||||
|
key={index} |
||||||
|
className="flex flex-row items-center mb-3" |
||||||
|
onClick={() => |
||||||
|
active !== item |
||||||
|
? setFilterOptions({ ...filterOptions, [name]: item }) |
||||||
|
: setFilterOptions({ ...filterOptions, [name]: null }) |
||||||
|
} |
||||||
|
> |
||||||
|
<Checkbox checked={active === item} /> |
||||||
|
<span className="text-tiny font-medium">{item}</span> |
||||||
|
</li> |
||||||
|
))} |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
const CkeckItem = ({ title, name }) => { |
||||||
|
return ( |
||||||
|
<div |
||||||
|
className="flex flex-row justify-between items-center py-4" |
||||||
|
onClick={() => |
||||||
|
setFilterOptions({ |
||||||
|
...filterOptions, |
||||||
|
[name]: !filterOptions.available, |
||||||
|
}) |
||||||
|
} |
||||||
|
> |
||||||
|
<span className="font-semibold text-tiny text-green4F">{title}</span> |
||||||
|
<Switch checked={filterOptions.available} /> |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className="flex flex-col w-1/4 px-4 pt-5 pb-2 bg-gray-50 transform translate-y-5 border border-solid border-gray-200 rounded-md" |
||||||
|
style={{ |
||||||
|
height: "fit-content", |
||||||
|
}} |
||||||
|
> |
||||||
|
<strong className="text-lg text-green4F mb-10">فیلترها</strong> |
||||||
|
<div className="flex flex-col divide-y divide-solid divide-gray-200"> |
||||||
|
<Dropdown |
||||||
|
list={productTypes} |
||||||
|
title="نوع محصول" |
||||||
|
name="productType" |
||||||
|
active={filterOptions.productType} |
||||||
|
/> |
||||||
|
<Dropdown |
||||||
|
list={Object.values(levels)} |
||||||
|
title={"پایه تحصیلی"} |
||||||
name="grade" |
name="grade" |
||||||
list={Object.values(grades)} |
active={filterOptions.grade} |
||||||
title="پایه تحصیلی" |
|
||||||
/> |
/> |
||||||
<VerticalExpandableProductFilter |
<Dropdown |
||||||
name="category" |
list={subjects} |
||||||
list={categories} |
title={"عنوان کتاب"} |
||||||
title="دسته بندی" |
name="subject" |
||||||
|
active={filterOptions.subject} |
||||||
/> |
/> |
||||||
|
<CkeckItem title="فقط کالاهای موجود" name={"available"} /> |
||||||
|
</div> |
||||||
</div> |
</div> |
||||||
); |
); |
||||||
}; |
}; |
||||||
|
|
||||||
const mapStateToProps = (state) => ({ |
const mapStateToProps = (state) => ({ |
||||||
grades: state.publicApi.grades, |
levels: state.book.levels, |
||||||
|
subjects: state.book.subjects, |
||||||
|
productTypes: state.book.productTypes, |
||||||
|
filterOptions: state.book.filterOptions, |
||||||
}); |
}); |
||||||
|
|
||||||
const mapDispatchToProps = {}; |
const mapDispatchToProps = { |
||||||
|
setFilterOptions: book.setFilterOptions, |
||||||
|
}; |
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Sidebar); |
export default connect(mapStateToProps, mapDispatchToProps)(Sidebar); |
||||||
|