|
@@ -1,15 +1,19 @@
|
|
|
import './App.scss';
|
|
|
-import { Router, Route } from 'react-router-dom';
|
|
|
+import { Router, Route, Redirect } from 'react-router-dom';
|
|
|
import createHistory from "history/createBrowserHistory";
|
|
|
import { Provider } from 'react-redux';
|
|
|
import { Header } from './components/header/Header';
|
|
|
import { Main } from './components/main/Main';
|
|
|
import { Footer } from './components/Footer';
|
|
|
-import { store } from './redux-Store/redux-Store'
|
|
|
+import { backURL, store } from './redux-Store/redux-Store'
|
|
|
import { actionPromise } from './redux-Store/promiseReducer'
|
|
|
import { gql } from './redux-Store/redux-Store'
|
|
|
import { CLoginForm } from './components/authorization/LoginForm';
|
|
|
import { CRegisterForm } from './components/authorization/RegisterForm';
|
|
|
+import { connect } from 'react-redux';
|
|
|
+import { useCallback } from 'react';
|
|
|
+import { useDropzone } from 'react-dropzone';
|
|
|
+import { useState } from 'react';
|
|
|
|
|
|
const actionRootCats = () =>
|
|
|
actionPromise('rootCats', gql(`query {
|
|
@@ -18,17 +22,159 @@ const actionRootCats = () =>
|
|
|
}
|
|
|
}`))
|
|
|
|
|
|
+export function routeReducer(state = {}, { type, match }) {
|
|
|
+ if (type === 'ROUTE') {
|
|
|
+ return match
|
|
|
+ }
|
|
|
+ return state
|
|
|
+}
|
|
|
+
|
|
|
+const RRoute = ({ action, component: Component, ...routeProps }) => {
|
|
|
+ const WrapperComponent = (componentProps) => {
|
|
|
+ action(componentProps.match)
|
|
|
+ return <Component {...componentProps} />
|
|
|
+ }
|
|
|
+ return < Route {...routeProps} component={WrapperComponent} />
|
|
|
+}
|
|
|
+
|
|
|
+const CRRoute = connect(null, { action: match => ({ type: 'ROUTE', match }) })(RRoute)
|
|
|
+
|
|
|
+const ProtectedRoute = ({
|
|
|
+ fallback = '/',
|
|
|
+ roles = ["admin"],
|
|
|
+ auth,
|
|
|
+ component: Component,
|
|
|
+ ...routeProps
|
|
|
+}) => {
|
|
|
+ const WrapperComponent = ({ componentProps }) => {
|
|
|
+ const acl = auth?.payload?.sub?.acl || ['anon']
|
|
|
+ const newArr = roles.filter(r => acl.includes(r))
|
|
|
+ return newArr.length !== 0 ? < Component {...componentProps} /> : <Redirect to='/' />
|
|
|
+
|
|
|
+ }
|
|
|
+ return <CRRoute {...routeProps} component={WrapperComponent} />
|
|
|
+}
|
|
|
+
|
|
|
+export const CPRoute = connect(state => ({ auth: state.auth }))(ProtectedRoute)
|
|
|
+
|
|
|
+const queries = {
|
|
|
+ "/good/:_id": match => ({
|
|
|
+ name: 'goodById',
|
|
|
+ query: `query goodById($q: String) {
|
|
|
+ GoodFindOne(query: $q) {
|
|
|
+ _id name price description images {
|
|
|
+ url
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }`,
|
|
|
+ variables: { q: JSON.stringify([{ _id: match.params._id }]) }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+export const actionGoodById = ({ match }) =>
|
|
|
+ async dispatch => {
|
|
|
+ console.log(match)
|
|
|
+ if (match.path in queries) {
|
|
|
+ const { name, query, variables } = queries[match.path](match)
|
|
|
+ await dispatch(actionPromise(name, gql(query, variables)))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
store.subscribe(() => console.log(store.getState()))
|
|
|
store.dispatch(actionRootCats())
|
|
|
|
|
|
export const history = createHistory()
|
|
|
|
|
|
+export const actionAboutMe = (_id) =>
|
|
|
+ async dispatch => {
|
|
|
+ await dispatch(actionPromise('dataProfileAuth', gql(`query userOned($id:String){
|
|
|
+ UserFindOne(query: $id){
|
|
|
+ _id
|
|
|
+
|
|
|
+ avatar { _id url }
|
|
|
+
|
|
|
+ }
|
|
|
+ }`, { id: JSON.stringify([{ _id }]) })))
|
|
|
+ }
|
|
|
+
|
|
|
+const actionUploadFile = (file) => {
|
|
|
+ let fd = new FormData()
|
|
|
+ fd.append('photo', file)
|
|
|
+ return actionPromise('upload', fetch(`${backURL}/upload`, {
|
|
|
+ method: "POST",
|
|
|
+ headers: localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } : {},
|
|
|
+ body: fd
|
|
|
+ }).then(res => res.json()))
|
|
|
+}
|
|
|
+
|
|
|
+const actionSetAvatar = file =>
|
|
|
+ async (dispatch, getState) => {
|
|
|
+ const result = await dispatch(actionUploadFile(file))
|
|
|
+ if (result) {
|
|
|
+ const { auth: { payload: { sub: { id } } } } = getState()
|
|
|
+ console.log(result);
|
|
|
+ await dispatch(actionPromise('uploadPhoto', gql(`mutation setUserAvatar($avar: UserInput){
|
|
|
+ UserUpsert(user: $avar){
|
|
|
+ _id avatar {_id}
|
|
|
+ }
|
|
|
+}`, { avar: { _id: id, avatar: { _id: result._id } } }))
|
|
|
+ )
|
|
|
+ await dispatch(actionAboutMe(id))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+function MyDropzone({ onUpload }) {
|
|
|
+ const onDrop = useCallback(acceptedFiles => {
|
|
|
+ onUpload(acceptedFiles[0])
|
|
|
+ }, [])
|
|
|
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop })
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div {...getRootProps()}>
|
|
|
+ <input {...getInputProps()} />
|
|
|
+ {
|
|
|
+ isDragActive ?
|
|
|
+ <p>Drop the files here ...</p> :
|
|
|
+ <p>Drag 'n' drop some files here, or click to select files</p>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const useLocalStoredState = (defaultState, localStorageName) => {
|
|
|
+ let inputJson
|
|
|
+ try {
|
|
|
+ inputJson = JSON.parse(localStorage.getItem(localStorageName))
|
|
|
+ } catch (err) {
|
|
|
+ console.error(err)
|
|
|
+ localStorage.removeItem(localStorageName)
|
|
|
+ }
|
|
|
+ const [state, setState] = useState(inputJson || defaultState)
|
|
|
+
|
|
|
+ return [state, newState => {
|
|
|
+ setState(newState)
|
|
|
+ localStorage.setItem(localStorageName, JSON.stringify(newState))
|
|
|
+ }]
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const CMyDropzone = connect(null, { onUpload: actionSetAvatar })(MyDropzone)
|
|
|
+
|
|
|
+
|
|
|
function App() {
|
|
|
return (
|
|
|
<Router history={history}>
|
|
|
<Provider store={store}>
|
|
|
<div className="App">
|
|
|
+ <CMyDropzone />
|
|
|
<Header />
|
|
|
<Main />
|
|
|
<Footer />
|