|
@@ -142,8 +142,11 @@ function promiseReducer(state={}, {type, name, status, payload, error}){
|
|
const actionAuthLogin = (token) => ({ type: 'AUTH_LOGIN', token })
|
|
const actionAuthLogin = (token) => ({ type: 'AUTH_LOGIN', token })
|
|
const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
|
|
const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
|
|
|
|
|
|
-const actionLogin = (login = 'tst', password = '123') =>
|
|
|
|
- actionPromise('login', gql(`query ($login:String, $password:String){ login(login:$login, password:$password)}`, { 'login': login, 'password': password }))
|
|
|
|
|
|
+const actionLogin = (login, password) =>
|
|
|
|
+ actionPromise('login', gql(`
|
|
|
|
+ query log($login:String, $password:String) {
|
|
|
|
+ login(login: $login, password: $password)
|
|
|
|
+ }`, { login, password }))
|
|
|
|
|
|
const actionFullLogin = (login = 'tst', password = '123') =>
|
|
const actionFullLogin = (login = 'tst', password = '123') =>
|
|
async dispatch => {
|
|
async dispatch => {
|
|
@@ -153,12 +156,18 @@ const actionFullLogin = (login = 'tst', password = '123') =>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-const actionRegister = (login = 'tst', password = '123') =>
|
|
|
|
- actionPromise('login', gql(`mutation reg($login:String, $password:String) {
|
|
|
|
- UserUpsert(user:{login:$login, password:$password, nick:$login}){
|
|
|
|
- _id login
|
|
|
|
|
|
+const actionRegister = (login, password) =>
|
|
|
|
+ actionPromise('registration', gql(`
|
|
|
|
+ mutation register($login:String, $password:String) {
|
|
|
|
+ UserUpsert(
|
|
|
|
+ user: {
|
|
|
|
+ login: $login,
|
|
|
|
+ password: $password,
|
|
|
|
+ }){
|
|
|
|
+ login _id
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }`, { 'login': login, 'password': password }))
|
|
|
|
|
|
+ `, { login, password }))
|
|
|
|
|
|
const actionFullRegister = (login = 'tst', password = '123') =>
|
|
const actionFullRegister = (login = 'tst', password = '123') =>
|
|
async dispatch => {
|
|
async dispatch => {
|
|
@@ -181,13 +190,20 @@ const actionCatById = (_id) =>
|
|
}`, { q: JSON.stringify([{ _id }]) }))
|
|
}`, { q: JSON.stringify([{ _id }]) }))
|
|
|
|
|
|
const actionGoodById = (_id) =>
|
|
const actionGoodById = (_id) =>
|
|
- actionPromise('goodById', gql(`query ($good:String) {
|
|
|
|
- GoodFindOne(query:$good) {
|
|
|
|
- _id name price images {
|
|
|
|
- url
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }`, { good: JSON.stringify([{ _id }]) }))
|
|
|
|
|
|
+ actionPromise('goodById', gql(`
|
|
|
|
+ query goodById ($good:String) {
|
|
|
|
+ GoodFindOne(query: $good) {
|
|
|
|
+ name
|
|
|
|
+ description
|
|
|
|
+ price
|
|
|
|
+ categories {
|
|
|
|
+ name
|
|
|
|
+ }
|
|
|
|
+ images {
|
|
|
|
+ url
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }`, { good: JSON.stringify([{ _id }]) }))
|
|
|
|
|
|
|
|
|
|
const store = createStore(combineReducers({promise: promiseReducer,
|
|
const store = createStore(combineReducers({promise: promiseReducer,
|
|
@@ -195,7 +211,6 @@ const store = createStore(combineReducers({promise: promiseReducer,
|
|
cart: cartReducer}), applyMiddleware(thunk))
|
|
cart: cartReducer}), applyMiddleware(thunk))
|
|
store.subscribe(() => console.log(store.getState()))
|
|
store.subscribe(() => console.log(store.getState()))
|
|
store.dispatch(actionRootCats())
|
|
store.dispatch(actionRootCats())
|
|
-//store.dispatch(actionCatById('5dc458985df9d670df48cc47'))
|
|
|
|
|
|
|
|
|
|
|
|
const Logo = () =>
|
|
const Logo = () =>
|
|
@@ -212,12 +227,13 @@ const Navbar = () =>
|
|
<nav className='Navbar'>
|
|
<nav className='Navbar'>
|
|
<CKoshik/>
|
|
<CKoshik/>
|
|
<LogBtn />
|
|
<LogBtn />
|
|
|
|
+ <RegBtn />
|
|
</nav>
|
|
</nav>
|
|
-
|
|
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
const CategoryListItem = ({_id, name}) =>
|
|
const CategoryListItem = ({_id, name}) =>
|
|
- <li className='CatLink'>
|
|
|
|
- <Link to={`/category/:${_id}`}>{name}</Link>
|
|
|
|
- </li>
|
|
|
|
|
|
+ <Link to={`/category/:${_id}`}>
|
|
|
|
+ <li className='CatLink' style={{color:'dodgerblue'}}>{name}</li>
|
|
|
|
+ </Link>
|
|
|
|
|
|
const CategoryList = ({cats}) =>
|
|
const CategoryList = ({cats}) =>
|
|
<ul>{cats.map((item) => <CategoryListItem {...item}/>)}</ul>
|
|
<ul>{cats.map((item) => <CategoryListItem {...item}/>)}</ul>
|
|
@@ -226,13 +242,13 @@ const CCategoryList = connect(state => ({cats:state.promise.rootCats?.payload ||
|
|
|
|
|
|
const Aside = () =>
|
|
const Aside = () =>
|
|
<aside><CCategoryList /></aside>
|
|
<aside><CCategoryList /></aside>
|
|
-
|
|
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
const GoodCard = ({good:{_id, name, price, images}, onAdd}) =>
|
|
const GoodCard = ({good:{_id, name, price, images}, onAdd}) =>
|
|
<li className='GoodCard'>
|
|
<li className='GoodCard'>
|
|
<h2>{name}</h2>
|
|
<h2>{name}</h2>
|
|
- {images && images[0] && images[0].url && <img className='GoodImg' alt='img' src={backendURL + '/' + images[0].url} />}
|
|
|
|
|
|
+ <Link to={`/good/:${_id}`}>На страницу товара</Link>
|
|
<br/>
|
|
<br/>
|
|
- <button>На страницу товара</button>
|
|
|
|
|
|
+ {images && images[0] && images[0].url && <img className='GoodImg' alt='img' src={backendURL + '/' + images[0].url} />}
|
|
<br/>
|
|
<br/>
|
|
<strong>Цена: {price}</strong>
|
|
<strong>Цена: {price}</strong>
|
|
<br/>
|
|
<br/>
|
|
@@ -240,11 +256,45 @@ const GoodCard = ({good:{_id, name, price, images}, onAdd}) =>
|
|
</li>
|
|
</li>
|
|
|
|
|
|
const CGoodCard = connect(null, {onAdd: actionCartAdd})(GoodCard)
|
|
const CGoodCard = connect(null, {onAdd: actionCartAdd})(GoodCard)
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
+const GoodPg = ({good:{_id, name, price, images, description}, onAdd}) =>
|
|
|
|
+ <div className='GoodCard'>
|
|
|
|
+ <h2>{name}</h2>
|
|
|
|
+ <br/>
|
|
|
|
+ {images && images[0] && images[0].url && <img className='GoodImg' alt='img' src={backendURL + '/' + images[0].url} />}
|
|
|
|
+ <br/>
|
|
|
|
+ <strong>Цена: {price}</strong>
|
|
|
|
+ <br/>
|
|
|
|
+ <p>{description}</p>
|
|
|
|
+ <br />
|
|
|
|
+ <button onClick={() => onAdd({_id, name, price, images})}>Добавить в корзину</button>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+const CGoodPg = connect(state => ({good:state.promise.goodById?.payload || {}}),{onAdd: actionCartAdd})(GoodPg)
|
|
|
|
+
|
|
|
|
+const PageGood = ({match: {params: {_id}}, getData}) => {
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ getData(_id.substring(1))
|
|
|
|
+ console.log('get', _id,typeof _id)
|
|
|
|
+ },[_id])
|
|
|
|
+ return (
|
|
|
|
+ <CGoodPg />
|
|
|
|
+ )
|
|
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const CPageGood = connect(null, {getData: actionGoodById})(PageGood)
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
const LogBtn = () =>
|
|
const LogBtn = () =>
|
|
- <div className='KoshikCnt item'>
|
|
|
|
- <Link to="/login" style={{color:'white', textDecoration:'none'}}>Войти</Link>
|
|
|
|
- </div>
|
|
|
|
|
|
+ <Link to="/login" style={{color:'white', textDecoration:'none'}}>
|
|
|
|
+ <div className='KoshikCnt item'>Войти / Выйти</div>
|
|
|
|
+ </Link>
|
|
|
|
+
|
|
|
|
+const RegBtn = () =>
|
|
|
|
+ <Link to="/registration" style={{color:'white', textDecoration:'none'}}>
|
|
|
|
+ <div className='KoshikCnt item'>Зарегистрироваться</div>
|
|
|
|
+ </Link>
|
|
|
|
+
|
|
|
|
|
|
const Koshik = ({cart}) => {
|
|
const Koshik = ({cart}) => {
|
|
let goodsInCart = cart
|
|
let goodsInCart = cart
|
|
@@ -253,37 +303,53 @@ const Koshik = ({cart}) => {
|
|
allGoodsInCart += goodsInCart[key].count
|
|
allGoodsInCart += goodsInCart[key].count
|
|
}
|
|
}
|
|
return (
|
|
return (
|
|
- <div className='KoshikCnt item'>
|
|
|
|
- <Link to="/cart" style={{color:'white', textDecoration:'none'}}>Корзина: {allGoodsInCart}</Link>
|
|
|
|
- </div>
|
|
|
|
|
|
+ <Link to="/cart" style={{color:'white', textDecoration:'none'}}>
|
|
|
|
+ <div className='KoshikCnt item'>
|
|
|
|
+ Корзина: {allGoodsInCart}
|
|
|
|
+ </div>
|
|
|
|
+ </Link>
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
const CKoshik = connect(({cart}) => ({cart}))(Koshik)
|
|
const CKoshik = connect(({cart}) => ({cart}))(Koshik)
|
|
-
|
|
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
const Category = ({cat:{name, goods=[]}={}}) =>
|
|
const Category = ({cat:{name, goods=[]}={}}) =>
|
|
-<div className='Category'>
|
|
|
|
- <h1>{name}</h1>
|
|
|
|
- <ul>
|
|
|
|
- {(goods || []).map(good => <CGoodCard good={good} />)}
|
|
|
|
- </ul>
|
|
|
|
-</div>
|
|
|
|
|
|
+ <div className='Category'>
|
|
|
|
+ <h1>{name}</h1>
|
|
|
|
+ <ul>
|
|
|
|
+ {(goods || []).map(good => <CGoodCard good={good} />)}
|
|
|
|
+ </ul>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+const CCategory = connect(state => ({cat:state.promise.catById?.payload || {}}))(Category)
|
|
|
|
+
|
|
|
|
+const PageCategory = ({match: {params: {_id}}, getData}) => {
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ getData(_id.substring(1))
|
|
|
|
+ console.log('get', _id,typeof _id)
|
|
|
|
+ },[_id])
|
|
|
|
+ return (
|
|
|
|
+ <CCategory />
|
|
|
|
+ )
|
|
|
|
|
|
-const CCategory = connect(state => ({cat:state.promise.catById?.payload || {}}))
|
|
|
|
- (Category)
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
+const CPageCategory = connect(null, {getData: actionCatById})(PageCategory)
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
const CartItem = ({cart:{_id, name, price, images}, count: {count}, onChange, onRemove}) => {
|
|
const CartItem = ({cart:{_id, name, price, images}, count: {count}, onChange, onRemove}) => {
|
|
console.log('good', _id)
|
|
console.log('good', _id)
|
|
return(
|
|
return(
|
|
<li className='GoodCard'>
|
|
<li className='GoodCard'>
|
|
<h2>{name}</h2>
|
|
<h2>{name}</h2>
|
|
|
|
+ <Link to={`/good/:${_id}`}>На страницу товара</Link>
|
|
|
|
+ <br/>
|
|
{images && images[0] && images[0].url && <img className='GoodImg' alt='img' src={backendURL + '/' + images[0].url} />}
|
|
{images && images[0] && images[0].url && <img className='GoodImg' alt='img' src={backendURL + '/' + images[0].url} />}
|
|
<br/>
|
|
<br/>
|
|
<strong>Цена: {price * count}</strong>
|
|
<strong>Цена: {price * count}</strong>
|
|
<br/>
|
|
<br/>
|
|
<label>Кол-во покупки: <input type="number" value={count} min="1" onInput={(e) => onChange({_id, name, price, images}, e.target.value)}/></label>
|
|
<label>Кол-во покупки: <input type="number" value={count} min="1" onInput={(e) => onChange({_id, name, price, images}, e.target.value)}/></label>
|
|
<br/>
|
|
<br/>
|
|
- <button>Заказать</button>
|
|
|
|
|
|
+ <button disabled={!localStorage.authToken}>{localStorage.authToken? 'Заказать' : 'Авторизуйтесть чтобы заказать'}</button>
|
|
<button onClick={() => onRemove({_id, name, price, images})}>Удалить заказ[X]</button>
|
|
<button onClick={() => onRemove({_id, name, price, images})}>Удалить заказ[X]</button>
|
|
</li>
|
|
</li>
|
|
)
|
|
)
|
|
@@ -296,8 +362,6 @@ const Cart = ({cart}) => {
|
|
for(let item in cart) {
|
|
for(let item in cart) {
|
|
cartArr.push(cart[item])
|
|
cartArr.push(cart[item])
|
|
}
|
|
}
|
|
- console.log('cartarr',cartArr)
|
|
|
|
-
|
|
|
|
return(
|
|
return(
|
|
<div>
|
|
<div>
|
|
<h1 style={{marginLeft:'30px'}}>Корзина</h1>
|
|
<h1 style={{marginLeft:'30px'}}>Корзина</h1>
|
|
@@ -307,72 +371,67 @@ const Cart = ({cart}) => {
|
|
}
|
|
}
|
|
|
|
|
|
const CCart = connect(state => ({cart:state.cart}))(Cart)
|
|
const CCart = connect(state => ({cart:state.cart}))(Cart)
|
|
-
|
|
|
|
-const PageCart = ({match: {params: {_id}}, getData}) => {
|
|
|
|
- useEffect(() => {
|
|
|
|
- getData(_id.substring(1))
|
|
|
|
- console.log('get', _id,typeof _id)
|
|
|
|
- },[_id])
|
|
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
+const LoginForm = ({log:{sub}, onLogin, onLogout}) => {
|
|
|
|
+ let [pass, setPass] = useState()
|
|
|
|
+ let [login, setLogin] = useState()
|
|
return (
|
|
return (
|
|
- <CCart />
|
|
|
|
|
|
+ <div className='form' style={{margin: '0 auto'}}>
|
|
|
|
+ <h3>Войти</h3>
|
|
|
|
+ <input placeholder='Логин' style={{outlineColor: login? 'black' : 'firebrick'}} onChange={(e) => setLogin(e.target.value)}/>
|
|
|
|
+ <br/>
|
|
|
|
+ <input placeholder='Пароль' type="password" style={{outlineColor: pass? 'black' : 'firebrick'}} onChange={(e) => setPass(e.target.value)}/>
|
|
|
|
+ <br/>
|
|
|
|
+ <button disabled={!pass || !login || localStorage.authToken} onClick={() => onLogin(login, pass)}>{localStorage.authToken? 'Авторизация была выполнена.' : 'Войти'}</button>
|
|
|
|
+ {localStorage.authToken && <button onClick={() => onLogout()}>Выйти</button>}
|
|
|
|
+ <br/>
|
|
|
|
+ {sub && <small>Пользователь {sub.login} авторизован</small>}
|
|
|
|
+ </div>
|
|
)
|
|
)
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-const CPageCart= connect(null, {getData: actionCatById})(PageCart)
|
|
|
|
-//const CCart = connect(забрать из редакса корзину положить в пропс cart,
|
|
|
|
- //дать компоненту onCartChange и onCartRemove с соответствующими actionCreator)(Cart)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-const LoginForm = ({onLogin}) => {
|
|
|
|
|
|
+const CLoginForm = connect(state => ({log: state.auth?.payload || {}}), {onLogin: actionFullLogin, onLogout: actionAuthLogout})(LoginForm)
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
+const RegForm = ({reg:{login}, loged: {sub}, onRegister, onFullRegister}) => {
|
|
let [pass, setPass] = useState()
|
|
let [pass, setPass] = useState()
|
|
- let [login, setLogin] = useState()
|
|
|
|
|
|
+ let [log, setLog] = useState()
|
|
return (
|
|
return (
|
|
- <div className='form'>
|
|
|
|
- <h3>Login Form</h3>
|
|
|
|
- <input placeholder='login' style={{outlineColor: login? 'black' : 'firebrick'}} onChange={(e) => setLogin(e.target.value)}/>
|
|
|
|
|
|
+ <div className='form' style={{margin: '0 auto'}}>
|
|
|
|
+ <h3>Зарегистрироваться</h3>
|
|
|
|
+ <input placeholder='Логин' style={{outlineColor: log? 'black' : 'firebrick'}} onChange={(e) => setLog(e.target.value)}/>
|
|
|
|
+ <br/>
|
|
|
|
+ <input placeholder='Пароль' type="password" style={{outlineColor: pass? 'black' : 'firebrick'}} onChange={(e) => setPass(e.target.value)}/>
|
|
<br/>
|
|
<br/>
|
|
- <input placeholder='password' type="password" style={{outlineColor: pass? 'black' : 'firebrick'}} onChange={(e) => setPass(e.target.value)}/>
|
|
|
|
|
|
+ <button disabled={!pass || !log || localStorage.authToken} onClick={() => onRegister(log, pass)}>{localStorage.authToken? 'Авторизация была выполнена' : 'Зарегистрироваться'}</button>
|
|
<br/>
|
|
<br/>
|
|
- <button disabled={!pass || !login} onClick={() => onLogin(login, pass)}>Login</button>
|
|
|
|
|
|
+ {!localStorage.authToken && <button disabled={!pass || !log} onClick={() => {onFullRegister(log, pass); }}>Зарегистрироваться и Войти</button>}
|
|
|
|
+ <br/>
|
|
|
|
+ {login && `Пользователь ${login} зарегистрирован ${sub && 'и авторизован'}!`}
|
|
</div>
|
|
</div>
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
-const CLoginForm = connect(null, {onLogin: actionFullLogin})(LoginForm)
|
|
|
|
|
|
+const CRegForm = connect(state => ({reg: state.promise.registration?.payload || {}, loged: state.auth?.payload || {}}), {onRegister: actionRegister, onFullRegister: actionFullRegister})(RegForm)
|
|
|
|
+//--------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
-const PageMain = () => <h1>MAIN PAGE</h1>
|
|
|
|
|
|
|
|
-const PageCategory = ({match: {params: {_id}}, getData}) => {
|
|
|
|
- useEffect(() => {
|
|
|
|
- getData(_id.substring(1))
|
|
|
|
- console.log('get', _id,typeof _id)
|
|
|
|
- },[_id])
|
|
|
|
- return (
|
|
|
|
- <CCategory />
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-const CPageCategory = connect(null, {getData: actionCatById})(PageCategory)
|
|
|
|
|
|
+const PageMain = () => <h1>MAIN PAGE</h1>
|
|
|
|
|
|
const Page404 = () => <h1> 404 </h1>
|
|
const Page404 = () => <h1> 404 </h1>
|
|
|
|
|
|
const Main = () =>
|
|
const Main = () =>
|
|
<main>
|
|
<main>
|
|
<Aside />
|
|
<Aside />
|
|
- <Content>
|
|
|
|
|
|
+ <Content style={{border:'1px solid black'}}>
|
|
<Switch>
|
|
<Switch>
|
|
<Redirect from='/main' to='/' />
|
|
<Redirect from='/main' to='/' />
|
|
<Route path="/" component={PageMain} exact/>
|
|
<Route path="/" component={PageMain} exact/>
|
|
<Route path="/category/:_id" component={CPageCategory}/>
|
|
<Route path="/category/:_id" component={CPageCategory}/>
|
|
|
|
+ <Route path="/good/:_id" component={CPageGood}/>
|
|
<Route path="/cart" component={CCart} />
|
|
<Route path="/cart" component={CCart} />
|
|
|
|
+ <Route path="/login" component={CLoginForm} />
|
|
|
|
+ <Route path="/registration" component={CRegForm} />
|
|
<Route path="*" component={Page404} />
|
|
<Route path="*" component={Page404} />
|
|
-
|
|
|
|
- {/* <CCategory /> */}
|
|
|
|
- {/* <LoginForm onLogin={(l, p) => actionFullLogin(l, p)}/> */}
|
|
|
|
- {/* <CLoginForm /> */}
|
|
|
|
- {/* <CCart /> */}
|
|
|
|
</Switch>
|
|
</Switch>
|
|
</Content>
|
|
</Content>
|
|
</main>
|
|
</main>
|
|
@@ -380,11 +439,12 @@ const Main = () =>
|
|
const Content = ({children}) =>
|
|
const Content = ({children}) =>
|
|
<div className="Content">{children}</div>
|
|
<div className="Content">{children}</div>
|
|
|
|
|
|
|
|
+
|
|
const Footer = () =>
|
|
const Footer = () =>
|
|
<footer><Logo /></footer>
|
|
<footer><Logo /></footer>
|
|
|
|
|
|
-const history = createHistory()
|
|
|
|
|
|
|
|
|
|
+const history = createHistory()
|
|
|
|
|
|
|
|
|
|
function App() {
|
|
function App() {
|
|
@@ -396,7 +456,6 @@ function App() {
|
|
<Navbar />
|
|
<Navbar />
|
|
<Main />
|
|
<Main />
|
|
<Footer />
|
|
<Footer />
|
|
- {/* <CCart /> */}
|
|
|
|
</div>
|
|
</div>
|
|
</Provider>
|
|
</Provider>
|
|
</Router>
|
|
</Router>
|