parent
6252e66372
commit
01d8fba0fd
@ -1,9 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import { render, screen } from '@testing-library/react'; |
|
||||||
import App from './App'; |
|
||||||
|
|
||||||
test('renders learn react link', () => { |
|
||||||
render(<App />); |
|
||||||
const linkElement = screen.getByText(/learn react/i); |
|
||||||
expect(linkElement).toBeInTheDocument(); |
|
||||||
}); |
|
@ -1,26 +1,71 @@ |
|||||||
import React from 'react'; |
import 'bootstrap/dist/css/bootstrap.min.css' |
||||||
import logo from './logo.svg'; |
import { BrowserRouter, Link, Navigate, Outlet, Route, Routes } from 'react-router-dom' |
||||||
import './App.css'; |
import './App.css' |
||||||
|
import DSAuth from '../src/Services/Auth/Auth.Services' |
||||||
|
import { Login } from './Components/Login/Login' |
||||||
|
import { RptViajesPendientes } from './Components/Reportes/RptViajesPendientes' |
||||||
|
import { Home } from './Components/Home/Home' |
||||||
|
import { Protected } from './Components/Home/Protected/Protected' |
||||||
|
import { useEffect } from 'react' |
||||||
|
import ProtectedRoute, { ProtectedRouteProps } from './Components/ProtectedRoute/ProtectedRoute' |
||||||
|
|
||||||
function App() { |
function App() { |
||||||
|
const Userlogued = (): boolean => { |
||||||
|
DSAuth.Validate() |
||||||
|
.then((response) => { |
||||||
|
console.log('Crednciales validas') |
||||||
|
return true |
||||||
|
}) |
||||||
|
.catch((e: Error) => { |
||||||
|
console.log('Credenciales apocrifas') |
||||||
|
return false |
||||||
|
}) |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
Userlogued() |
||||||
|
console.log('Entro al proceso de router') |
||||||
|
}, []) |
||||||
|
|
||||||
|
function PageNotFound() { |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<h2>Sorry, no matching page</h2> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const ProtectedRoute = ({ auth = false, redirectPath = '/login' }) => { |
||||||
|
if (!auth) { |
||||||
|
return <Navigate to={redirectPath} replace /> |
||||||
|
} |
||||||
|
|
||||||
|
return <Outlet /> |
||||||
|
} |
||||||
|
|
||||||
return ( |
return ( |
||||||
<div className="App"> |
<div className='App'> |
||||||
<header className="App-header"> |
<BrowserRouter> |
||||||
<img src={logo} className="App-logo" alt="logo" /> |
<Link to='login'>login</Link> |
||||||
<p> |
<br /> |
||||||
Edit <code>src/App.tsx</code> and save to reload. |
<Link to='RptViajesPendientes'>Reporte de viajes</Link> |
||||||
</p> |
<Routes> |
||||||
<a |
<Route path='/' element={<Home />}></Route> |
||||||
className="App-link" |
<Route path='login' element={<Login />}></Route> |
||||||
href="https://reactjs.org" |
<Route element={<ProtectedRoute auth={Userlogued()} />}> |
||||||
target="_blank" |
<Route path='RptViajesPendientes' element={<RptViajesPendientes />} /> |
||||||
rel="noopener noreferrer" |
</Route> |
||||||
> |
<Route path='*' element={<PageNotFound />} /> |
||||||
Learn React |
</Routes> |
||||||
</a> |
</BrowserRouter> |
||||||
</header> |
|
||||||
</div> |
</div> |
||||||
); |
) |
||||||
} |
} |
||||||
|
|
||||||
export default App; |
export default App |
||||||
|
|
||||||
|
/* export default App |
||||||
|
function useSessionContext(): [any, any] { |
||||||
|
throw new Error('Function not implemented.') |
||||||
|
} */ |
||||||
|
@ -0,0 +1,13 @@ |
|||||||
|
import React, { FC } from 'react' |
||||||
|
import { Outlet } from 'react-router-dom' |
||||||
|
|
||||||
|
interface IProps {} |
||||||
|
|
||||||
|
export const Home: FC<IProps> = (props) => { |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<h1>This is the Guest Layout Page</h1> |
||||||
|
<Outlet /> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
import React, { FC } from 'react' |
||||||
|
|
||||||
|
interface IProps {} |
||||||
|
|
||||||
|
/** |
||||||
|
* @author |
||||||
|
* @function @Protected |
||||||
|
**/ |
||||||
|
|
||||||
|
export const Protected: FC<IProps> = (props) => { |
||||||
|
return <div>Protected</div> |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
import { FC, useEffect, useState } from 'react' |
||||||
|
import { Navigate, useNavigate } from 'react-router-dom' |
||||||
|
import IAuth from '../../Interfaces/Auth/IAuth' |
||||||
|
import DSAuth from '../../Services/Auth/Auth.Services' |
||||||
|
|
||||||
|
interface IProps {} |
||||||
|
|
||||||
|
export const Login: FC<IProps> = (props) => { |
||||||
|
const navigate = useNavigate() |
||||||
|
const [Usuario, setUsuario] = useState('') |
||||||
|
const [Contrasena, setContrasena] = useState('') |
||||||
|
const [token, setToken] = useState<string>( |
||||||
|
(window.localStorage.getItem('token') ? window.localStorage.getItem('token') : '')! |
||||||
|
) |
||||||
|
|
||||||
|
const Login = () => { |
||||||
|
const data: IAuth = { |
||||||
|
usuario: Usuario, |
||||||
|
contrasena: Contrasena, |
||||||
|
} |
||||||
|
DSAuth.login(data) |
||||||
|
.then((response) => { |
||||||
|
localStorage.setItem('token', response.data.token) |
||||||
|
setToken(response.data.token) |
||||||
|
window.location.href = 'http://localhost:3000/login' |
||||||
|
}) |
||||||
|
.catch((e: Error) => { |
||||||
|
alert('Credeciales invalidas!') |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
const ValidateToken = () => { |
||||||
|
if (token.length > 10) { |
||||||
|
DSAuth.Validate() |
||||||
|
.then((response) => { |
||||||
|
navigate('../RptViajesPendientes', { replace: true }) |
||||||
|
}) |
||||||
|
.catch((e: Error) => { |
||||||
|
// navigate('login', { replace: true })
|
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
ValidateToken() |
||||||
|
}, []) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
ValidateToken() |
||||||
|
}, []) |
||||||
|
|
||||||
|
return ( |
||||||
|
<div> |
||||||
|
{token && <Navigate to='RptViajesPendientes' replace={true} />} |
||||||
|
<div className='Auth-form-container'> |
||||||
|
<form className='Auth-form'> |
||||||
|
<div className='Auth-form-content'> |
||||||
|
<h3 className='Auth-form-title'>AOL</h3> |
||||||
|
<div className='form-group mt-3'> |
||||||
|
<label>Usuario</label> |
||||||
|
<input |
||||||
|
type='email' |
||||||
|
className='form-control mt-1' |
||||||
|
placeholder='Usuario' |
||||||
|
onChange={(e) => { |
||||||
|
setUsuario(e.target.value) |
||||||
|
}} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
<div className='form-group mt-3'> |
||||||
|
<label>Contraseña</label> |
||||||
|
<input |
||||||
|
type='password' |
||||||
|
className='form-control mt-1' |
||||||
|
placeholder='Contraseña' |
||||||
|
onChange={(e) => { |
||||||
|
setContrasena(e.target.value) |
||||||
|
}} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
<div className='d-grid gap-2 mt-3'> |
||||||
|
<button |
||||||
|
type='button' |
||||||
|
className='btn btn-primary' |
||||||
|
onClick={() => { |
||||||
|
Login() |
||||||
|
}} |
||||||
|
> |
||||||
|
login |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
import { useEffect } from 'react' |
||||||
|
import { Navigate, useLocation } from 'react-router' |
||||||
|
|
||||||
|
export type ProtectedRouteProps = { |
||||||
|
isAuthenticated: boolean |
||||||
|
authenticationPath: string |
||||||
|
redirectPath: string |
||||||
|
setRedirectPath: (path: string) => void |
||||||
|
outlet: JSX.Element |
||||||
|
} |
||||||
|
|
||||||
|
export default function ProtectedRoute({ |
||||||
|
isAuthenticated, |
||||||
|
authenticationPath, |
||||||
|
redirectPath, |
||||||
|
setRedirectPath, |
||||||
|
outlet, |
||||||
|
}: ProtectedRouteProps) { |
||||||
|
const currentLocation = useLocation() |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (!isAuthenticated) { |
||||||
|
setRedirectPath(currentLocation.pathname) |
||||||
|
} |
||||||
|
}, [isAuthenticated, setRedirectPath, currentLocation]) |
||||||
|
|
||||||
|
if (isAuthenticated && redirectPath === currentLocation.pathname) { |
||||||
|
return outlet |
||||||
|
} else { |
||||||
|
return <Navigate to={{ pathname: isAuthenticated ? redirectPath : authenticationPath }} /> |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
import React, { FC } from 'react' |
||||||
|
|
||||||
|
interface IProps {} |
||||||
|
|
||||||
|
export const RptViajesPendientes: FC<IProps> = (props) => { |
||||||
|
return <div>RptViajesPendientes</div> |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
export class TargetURL { |
||||||
|
get() { |
||||||
|
return (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') ? "https://localhost:7000/api" : "http://reportes.gemcousa.com:5000/api" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
export default interface IAuth { |
||||||
|
usuario: string, |
||||||
|
contrasena: string |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
export default interface IMenu { |
||||||
|
id: number, |
||||||
|
descripcion: string, |
||||||
|
padreId: number, |
||||||
|
posicion: number, |
||||||
|
url: string |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
import IMenu from "./IMenu"; |
||||||
|
|
||||||
|
export default interface IPermisos { |
||||||
|
menu : IMenu[], |
||||||
|
token: string |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
import http from "../../Services/Auth/config/http-common"; |
||||||
|
import IAuth from "../../Interfaces/Auth/IAuth" |
||||||
|
//import ItemMenuData from "../../Interfaces/Auth/IMenu";
|
||||||
|
import IPermisos from "../../Interfaces/Auth/IPermisos"; |
||||||
|
//import Token from '../../Interfaces/token'
|
||||||
|
|
||||||
|
class authDataService { |
||||||
|
login(data: IAuth) { |
||||||
|
return http.post<IPermisos>("Auth/Login", data); |
||||||
|
} |
||||||
|
Validate() { |
||||||
|
return http.get<String>("Auth/Validate"); |
||||||
|
} |
||||||
|
} |
||||||
|
export default new authDataService(); |
@ -0,0 +1,52 @@ |
|||||||
|
import axios from "axios"; |
||||||
|
import { TargetURL } from '../../../Constants/TargetURL' |
||||||
|
const token = localStorage.getItem("token"); |
||||||
|
const URL = new TargetURL() |
||||||
|
|
||||||
|
const instance = axios.create({ |
||||||
|
baseURL: URL.get(), |
||||||
|
headers: { |
||||||
|
"Content-type": "application/json", |
||||||
|
"Authorization": (token) ? `Bearer ${token}` : ''
|
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
instance.interceptors.response.use(function (response) { |
||||||
|
//if (process.env.NODE_ENV === 'development') console.log('log: '+JSON.stringify(response))
|
||||||
|
return response; |
||||||
|
}, function (error) { |
||||||
|
if ( (window.location.href.indexOf("login")>0) || (window.location.href.indexOf("reset")>0) ) { |
||||||
|
return Promise.reject(error); |
||||||
|
} |
||||||
|
else if (401 === error.response.status) { |
||||||
|
localStorage.clear(); |
||||||
|
window.location.href = "/login"; |
||||||
|
} else if ((409 === error.response.status) && (error.response.data.respuesta.indexOf('factura'))) { |
||||||
|
console.log(JSON.stringify(error.response)) |
||||||
|
if (error.response.data.registro.factura) { |
||||||
|
(error.response.data.registro.id===-1) ? |
||||||
|
alert(error.response.data.respuesta + |
||||||
|
' en la factura: ' + |
||||||
|
error.response.data.registro.factura + |
||||||
|
' en el trafico: CG' + |
||||||
|
error.response.data.registro.idTrafico) : |
||||||
|
alert(error.response.data.respuesta + ' en TRADE')
|
||||||
|
} |
||||||
|
} else { |
||||||
|
return Promise.reject(error); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
instance.interceptors.request.use(function (config) { |
||||||
|
/* if (process.env.NODE_ENV === 'development') |
||||||
|
console.log('log: '+JSON.stringify(config))*/ |
||||||
|
return config;
|
||||||
|
}, function (error) { |
||||||
|
return Promise.reject(error); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
export default instance; |
||||||
|
|
@ -1,19 +1,21 @@ |
|||||||
import React from 'react'; |
import React from 'react' |
||||||
import ReactDOM from 'react-dom/client'; |
import ReactDOM from 'react-dom/client' |
||||||
import './index.css'; |
import './index.css' |
||||||
import App from './App'; |
import App from './App' |
||||||
import reportWebVitals from './reportWebVitals'; |
import { Provider } from 'react-redux' |
||||||
|
import { store } from './store/store' |
||||||
|
import reportWebVitals from './reportWebVitals' |
||||||
|
|
||||||
const root = ReactDOM.createRoot( |
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) |
||||||
document.getElementById('root') as HTMLElement |
|
||||||
); |
|
||||||
root.render( |
root.render( |
||||||
<React.StrictMode> |
<Provider store={store}> |
||||||
<App /> |
<React.StrictMode> |
||||||
</React.StrictMode> |
<App /> |
||||||
); |
</React.StrictMode> |
||||||
|
</Provider> |
||||||
|
) |
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
// If you want to start measuring performance in your app, pass a function
|
||||||
// to log results (for example: reportWebVitals(console.log))
|
// to log results (for example: reportWebVitals(console.log))
|
||||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
reportWebVitals(); |
reportWebVitals() |
||||||
|
@ -0,0 +1,41 @@ |
|||||||
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit' |
||||||
|
import IMenu from '../../../Interfaces/Auth/IMenu'; |
||||||
|
const MenuItems: IMenu[] = [{ id:0, descripcion:'', padreId:0, posicion:0, url:''}] |
||||||
|
const initialState = { MenuItems } |
||||||
|
|
||||||
|
export const MenuItemsSlice = createSlice({ |
||||||
|
name: 'MenuItems', |
||||||
|
initialState: initialState, |
||||||
|
reducers: { |
||||||
|
populateMenuItems : (state, action: PayloadAction<IMenu[]>) => { |
||||||
|
state.MenuItems = [] |
||||||
|
state.MenuItems.push(... action.payload) |
||||||
|
}, |
||||||
|
addMenuItems : (state, action: PayloadAction<IMenu>) => { |
||||||
|
var Existe = state.MenuItems.find(function(item) { |
||||||
|
return item.id === action.payload.id; |
||||||
|
}); |
||||||
|
if (!Existe) state.MenuItems.push(action.payload) |
||||||
|
}, |
||||||
|
updateMenuItems : (state, action: PayloadAction<IMenu>) => { |
||||||
|
const i = state.MenuItems.findIndex(_element => _element.id === action.payload.id); |
||||||
|
if (i > -1) state.MenuItems[i] = action.payload; |
||||||
|
else state.MenuItems.push(action.payload); |
||||||
|
|
||||||
|
}, |
||||||
|
deleteMenuItems : (state, action: PayloadAction<number>) => { |
||||||
|
const newArr = state.MenuItems.filter(data => data.id != action.payload); |
||||||
|
state.MenuItems=newArr |
||||||
|
}, |
||||||
|
InitMenuItems : (state, action: PayloadAction<number>) => { |
||||||
|
state.MenuItems.splice(0,state.MenuItems.length-1) |
||||||
|
}, |
||||||
|
}, |
||||||
|
}) |
||||||
|
|
||||||
|
export const { addMenuItems,
|
||||||
|
populateMenuItems,
|
||||||
|
updateMenuItems,
|
||||||
|
deleteMenuItems, |
||||||
|
InitMenuItems } = MenuItemsSlice.actions; |
||||||
|
export default MenuItemsSlice.reducer; |
@ -0,0 +1,12 @@ |
|||||||
|
import { configureStore } from '@reduxjs/toolkit' |
||||||
|
import { MenuItemsSlice } from './features/Auth/MenuItemsSlice' |
||||||
|
|
||||||
|
|
||||||
|
export const store = configureStore({ |
||||||
|
reducer: { |
||||||
|
// MenuItemsSlice: MenuItemsSlice
|
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export type RootState = ReturnType<typeof store.getState> |
||||||
|
export type AppDispatch = typeof store.dispatch |
Loading…
Reference in new issue