reza added products

temp
Reza_ashrafi 3 years ago
parent 669c4732b2
commit fc6d4c4132
  1. 2
      src/App.scss
  2. 7
      src/assets/icons/search-light.svg
  3. 2
      src/components/Navbar/index.js
  4. 49
      src/components/Search/index.js
  5. 45
      src/components/Select/index.js
  6. 7
      src/index.css
  7. 2
      src/redux/reducers/public.js
  8. 7
      src/router.js
  9. 32
      src/views/Home/Portrait/Private/Blogs/index.js
  10. 8
      src/views/Home/Portrait/Private/MyBooks/index.js
  11. 14
      src/views/Home/Portrait/Private/Shop/index.js
  12. 35
      src/views/Home/Portrait/Private/Videos/index.js
  13. 2
      src/views/Home/Portrait/Public/Features/index.js
  14. 2
      src/views/Home/Portrait/Public/Header/index.js
  15. 4
      src/views/Home/Portrait/Public/Responsive/index.js
  16. 2
      src/views/Home/index.js
  17. 112
      src/views/Products/index.js
  18. 68
      tailwind.config.js

@ -90,4 +90,4 @@
.container{
max-width: 1480px;
}
}
}

@ -0,0 +1,7 @@
<svg id="vuesax_linear_search-normal" data-name="vuesax/linear/search-normal" xmlns="http://www.w3.org/2000/svg" width="19.237" height="19.237" viewBox="0 0 19.237 19.237">
<g id="search-normal">
<path id="Vector" d="M15.229,7.615A7.615,7.615,0,1,1,7.615,0,7.615,7.615,0,0,1,15.229,7.615Z" transform="translate(1.603 1.603)" fill="none" stroke="#196ec0" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M1.6,1.6,0,0" transform="translate(16.031 16.031)" fill="none" stroke="#196ec0" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-3" data-name="Vector" d="M0,0H19.237V19.237H0Z" fill="none" opacity="0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 731 B

@ -31,7 +31,7 @@ function Navbar({ pages, isDark, isLogin }) {
className={_.join(
[
"z-50 flex flex-1 flex-row fixed left-0 top-0 justify-between w-full lg:bg-opacity-20 lg:bg-transparent lg:shadow-sm lg:backdrop-filter lg:backdrop-blur-md lg:px-5 xl:px-10 transition-all duration-300",
!top ? "bg-white" : "",
!top ? (isDark ? "bg-dark" :"bg-white") : "",
],
" "
)}

@ -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"],
};

@ -3,12 +3,7 @@
@tailwind utilities;
.bg-dark {
background: rgb(44, 73, 100);
background: radial-gradient(
circle,
rgba(44, 73, 100, 1) 0%,
rgba(6, 27, 48, 1) 100%
);
background: #2C2C2C;
}
.rtl {

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

@ -1,9 +1,11 @@
import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { connect } from "react-redux";
import Navbar from "./components/Navbar";
import _ from "lodash";
import Home from "./views/Home";
import Products from "./views/Products";
// import VideoTube from "./views/Home/VideoTube";
function Router({ isDark }) {
@ -19,9 +21,10 @@ function Router({ isDark }) {
)}
>
<BrowserRouter>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
{/* <Route path="/vod" element={<VideoTube />} /> */}
<Route path="/" exact element={<Home />} />
<Route path="/products" exact element={<Products />} />
<Route
path="*"
element={

@ -2,19 +2,26 @@ import React, { useEffect } from "react";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { blog } from "../../../../../redux/actions";
import _ from 'lodash';
import _ from "lodash";
import arrowBlueIcon from "../../../../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../../../../assets/icons/arrow-left-white.svg";
function Blogs({ list, getList }) {
function Blogs({ list, getList, isDark }) {
useEffect(() => {
getList();
}, []);
return (
<div className="w-full pr-4">
<div className="w-full flex flex-col rounded-md py-4 overflow-hidden">
<header className="w-full flex flex-row justify-between items-center pl-4">
<strong className="text-blueC0 font-bold text-lg">خواندنیها</strong>
<img src={arrowBlueIcon} alt="" className="transform rotate-180" />
<header className="w-full flex flex-row justify-between items-center">
<strong className="text-blueC0 dark:text-white font-bold text-lg">
خواندنیها
</strong>
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt=""
className={`transform ml-4 ${isDark ? "w-7" : "rotate-180"}`}
/>
</header>
<ul className="list-none w-full overflow-x-scroll pt-3 flex flex-row pb-10">
{list.map((blog, index) => (
@ -40,8 +47,10 @@ const Blog = ({ blog }) => {
minHeight: "calc(100vw / 1.3 * 2 / 3)",
}}
>
<div className="w-11/12 bg-white rounded-md shadow-md flex flex-col transform translate-y-1/2 p-2">
<h2 className="text-xs font-semibold text-blue5F">{blog.title}</h2>
<div className="w-11/12 bg-white rounded-md shadow-md flex flex-col transform translate-y-1/2 p-2 dark:bg-gray36">
<h2 className="text-xs font-semibold text-blue5F dark:text-white">
{blog.title}
</h2>
<div className="w-full flex flex-row justify-between items-center mt-3">
<div className="flex flex-row items-center">
<img
@ -49,10 +58,14 @@ const Blog = ({ blog }) => {
alt=""
className="w-5 h-5 rounded-full ml-2"
/>
<span className="text-blueC0 text-xs font-light">{"حامد دژبانی نسب"}</span>
<span className="text-blueC0 text-xs font-light dark:text-greenBA">
{"حامد دژبانی نسب"}
</span>
</div>
<div className="flex flex-row items-center">
<span className="text-xs font-light">{_.join(['زمان مناسب', '30' ], " ")}</span>
<span className="text-xs font-light dark:text-greenBA">
{_.join(["زمان مناسب", "30"], " ")}
</span>
</div>
</div>
</div>
@ -63,6 +76,7 @@ const Blog = ({ blog }) => {
const mapStateToProps = (state) => ({
list: state.publicApi.blogList,
isDark: state.publicApi.isDark,
});
export default connect(mapStateToProps, { getList: blog.list })(Blogs);

@ -10,8 +10,8 @@ function MyBooks({ list, getList, grades }) {
}, []);
return (
<div className="w-full px-4 mb-5">
<div className="w-full flex flex-col rounded-md pt-4 px-2 bg-blueFF1 overflow-hidden">
<strong className="text-blueC0 font-bold text-lg">کتابهای من</strong>
<div className="w-full flex flex-col rounded-md pt-4 px-2 bg-blueFF1 dark:bg-gray20 overflow-hidden">
<strong className="text-blueC0 dark:text-white font-bold text-lg">کتابهای من</strong>
<ul className="list-none w-full overflow-x-scroll pt-2 flex flex-row">
{list.map((book, index) => (
<Book book={book} key={index} grades={grades} />
@ -35,8 +35,8 @@ const Book = ({ book, grades }) => {
minWidth: "calc(100vh / 5 * 3 / 4)",
}}
/>
<h2 className="mt-2 text-sm font-semibold text-blue5F">{book.name}</h2>
<p className="font-medium text-blueC0 text-xs mt-1">{`پایه ${grades[book.gradeId]}`}</p>
<h2 className="mt-2 text-sm font-semibold text-blue5F dark:text-white">{book.name}</h2>
<p className="font-medium text-blueC0 dark:text-greenBA text-xs mt-1">{`پایه ${grades[book.gradeId]}`}</p>
<Progress percent={60} />
</Link>
</li>

@ -3,8 +3,9 @@ import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { book } from "../../../../../redux/actions";
import arrowBlueIcon from "../../../../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../../../../assets/icons/arrow-left-white.svg";
function Shop({ list, getList, grades }) {
function Shop({ list, getList, grades, isDark }) {
useEffect(() => {
getList();
}, []);
@ -12,8 +13,14 @@ function Shop({ list, getList, grades }) {
<div className="w-full pr-4">
<div className="w-full flex flex-col rounded-md py-4 overflow-hidden">
<header className="w-full flex flex-row justify-between items-center pl-4">
<strong className="text-blueC0 font-bold text-lg">فروشگاه</strong>
<img src={arrowBlueIcon} alt="" className="transform rotate-180" />
<strong className="text-blueC0 dark:text-white font-bold text-lg">
فروشگاه
</strong>
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt=""
className={`transform ${isDark ? 'w-7' : 'rotate-180'}`}
/>
</header>
<ul
className="list-none w-full overflow-x-scroll pt-3 flex flex-col flex-wrap"
@ -68,6 +75,7 @@ const Book = ({ book, index }) => {
const mapStateToProps = (state) => ({
list: state.book.list,
isDark: state.publicApi.isDark,
});
export default connect(mapStateToProps, { getList: book.list })(Shop);

@ -4,8 +4,9 @@ import { connect } from "react-redux";
import { book } from "../../../../../redux/actions";
import Progress from "../../../../../components/Progress";
import arrowBlueIcon from "../../../../../assets/icons/arrow-right-blue.svg";
import arrowWhiteIcon from "../../../../../assets/icons/arrow-left-white.svg";
function Videos({ list, getList, grades }) {
function Videos({ list, getList, grades, isDark }) {
useEffect(() => {
getList();
}, []);
@ -13,18 +14,18 @@ function Videos({ list, getList, grades }) {
<div className="w-full px-4">
<div className="w-full flex flex-col rounded-md py-4 overflow-hidden">
<header className="w-full flex flex-row justify-between items-center">
<strong className="text-blueC0 font-bold text-lg">دورههای ویدئویی شما</strong>
<img src={arrowBlueIcon} alt="" className="transform rotate-180" />
<strong className="text-blueC0 dark:text-white font-bold text-lg">
دورههای ویدئویی شما
</strong>
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt=""
className={`transform ${isDark ? 'w-7' : 'rotate-180'}`}
/>
</header>
<ul
className="list-none w-full overflow-x-scroll pt-3 flex flex-row"
>
<ul className="list-none w-full overflow-x-scroll pt-3 flex flex-row">
{list.map((book, index) => (
<Book
book={book}
key={index}
grades={grades}
/>
<Book book={book} key={index} grades={grades} />
))}
</ul>
</div>
@ -45,8 +46,12 @@ const Book = ({ book, grades }) => {
minWidth: "calc(100vw / 2 )",
}}
/>
<h2 className="mt-2 text-sm font-semibold text-blue5F">{book.name}</h2>
<p className="font-medium text-blueC0 text-xs mt-1">{`پایه ${grades[book.gradeId]}`}</p>
<h2 className="mt-2 text-sm font-semibold text-blue5F dark:text-white">
{book.name}
</h2>
<p className="font-medium text-blueC0 dark:text-greenBA text-xs mt-1">{`پایه ${
grades[book.gradeId]
}`}</p>
<Progress percent={60} />
</Link>
</li>
@ -55,8 +60,8 @@ const Book = ({ book, grades }) => {
const mapStateToProps = (state) => ({
list: state.book.list,
grades : state.publicApi.grades
grades: state.publicApi.grades,
isDark: state.publicApi.isDark,
});
export default connect(mapStateToProps, { getList: book.list })(Videos);

@ -26,7 +26,7 @@ const Feature = ({ feature }) => {
>
{feature.title}
</strong>
<p className="mt-1 font-light text-gray1 text-xs">{feature.text}</p>
<p className="mt-1 font-light text-gray1 dark:text-white text-xs">{feature.text}</p>
</div>
);
};

@ -70,7 +70,7 @@ function Header({ list }) {
ورود به فروشگاه
</Link>
</div>
<div className="flex flex-col items-center text-center font-extrabold text-blue5F text-2xl mt-3 transform translate-y-4">
<div className="flex flex-col items-center text-center font-extrabold text-blue5F dark:text-white text-2xl mt-3 transform translate-y-4">
<div className="flex flex-row">
<div className="relative">
<h1 className="inline z-50 pb-1">یادگیری &nbsp;</h1>

@ -30,10 +30,10 @@ function Responsive() {
</div>
</div>
<div className="w-full relative mt-16" style={{ height : 'calc(100vh / 4)' }}>
<div className="absolute left-0 bottom-0 rounded-md" style={{ backgroundColor: '#E3E3E3', height : 'calc(100vh / 4)', width : 'calc(100vw / 1.2)' }}>
<div className="absolute left-0 bottom-0 rounded-md bg-grayE3" style={{ height : 'calc(100vh / 4)', width : 'calc(100vw / 1.2)' }}>
</div>
<div className="absolute right-0 bottom-0 rounded-md" style={{ backgroundColor: '#EEEEEE', height : 'calc(100vh / 5.2)', width : 'calc(100vw / 6)' }}>
<div className="absolute right-0 bottom-0 rounded-md bg-grayEE" style={{ height : 'calc(100vh / 5.2)', width : 'calc(100vw / 6)' }}>
</div>
</div>

@ -1,13 +1,11 @@
import React from 'react';
import Landscape from './Landscape';
import Portrait from './Portrait';
import Navbar from "../../components/Navbar";
export default function Home() {
return (
<>
<Navbar />
<Portrait />
<Landscape />
</>

@ -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);

@ -5,42 +5,58 @@ module.exports = {
backgroundColor: (theme) => ({
...theme("colors"),
blueC0: "#196EC0",
blueB0 : "#517AB0",
blueB0: "#517AB0",
blue90: "#235A90",
blueEB : '#2B8DEB',
blueFF : '#E8FCFF',
blueFF1 : '#E9F0FF',
redFF : '#FFE6E6',
redFF1 : '#FF2020',
yellow2 : '#FDFFDA',
yellow3 : '#EFFF00',
gray36 : '#363636',
orange1 : '#FF6600',
green1 : '#00FF80'
blueEB: "#2B8DEB",
blueFF: "#E8FCFF",
blueFF1: "#E9F0FF",
redFF: "#FFE6E6",
redFF1: "#FF2020",
yellow2: "#FDFFDA",
yellow3: "#EFFF00",
gray36: "#363636",
orange1: "#FF6600",
green1: "#00FF80",
gray20: "#202020",
gray2C: "#2C2C2C",
gray36: "#363636",
grayDB: "#DBDBDB",
grayE3: "#E3E3E3",
grayEE: "#EEEEEE",
grayF9: "#F9F9F9",
}),
textColor : (theme) => ({
textColor: (theme) => ({
...theme("colors"),
primary: "#235A90",
blueC0: "#196EC0",
blueE8 : '#2E81E8',
blue52 : '#132F52',
blue5F : '#05335F',
green71 : '#067182',
red5F : '#5F1A05',
yellow1 : '#5F5F05',
gray1 : '#333333'
blueE8: "#2E81E8",
blue52: "#132F52",
blue5F: "#05335F",
green71: "#067182",
greenBA: "#06BACE",
red5F: "#5F1A05",
yellow1: "#5F5F05",
gray1: "#333333",
gray70 : "#707070"
}),
borderColor : (theme) => ({
borderColor: (theme) => ({
...theme("colors"),
blueC0: "#196EC0",
blueFE : "#C1E0FE"
blueFE: "#C1E0FE",
grayDB: "#DBDBDB",
gray45 : '#454545'
}),
extend : {
fill: (theme) => ({
...theme("colors"),
blueC0 : '#196EC0',
grayDF : '#DFDFDF',
greenBA : '#06BACE'
}),
extend: {
borderRadius: {
'sm': '3px',
}
}
sm: "3px",
},
},
},
variants: {
extend: {},

Loading…
Cancel
Save