parent
669c4732b2
commit
fc6d4c4132
18 changed files with 326 additions and 74 deletions
After Width: | Height: | Size: 731 B |
@ -0,0 +1,49 @@ |
||||
import React from "react"; |
||||
import _ from "lodash"; |
||||
|
||||
const langDetector = (lang = "fa", option1, option2) => { |
||||
return lang === "fa" ? option1 : option2; |
||||
}; |
||||
|
||||
export default function Search({ |
||||
lang, |
||||
backgroundColor, |
||||
borderColor, |
||||
textColor, |
||||
icon, |
||||
}) { |
||||
return ( |
||||
<div |
||||
className={`flex items-center justify-center border-solid w-full border rounded-md overflow-hidden my-2 ${backgroundColor} ${borderColor}`} |
||||
> |
||||
<div className="relative text-gray-600 w-full bg-transparent"> |
||||
<span |
||||
className={_.join( |
||||
[ |
||||
"absolute inset-y-0 flex items-center pl-2", |
||||
langDetector(lang, "left-0", "right-0"), |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
<button |
||||
type="submit" |
||||
className="p-1 focus:outline-none focus:shadow-outline" |
||||
> |
||||
{icon && <img src={icon} className="w-6 h-6" alt="" />} |
||||
</button> |
||||
</span> |
||||
<input |
||||
type="search" |
||||
name="q" |
||||
className={`w-full py-3 text-sm rounded-md pr-3 outline-none bg-transparent ${textColor}`} |
||||
placeholder={_.join( |
||||
[langDetector(lang, "جستجو...", "Search...")], |
||||
" " |
||||
)} |
||||
autoComplete="off" |
||||
/> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,45 @@ |
||||
import React from "react"; |
||||
|
||||
function Select({ |
||||
options, |
||||
icon, |
||||
fill, |
||||
hoverFill, |
||||
margin, |
||||
borderColor, |
||||
backgroundColor, |
||||
onChane, |
||||
name, |
||||
}) { |
||||
return ( |
||||
<div |
||||
className={`inline-block relative w-1/2 group ${margin} ${backgroundColor}`} |
||||
> |
||||
<select |
||||
className={`text-gray70 text-xs block appearance-none bg-transparent w-full border border-solid px-4 py-3 pr-3 rounded-md leading-tight focus:outline-none focus:border-blueC0 focus:text-blueC0 ${borderColor}`} |
||||
onChane={(e) => onChane(name, e.target.value)} |
||||
> |
||||
{options.map((option, index) => ( |
||||
<option key={index} className=""> |
||||
{option} |
||||
</option> |
||||
))} |
||||
</select> |
||||
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center px-2"> |
||||
<svg |
||||
className={`${fill} h-5 w-5 group-focus:${hoverFill}`} |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
viewBox="0 0 20 20" |
||||
> |
||||
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" /> |
||||
</svg> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default Select; |
||||
|
||||
Select.defaultProps = { |
||||
options: ["Really", "Option 2", "Option 3"], |
||||
}; |
@ -0,0 +1,112 @@ |
||||
import React, { useState, useEffect, useCallback } from "react"; |
||||
import { Link } from "react-router-dom"; |
||||
import { connect } from "react-redux"; |
||||
import Search from "../../components/Search"; |
||||
import Select from "../../components/Select"; |
||||
import { book } from "../../redux/actions"; |
||||
|
||||
//assets
|
||||
import searchLight from "../../assets/icons/search-light.svg"; |
||||
|
||||
const Product = ({ productsType, product, index, grades }) => { |
||||
return ( |
||||
<> |
||||
{productsType === "book" && ( |
||||
<Link |
||||
to={"/products" + product?.name} |
||||
className={`w-1/2 flex flex-col border-t border-grayDB dark:border-gray45 p-3 border-solid ${ |
||||
index % 2 === 0 ? "border-l" : "" |
||||
}`}
|
||||
> |
||||
<img |
||||
src={"https://dnvn.ir/api/v1/file/" + product?.fileIds} |
||||
className="w-full rounded-md mb-2" |
||||
/> |
||||
<strong className="text-blue5F dark:text-white text-md font-bold mb-1"> |
||||
{product?.name} |
||||
</strong> |
||||
<span className="text-xs text-blueC0 dark:text-white font-light mb-4"> |
||||
{"پایه" + " " + grades[product?.gradeId]} |
||||
</span> |
||||
<div className="w-full flex flex-row justify-center font-semibold text-md text-blue5F dark:text-white"> |
||||
{1399 + " " + "تومان"} |
||||
</div> |
||||
</Link> |
||||
)} |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export const Products = ({ isDark, books, getList, grades }) => { |
||||
const [filter, setFilter] = useState({ |
||||
search: "", |
||||
grade: "", |
||||
productsType: "book", |
||||
}); |
||||
|
||||
const onChange = (name, value) => { |
||||
setFilter({ ...filter, [name]: value }); |
||||
}; |
||||
|
||||
useEffect(() => { |
||||
getList(); |
||||
}, []); |
||||
return ( |
||||
<> |
||||
{/* Portrait */} |
||||
<div className="w-full flex flex-col bg-transparent pt-20"> |
||||
<header className="w-full px-4"> |
||||
<Search |
||||
backgroundColor="bg-grayF9 dark:bg-gray36" |
||||
borderColor="border-grayDB dark:border-gray45" |
||||
textColor="text-blueC0 dark:text-white" |
||||
icon={searchLight} |
||||
/> |
||||
<div className="w-full flex flex-row justify-between mt-3"> |
||||
<Select |
||||
margin="ml-1" |
||||
fill="fill-blueC0 dark:fill-white" |
||||
borderColor="border-grayDB dark:border-gray45" |
||||
backgroundColor="bg-grayF9 dark:bg-gray36" |
||||
onChange={onChange} |
||||
name="productsType" |
||||
options={["کتاب", "ویديو", "اشتراک"]} |
||||
// hoverFill="fill-greenBA"
|
||||
/> |
||||
<Select |
||||
margin="mr-1" |
||||
fill="fill-blueC0 dark:fill-white" |
||||
borderColor="border-grayDB dark:border-gray45" |
||||
backgroundColor="bg-grayF9 dark:bg-gray36" |
||||
onChange={onChange} |
||||
name="grade" |
||||
options={Object.values(grades)} |
||||
// hoverFill="fill-grayBA"
|
||||
/> |
||||
</div> |
||||
</header> |
||||
<div className="w-full flex flex-row flex-wrap mt-3"> |
||||
{books?.map((product, index) => ( |
||||
<Product |
||||
key={index} |
||||
productsType={filter.productsType} |
||||
product={product} |
||||
index={Number(index)} |
||||
grades={grades} |
||||
/> |
||||
))} |
||||
</div> |
||||
</div> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
isDark: state.publicApi.isDark, |
||||
books: state.book.list, |
||||
grades: state.publicApi.grades, |
||||
}); |
||||
|
||||
const mapDispatchToProps = { getList: book.list }; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Products); |
Loading…
Reference in new issue