|
@@ -3,7 +3,10 @@ import './App.scss';
|
|
|
import thunk from 'redux-thunk';
|
|
|
import {createStore, combineReducers, applyMiddleware} from 'redux';
|
|
|
import {Provider, connect} from 'react-redux';
|
|
|
-import {useState} from 'react';
|
|
|
+import {useEffect, useState} from 'react';
|
|
|
+import {Router, Route, Link, Redirect, match} from 'react-router-dom';
|
|
|
+import {createBrowserHistory} from 'history';
|
|
|
+
|
|
|
|
|
|
const actionPending = name => ({type: 'PROMISE', status: 'PENDING', name});
|
|
|
const actionResolved = (name, payload) => ({type: 'PROMISE', status: 'RESOLVED', name, payload});
|
|
@@ -217,20 +220,23 @@ const store = createStore(combineReducers(
|
|
|
store.subscribe(() => console.log(store.getState()));
|
|
|
|
|
|
store.dispatch(actionRootCats());
|
|
|
-store.dispatch(actionCatById('5dc458985df9d670df48cc47'));
|
|
|
-
|
|
|
|
|
|
const Logo = () =>
|
|
|
- <img src={logo} className="Logo" alt="logo"/>;
|
|
|
+ <Link to="/">
|
|
|
+ <img src={logo} className="Logo" alt="logo"/>
|
|
|
+ </Link>;
|
|
|
|
|
|
const Header = () =>
|
|
|
<header className="header">
|
|
|
<Logo/>
|
|
|
+ <Login/>
|
|
|
<CKoshik/>
|
|
|
</header>;
|
|
|
|
|
|
const CategoryListItem = ({_id, name}) =>
|
|
|
- <li><a href={`#/category/${_id}`}>{name}</a></li>;
|
|
|
+ <li>
|
|
|
+ <Link to={`/category/${_id}`}>{name}</Link>
|
|
|
+ </li>;
|
|
|
|
|
|
const CategoryList = ({cats}) => {
|
|
|
return (
|
|
@@ -240,9 +246,28 @@ const CategoryList = ({cats}) => {
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-
|
|
|
const CCategoryList = connect(state => ({cats: state.promise.rootCats?.payload || []}))(CategoryList);
|
|
|
|
|
|
+const PageGood = ({good: {name, price, images}, match: {params: {_id}}, getData}) => {
|
|
|
+ const isFirstImgExists = images && images[0] && images[0].url;
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ getData(_id);
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <h2>{name}</h2>
|
|
|
+ {isFirstImgExists && <img src={`${backendURL}/${images[0].url}`} alt={name}/>}
|
|
|
+ <strong>{price} грн</strong>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+const CPageGood = connect(state => ({
|
|
|
+ good: state.promise.goodById?.payload ?? [],
|
|
|
+}), {getData: actionGoodById})(PageGood);
|
|
|
+
|
|
|
const Aside = () =>
|
|
|
<aside className="aside">
|
|
|
<CCategoryList/>
|
|
@@ -251,12 +276,23 @@ const Aside = () =>
|
|
|
const GoodCard = ({good: {_id, name, price, images}, onAdd}) =>
|
|
|
<li className="GoodCard">
|
|
|
<h2>{name}</h2>
|
|
|
- {images && images[0] && images[0].url && <img src={backendURL + '/' + images[0].url}/>}
|
|
|
+ {images && images[0] && images[0].url && <img src={`${backendURL}/${images[0].url}`}/>}
|
|
|
<strong>{price} грн</strong>
|
|
|
<button onClick={() => onAdd({_id, name, price, images})}>+</button>
|
|
|
+ <Link to={`/good/${_id}`}>
|
|
|
+ Подробнее
|
|
|
+ </Link>
|
|
|
</li>;
|
|
|
|
|
|
-const CGoodCard = connect(null, {onAdd: actionCartAdd})(GoodCard);
|
|
|
+
|
|
|
+const Login = () =>
|
|
|
+ <Link to="/login">
|
|
|
+ <h2 className="login">Личный кабинет</h2>
|
|
|
+ </Link>;
|
|
|
+
|
|
|
+const CGoodCard = connect(null, {
|
|
|
+ onAdd: actionCartAdd
|
|
|
+})(GoodCard);
|
|
|
|
|
|
const Koshik = ({cart}) => {
|
|
|
let goodsInCart = cart;
|
|
@@ -265,7 +301,11 @@ const Koshik = ({cart}) => {
|
|
|
allGoodsInCart += goodsInCart[key].count;
|
|
|
}
|
|
|
return (
|
|
|
- <h2 className="koshikCounter">В корзине:{allGoodsInCart}</h2>
|
|
|
+ <h2 className="koshikCounter">
|
|
|
+ <Link to="/cart">В корзине:{allGoodsInCart}
|
|
|
+ </Link>
|
|
|
+ </h2>
|
|
|
+
|
|
|
);
|
|
|
};
|
|
|
|
|
@@ -277,7 +317,7 @@ const Category = ({cat: {name, goods = []} = {}}) => {
|
|
|
<div className="Category">
|
|
|
<h1>{name}</h1>
|
|
|
<ul className="ul">
|
|
|
- {goods.map(good => <CGoodCard key={good._id} good={good}/>)}
|
|
|
+ {(goods || []).map(good => <CGoodCard key={good._id} good={good}/>)}
|
|
|
</ul>
|
|
|
</div>
|
|
|
);
|
|
@@ -348,15 +388,15 @@ const LoginForm = ({onCartLogin}) => {
|
|
|
const [login, setLogin] = useState('');
|
|
|
const [password, setPassword] = useState('');
|
|
|
const isDisabled = login === '' || password === '';
|
|
|
- console.log(login, password, isDisabled)
|
|
|
+ console.log(login, password, isDisabled);
|
|
|
|
|
|
const onChange = (event) => {
|
|
|
- event.target.name === 'login' ? setLogin(event.target.value) : setPassword(event.target.value);
|
|
|
+ event.target.name === 'login' ? setLogin(event.target.value) : setPassword(event.target.value);
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<div className="inputWrapper">
|
|
|
- <h1>Регистрация</h1>
|
|
|
+ <h2>Вход в личный кабинет</h2>
|
|
|
<input
|
|
|
className="inputLogin"
|
|
|
name="login"
|
|
@@ -381,6 +421,8 @@ const LoginForm = ({onCartLogin}) => {
|
|
|
onCartLogin(login, password);
|
|
|
}}>Login
|
|
|
</button>
|
|
|
+ <h4>Вы еще не зарегистрированы?</h4>
|
|
|
+ <Link to="/registration">Зарегистрироваться</Link>
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
@@ -388,16 +430,95 @@ const LoginForm = ({onCartLogin}) => {
|
|
|
const CLoginForm = connect(
|
|
|
null,
|
|
|
{
|
|
|
- onCartLogin: actionFullRegister
|
|
|
+ onCartLogin: actionFullLogin
|
|
|
})(LoginForm);
|
|
|
|
|
|
+const RegisterForm = ({onCartRegister}) => {
|
|
|
+ const [login, setLogin] = useState('');
|
|
|
+ const [password, setPassword] = useState('');
|
|
|
+ const isDisabled = login === '' || password === '';
|
|
|
+ console.log(login, password, isDisabled);
|
|
|
+
|
|
|
+ const onChange = (event) => {
|
|
|
+ event.target.name === 'login' ? setLogin(event.target.value) : setPassword(event.target.value);
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="inputWrapper">
|
|
|
+ <h2>Регистрация</h2>
|
|
|
+ <input
|
|
|
+ className="inputLogin"
|
|
|
+ name="userName"
|
|
|
+ style={{borderColor: isDisabled ? 'red' : ''}}
|
|
|
+ placeholder="введите имя"
|
|
|
+ type="text"
|
|
|
+ onChange={onChange}
|
|
|
+ />
|
|
|
+ <input
|
|
|
+ className="inputLogin"
|
|
|
+ name="login"
|
|
|
+ style={{borderColor: isDisabled ? 'red' : ''}}
|
|
|
+ placeholder="*введите логин"
|
|
|
+ type="text"
|
|
|
+ onChange={onChange}
|
|
|
+ />
|
|
|
+ <input
|
|
|
+ className="inputPsw"
|
|
|
+ name="password"
|
|
|
+ style={{borderColor: isDisabled ? 'red' : ''}}
|
|
|
+ placeholder="*введите пароль"
|
|
|
+ type="password"
|
|
|
+ onChange={onChange}
|
|
|
+ />
|
|
|
+ <button
|
|
|
+ className="buttonLogin"
|
|
|
+ disabled={isDisabled}
|
|
|
+ onClick={
|
|
|
+ () => {
|
|
|
+ onCartRegister(login, password);
|
|
|
+ }}>Login
|
|
|
+ </button>
|
|
|
+ <Link to="/login">Войти в личный кабинет</Link>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+const CRegisterForm = connect(
|
|
|
+ null,
|
|
|
+ {
|
|
|
+ onCartRegister: actionFullRegister
|
|
|
+ })(RegisterForm);
|
|
|
+
|
|
|
+const PageMain = () =>
|
|
|
+ <h1>Главная страничка</h1>;
|
|
|
+
|
|
|
+const PageCategory = ({match: {params: {_id}}, getData}) => {
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ getData(_id);
|
|
|
+ }, [_id]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <CCategory/>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+const CPageCategory = connect(null, {getData: actionCatById})(PageCategory);
|
|
|
+
|
|
|
const Main = () =>
|
|
|
<main className="main">
|
|
|
<Aside/>
|
|
|
<Content>
|
|
|
- <CCategory/>
|
|
|
- <CLoginForm/>
|
|
|
- <CCart/>
|
|
|
+
|
|
|
+ <Route path="/" component={PageMain} exact/>
|
|
|
+ <Route path="/category/:_id" component={CPageCategory} exact/>
|
|
|
+ <Route path="/cart" component={CCart} exact/>
|
|
|
+ <Route path="/login" component={CLoginForm} exact/>
|
|
|
+ <Route path="/registration" component={CRegisterForm} exact/>
|
|
|
+ <Route path="/good/:_id" component={CPageGood} exact/>
|
|
|
+ {/*<CCategory/>*/}
|
|
|
</Content>
|
|
|
</main>;
|
|
|
|
|
@@ -411,16 +532,20 @@ const Footer = () =>
|
|
|
<Logo/>
|
|
|
</footer>;
|
|
|
|
|
|
+const history = createBrowserHistory();
|
|
|
+
|
|
|
//import {Provider, connect} from 'react-redux';
|
|
|
function App() {
|
|
|
return (
|
|
|
- <Provider store={store}>
|
|
|
- <div className="App">
|
|
|
- <Header/>
|
|
|
- <Main/>
|
|
|
- <Footer/>
|
|
|
- </div>
|
|
|
- </Provider>
|
|
|
+ <Router history={history}>
|
|
|
+ <Provider store={store}>
|
|
|
+ <div className="App">
|
|
|
+ <Header/>
|
|
|
+ <Main/>
|
|
|
+ <Footer/>
|
|
|
+ </div>
|
|
|
+ </Provider>
|
|
|
+ </Router>
|
|
|
);
|
|
|
}
|
|
|
|