- initial;
This commit is contained in:
30
src/App.js
Normal file
30
src/App.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import Routes from './routes';
|
||||
import { createI18n, setLocaleData } from '@wordpress/i18n';
|
||||
import { I18nProvider } from '@wordpress/react-i18n';
|
||||
|
||||
const i18n = createI18n();
|
||||
|
||||
function App() {
|
||||
const [messages, setMessages] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
/*import('../languages/en_US.json').then((translations) => {
|
||||
setLocaleData(translations, 'gepafin');
|
||||
});*/
|
||||
fetch('/languages/en_US.json')
|
||||
.then((res) => res.json())
|
||||
.then(res => console.log(res))
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<I18nProvider i18n={i18n}>
|
||||
<BrowserRouter>
|
||||
<Routes/>
|
||||
</BrowserRouter>
|
||||
</I18nProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
3
src/assets/scss/theme.scss
Normal file
3
src/assets/scss/theme.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
body {
|
||||
background-color: moccasin;
|
||||
}
|
||||
28
src/components/ProtectedRoute/index.js
Normal file
28
src/components/ProtectedRoute/index.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
|
||||
// tools
|
||||
import AuthenticationService from '../../service/authentication-service';
|
||||
|
||||
const ProtectedRoute = () => {
|
||||
|
||||
if (!AuthenticationService.wasLoggedIn()) {
|
||||
return (<Navigate to={'/login'} replace/>);
|
||||
}
|
||||
|
||||
if (AuthenticationService.isExpired()) {
|
||||
return (<Navigate to={'/login?redirectReason=expired'} replace/>);
|
||||
}
|
||||
|
||||
if (!AuthenticationService.isLoggedIn()) {
|
||||
return (<Navigate to={'/login?redirectReason=auth_required'} replace/>);
|
||||
}
|
||||
|
||||
if (window.location.pathname === '/') {
|
||||
return (<Navigate to={'/pages/dashboard'} replace/>);
|
||||
}
|
||||
|
||||
return <Outlet/>;
|
||||
}
|
||||
|
||||
export default ProtectedRoute;
|
||||
1
src/index.css
Normal file
1
src/index.css
Normal file
@@ -0,0 +1 @@
|
||||
@import './assets/scss/theme.scss';
|
||||
15
src/index.js
Normal file
15
src/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
|
||||
const rootEl = document.getElementById('root');
|
||||
const rootReact = createRoot(rootEl);
|
||||
|
||||
rootReact.render(
|
||||
<React.StrictMode>
|
||||
<App/>
|
||||
</React.StrictMode>
|
||||
);
|
||||
14
src/layouts/DefaultLayout/index.js
Normal file
14
src/layouts/DefaultLayout/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
|
||||
const DefaultLayout = ({ children }) => {
|
||||
return(
|
||||
<div>
|
||||
<div>
|
||||
Top bar
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DefaultLayout;
|
||||
11
src/pages/Dashboard/index.js
Normal file
11
src/pages/Dashboard/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
const Dashboard = () => {
|
||||
return(
|
||||
<div>
|
||||
Dashboard - main data
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dashboard;
|
||||
12
src/pages/Login/index.js
Normal file
12
src/pages/Login/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const Login = () => {
|
||||
return(
|
||||
<div>
|
||||
{__('Login page', 'gepafin')}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Login;
|
||||
11
src/pages/PageNotFound/index.js
Normal file
11
src/pages/PageNotFound/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
const PageNotFound = () => {
|
||||
return(
|
||||
<div>
|
||||
Page not found
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PageNotFound;
|
||||
20
src/routes.js
Normal file
20
src/routes.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
|
||||
// components
|
||||
import PageNotFound from './pages/PageNotFound';
|
||||
import Login from './pages/Login';
|
||||
import ProtectedRoute from './components/ProtectedRoute';
|
||||
import Dashboard from './pages/Dashboard';
|
||||
import DefaultLayout from './layouts/DefaultLayout';
|
||||
|
||||
const routes = () => (
|
||||
<Routes>
|
||||
<Route element={<ProtectedRoute/>}>
|
||||
<Route path="/" element={<DefaultLayout><Dashboard/></DefaultLayout>}/>
|
||||
</Route>
|
||||
<Route exact path="/login" element={<Login/>}/>
|
||||
{/*<Route exact path="/forgot-password" element={<ForgotPassword/>}/>*/}
|
||||
<Route path="*" element={<PageNotFound/>}/>
|
||||
</Routes>);
|
||||
|
||||
export default routes;
|
||||
79
src/service/authentication-service.js
Normal file
79
src/service/authentication-service.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { NetworkService } from './network-service';
|
||||
import { jwtDecode } from 'jwt-decode';
|
||||
|
||||
// store
|
||||
import { storeGet } from '../store';
|
||||
|
||||
const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS;
|
||||
|
||||
export default class AuthenticationService {
|
||||
|
||||
static wasLoggedIn = () => {
|
||||
const token = storeGet.main.getToken();
|
||||
return token ?? false;
|
||||
};
|
||||
|
||||
static isExpired = () => {
|
||||
const token = storeGet.main.getToken();
|
||||
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let decoded = jwtDecode(token);
|
||||
|
||||
if (!decoded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let currentTs = new Date().getTime();
|
||||
|
||||
if (currentTs >= (decoded.exp * 1000)) {
|
||||
return true; //FIXME: try refresh
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
static isLoggedIn = () => {
|
||||
const token = storeGet.main.getToken();
|
||||
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let decoded = jwtDecode(token);
|
||||
|
||||
if (!decoded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let currentTs = new Date().getTime();
|
||||
|
||||
if (currentTs >= decoded.exp * 1000) {
|
||||
return false; //FIXME: try refresh
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
static login = (loginRequest, callback, errCallback) => {
|
||||
NetworkService.unauthorizedPost(`${API_BASE_URL}/user/login/`, loginRequest, callback, errCallback);
|
||||
};
|
||||
|
||||
static registerUser = (registerRequest, callback, errCallback) => {
|
||||
NetworkService.post(`${API_BASE_URL}/user/register/`, registerRequest, callback, errCallback);
|
||||
};
|
||||
|
||||
static forgotPassword = (request, callback, errCallback) => {
|
||||
NetworkService.unauthorizedPost(`${API_BASE_URL}/user/reset_password_request/?email=` + request, {}, callback, errCallback);
|
||||
}
|
||||
|
||||
static checkTokenForgotPassword = (request, callback, errCallback) => {
|
||||
NetworkService.unauthorizedGet(`${API_BASE_URL}/user/reset_token_check/?token=` + request, {}, callback, errCallback);
|
||||
}
|
||||
|
||||
static changePassword = (request, callback, errCallback) => {
|
||||
NetworkService.unauthorizedPatch(`${API_BASE_URL}/user/reset_password/`, request, callback, errCallback);
|
||||
}
|
||||
}
|
||||
374
src/service/network-service.js
Normal file
374
src/service/network-service.js
Normal file
@@ -0,0 +1,374 @@
|
||||
import { storeGet } from '../store';
|
||||
|
||||
export class NetworkService {
|
||||
static TOKEN_KEY
|
||||
static REFRESH_TOKEN_KEY
|
||||
|
||||
static postEmptyResponse = (url, body, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': storeGet.main.getToken(),
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.status)
|
||||
else
|
||||
callback()
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
};
|
||||
|
||||
static putEmptyResponse = (url, body, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'PUT',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': storeGet.main.getToken(),
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.status)
|
||||
else
|
||||
callback()
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
};
|
||||
|
||||
static post = (url, body, callback, errorCallback, queryParams) => {
|
||||
|
||||
if (queryParams) {
|
||||
url += '?'
|
||||
for (let i = 0; i < queryParams.length; i++) {
|
||||
if (queryParams[i] && this.isNotBlank(queryParams[i][0]) && this.isNotBlank(queryParams[i][1])) {
|
||||
let param = queryParams[i][0] + '=' + queryParams[i][1]
|
||||
|
||||
if (i !== queryParams.length - 1)
|
||||
param += '&'
|
||||
|
||||
url += param;
|
||||
}
|
||||
}
|
||||
|
||||
if (url.charAt(url.length) === '&')
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + storeGet.main.getToken(),
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.response)
|
||||
else
|
||||
callback(data.response)
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
};
|
||||
|
||||
static unauthorizedPost = (url, body, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.response)
|
||||
else
|
||||
callback(data.response)
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
};
|
||||
|
||||
static patch = (url, body, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'PATCH',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.response)
|
||||
else
|
||||
callback(data.response)
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
};
|
||||
|
||||
static put = (url, body, callback, errorCallback, queryParams = null) => {
|
||||
if (queryParams) {
|
||||
url += '?'
|
||||
|
||||
for (let i = 0; i < queryParams.length; i++) {
|
||||
if (queryParams[i] && this.isNotBlank(queryParams[i][0]) && this.isNotBlank(queryParams[i][1])) {
|
||||
let param = queryParams[i][0] + '=' + queryParams[i][1]
|
||||
|
||||
if (i !== queryParams.length - 1)
|
||||
param += '&'
|
||||
|
||||
url += param;
|
||||
}
|
||||
}
|
||||
|
||||
if (url.charAt(url.length) === '&')
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method: 'PUT',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + storeGet.main.getToken(),
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.response)
|
||||
else
|
||||
callback(data.response)
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
};
|
||||
|
||||
static unauthorizedPostEmptyResponse = (url, body, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(data => callback(data))
|
||||
.catch(err => errorCallback(err));
|
||||
|
||||
};
|
||||
|
||||
static unauthorizedPutEmptyResponse = (url, body, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(data => callback(data))
|
||||
.catch(err => errorCallback(err));
|
||||
|
||||
};
|
||||
|
||||
static unauthorizedGet = (url, queryParams, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.response)
|
||||
else
|
||||
callback(data.response)
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
|
||||
};
|
||||
|
||||
static unauthorizedPatch = (url, body, callback, errorCallback) => {
|
||||
fetch(url, {
|
||||
method: 'PATCH',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.response)
|
||||
else
|
||||
callback(data.response)
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
|
||||
};
|
||||
|
||||
static isNotBlank(value) {
|
||||
return value !== null && value !== undefined && value !== ''
|
||||
}
|
||||
|
||||
static get = (url, callback, errorCallback, queryParams = null) => {
|
||||
if (queryParams) {
|
||||
url += '?'
|
||||
|
||||
for (let i = 0; i < queryParams.length; i++) {
|
||||
if (queryParams[i] && this.isNotBlank(queryParams[i][0]) && this.isNotBlank(queryParams[i][1])) {
|
||||
let param = queryParams[i][0] + '=' + queryParams[i][1]
|
||||
|
||||
if (i !== queryParams.length - 1)
|
||||
param += '&'
|
||||
|
||||
url += param;
|
||||
}
|
||||
}
|
||||
|
||||
if (url.charAt(url.length) === '&')
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + storeGet.main.getToken(),
|
||||
}
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599) {
|
||||
errorCallback(data.response)
|
||||
} else {
|
||||
callback(data.response)
|
||||
}
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
|
||||
};
|
||||
|
||||
static promiseGet = async (url, queryParams = null) => {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + storeGet.main.getToken(),
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
}
|
||||
});
|
||||
|
||||
const json = await response.json();
|
||||
return json;
|
||||
}
|
||||
|
||||
static deleteEmptyResponse = (url, callback, errorCallback, queryParams = null) => {
|
||||
if (queryParams) {
|
||||
let params = '?'
|
||||
|
||||
for (let i = 0; i < queryParams.length; i++) {
|
||||
params += queryParams[i][0] + '=' + queryParams[i][1]
|
||||
if (queryParams.length !== i + 1)
|
||||
params += '&'
|
||||
url += params
|
||||
params = ''
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fetch(url, {
|
||||
method: 'DELETE',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': storeGet.main.getToken(),
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.status)
|
||||
else
|
||||
callback()
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
}
|
||||
|
||||
static delete = (url, body, callback, errorCallback, queryParams = null) => {
|
||||
if (queryParams) {
|
||||
let params = '?'
|
||||
|
||||
for (let i = 0; i < queryParams.length; i++) {
|
||||
params += queryParams[i][0] + '=' + queryParams[i][1]
|
||||
if (queryParams.length !== i + 1)
|
||||
params += '&'
|
||||
url += params
|
||||
params = ''
|
||||
}
|
||||
|
||||
}
|
||||
fetch(url, {
|
||||
method: 'DELETE',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + storeGet.main.getToken(),
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(async response => {
|
||||
let status = response.status;
|
||||
return { response: await response.json(), status: status }
|
||||
})
|
||||
.then(data => {
|
||||
if (data.status >= 400 && data.status <= 599)
|
||||
errorCallback(data.response)
|
||||
else
|
||||
callback(data.response)
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
|
||||
};
|
||||
}
|
||||
16
src/setupProxy.js
Normal file
16
src/setupProxy.js
Normal file
@@ -0,0 +1,16 @@
|
||||
//made available by http-proxy-middleware
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||||
|
||||
module.exports = function(app) {
|
||||
|
||||
app.use(
|
||||
createProxyMiddleware(
|
||||
"/api",
|
||||
{
|
||||
target: 'https://localhost:8000/',
|
||||
changeOrigin: true,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
};
|
||||
15
src/store/actions.js
Normal file
15
src/store/actions.js
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
|
||||
export const actionsAlpha = (set, get, api) => ({
|
||||
setAsyncRequest: () => {
|
||||
const num = get.isAsyncRequest();
|
||||
set.isAsyncRequest(num + 1);
|
||||
},
|
||||
unsetAsyncRequest: () => {
|
||||
const num = get.isAsyncRequest();
|
||||
set.isAsyncRequest(num - 1 < 0 ? 0 : num - 1);
|
||||
},
|
||||
})
|
||||
|
||||
export const actionsBeta = (set, get, api) => ({
|
||||
});
|
||||
20
src/store/index.js
Normal file
20
src/store/index.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { mapValuesKey } from 'zustand-x';
|
||||
|
||||
// stores
|
||||
import { mainStore } from './main';
|
||||
|
||||
// Global store - initial data
|
||||
const dashboardStore = {
|
||||
main: mainStore
|
||||
};
|
||||
|
||||
// Global hook selectors
|
||||
export const useStore = () => mapValuesKey('use', dashboardStore);
|
||||
// Global tracked hook selectors
|
||||
export const useTrackedStore = () => mapValuesKey('useTracked', dashboardStore);
|
||||
// Global getter selectors
|
||||
export const storeGet = mapValuesKey('get', dashboardStore);
|
||||
// Global actions
|
||||
export const storeSet = mapValuesKey('set', dashboardStore);
|
||||
|
||||
export default dashboardStore;
|
||||
6
src/store/initial.js
Normal file
6
src/store/initial.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const initialStore = {
|
||||
// ui related
|
||||
isAsyncRequest: 0, // number
|
||||
}
|
||||
|
||||
export default initialStore;
|
||||
11
src/store/main.js
Normal file
11
src/store/main.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { createStore } from 'zustand-x';
|
||||
|
||||
import zustandXOpts from './zustand-x-opts';
|
||||
import initialStore from './initial';
|
||||
import selectors from './selectors';
|
||||
import { actionsAlpha, actionsBeta } from './actions';
|
||||
|
||||
export const mainStore = createStore('main')(initialStore, zustandXOpts)
|
||||
.extendSelectors(selectors)
|
||||
.extendActions(actionsAlpha)
|
||||
.extendActions(actionsBeta);
|
||||
10
src/store/selectors.js
Normal file
10
src/store/selectors.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { isEmpty } from 'ramda';
|
||||
|
||||
const selectors = (state, get, api) => ({
|
||||
getToken: () => {
|
||||
const userData = get.userData();
|
||||
return userData.access && !isEmpty(userData.access) ? userData.access : null;
|
||||
},
|
||||
})
|
||||
|
||||
export default selectors;
|
||||
16
src/store/zustand-x-opts.js
Normal file
16
src/store/zustand-x-opts.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const zustandXOpts = {
|
||||
devtools: {
|
||||
enabled: true
|
||||
},
|
||||
persist: {
|
||||
enabled: true,
|
||||
partialize: (state) => ({
|
||||
userData: state.userData,
|
||||
hubsList: state.hubsList,
|
||||
chosenHub: state.chosenHub,
|
||||
groups: state.groups,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
export default zustandXOpts;
|
||||
Reference in New Issue
Block a user