Se Agrego el fronted del proyecto de aminusa.

master
Luis Rendon 1 week ago
commit 3fdc5509a9
  1. 3
      .env.development
  2. 3
      .env.qa
  3. 23
      .gitignore
  4. 46
      README.md
  5. 3
      index.html
  6. 61
      package.json
  7. BIN
      public/favicon.ico
  8. 43
      public/index.html
  9. BIN
      public/logo192.png
  10. BIN
      public/logo512.png
  11. 25
      public/manifest.json
  12. 3
      public/robots.txt
  13. 38
      src/App.css
  14. 9
      src/App.test.tsx
  15. 205
      src/App.tsx
  16. 238
      src/Componest/Catalogos/CatNotificaciones.tsx
  17. 450
      src/Componest/Catalogos/CatRelacionBookPrecta/CatRelacionBookPrecta.tsx
  18. 4
      src/Componest/Catalogos/CatRelacionBookPrecta/DTO/DTOPrecuentaCheques.ts
  19. 25
      src/Componest/Catalogos/CatRelacionBookPrecta/DTO/DTORelacionBookPrecta.ts
  20. 19
      src/Componest/Catalogos/CatWorkingHours/DTO/WorkingHours.ts
  21. 474
      src/Componest/Catalogos/CatWorkingHours/FileUploadExelWorkingHours.tsx
  22. 830
      src/Componest/Catalogos/FileUploadExel.tsx
  23. 30
      src/Componest/Cliente/Services/CatNotificaciones.Services.ts
  24. 5
      src/Componest/Cliente/interfaces/ICatNotificaciones.ts
  25. 30
      src/Componest/Dashboard/Dashboard.tsx
  26. 89
      src/Componest/Dashboard/DashboardCliente.tsx
  27. 175
      src/Componest/Loging/ForgotPassword.tsx
  28. 244
      src/Componest/Loging/Login.tsx
  29. 140
      src/Componest/Loging/PIN.tsx
  30. 197
      src/Componest/Loging/ResetCredentials.tsx
  31. 21
      src/Componest/Logout/logout.tsx
  32. 37
      src/Componest/MenuUsuario/MenuUsuario.tsx
  33. 233
      src/Componest/Register/UserList/UserList.tsx
  34. 251
      src/Componest/Register/admonPerfiles/AdmonPerfiles.tsx
  35. 195
      src/Componest/Register/admonPerfiles/nuevoItemMenu/NuevoItemMenu.tsx
  36. 125
      src/Componest/Register/admonPerfiles/nuevoPerfil/NuevoPerfil.tsx
  37. 847
      src/Componest/Register/register.tsx
  38. 445
      src/Componest/Reportes/RptTotalHours/RptTotalHours.tsx
  39. 62
      src/Componest/Submenu/Submenu.tsx
  40. 260
      src/Componest/UserControl/UserControl.tsx
  41. 5
      src/Constants/TargetURL.ts
  42. 4
      src/DTO/DTOClonarUsuario.ts
  43. 5
      src/DTO/DTOItemMenuPerfil.ts
  44. 4
      src/DTO/DTOPINUsuario.ts
  45. 4
      src/DTO/DTOPerfilCreate.ts
  46. 26
      src/DTO/DTORelPreChe.ts
  47. 4
      src/DTO/DTOResetPassword.ts
  48. 4
      src/DTO/DTOUsuario.ts
  49. 5
      src/DTO/DTOUsuarioCliente.ts
  50. 5
      src/DTO/DTOUsuariosShort.ts
  51. 21
      src/DTO/DTOWorkingHours.ts
  52. 11
      src/DTO/Reportes/DTOTotalHours.ts
  53. 36
      src/Services/Auth/Auth.Service.ts
  54. 52
      src/Services/Catalogos/PerfilesMenu.Services.ts
  55. 37
      src/Services/Catalogos/RelacionPrecuentaCheques.ts
  56. 50
      src/Services/Catalogos/Usuarios.Services.ts
  57. 52
      src/Services/Reportes/reportes.services.ts
  58. 61
      src/Services/common/http-common.ts
  59. 12
      src/Store/features/CatRelacionBookPrectaSlice.ts
  60. 46
      src/Store/features/Clientes/1868/CatNotificaciones.ts
  61. 6
      src/Store/features/hooks.ts
  62. 24
      src/Store/features/userStatusSlice/userStatusSlice.ts
  63. 130
      src/Store/store.ts
  64. 35
      src/Utils/ExelFiles/Exel.services.ts
  65. 51
      src/Utils/Toast/msgInformativo.tsx
  66. 292
      src/css/generic01.css
  67. 53
      src/css/login.css
  68. 68
      src/css/menu2.css
  69. 12
      src/css/reactCaptcha.css
  70. BIN
      src/images/GEMCO_mini.png
  71. BIN
      src/images/expand.gif
  72. BIN
      src/images/fire-flame.gif
  73. BIN
      src/images/globe.gif
  74. BIN
      src/images/grupo-promax-b.png
  75. BIN
      src/images/pixels.gif
  76. 13
      src/index.css
  77. 59
      src/index.tsx
  78. 7
      src/interfaces/Catalogos/IItemMenu.ts
  79. 4
      src/interfaces/Catalogos/IPerfiles.ts
  80. 5
      src/interfaces/ICatNotificaciones.ts
  81. 12
      src/interfaces/IPerfilesMenu.tsx
  82. 32
      src/interfaces/IRegister.tsx
  83. 3
      src/interfaces/IRespuesta.ts
  84. 6
      src/interfaces/IUsuario.ts
  85. 10
      src/interfaces/IjwtStructure.ts
  86. 4
      src/interfaces/Ilogin.ts
  87. 12
      src/interfaces/Utils/ITokenInfo.ts
  88. 51
      src/interfaces/Utils/Toast/msgInformativo.tsx
  89. 3
      src/interfaces/token.ts
  90. 1
      src/logo.svg
  91. 1
      src/react-app-env.d.ts
  92. 15
      src/reportWebVitals.ts
  93. 5
      src/setupTests.ts
  94. 26
      tsconfig.json
  95. 10446
      yarn.lock

@ -0,0 +1,3 @@
REACT_APP_ENVIRONMENT=development
REACT_APP_API=https://localhost:5020/api
REACT_APP_SERVICES=http://localhost:7000/

@ -0,0 +1,3 @@
REACT_APP_ENVIRONMENT=qa
REACT_APP_API=https://adminusa.gemcousa.solutions/ADMINUSABackend/api

23
.gitignore vendored

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

@ -0,0 +1,46 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.\
You will also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).

@ -0,0 +1,3 @@
<html>
Sitio web para ser administrado por Luis Rendon
</html>

@ -0,0 +1,61 @@
{
"name": "adminusafronted",
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^2.2.6",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.104",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-redux": "^7.1.33",
"axios": "^1.7.2",
"env-cmd": "^10.1.0",
"formik": "^2.4.6",
"jwt-decode": "3.1.2",
"react": "^18.3.1",
"react-bootstrap": "^2.10.4",
"react-data-table-component": "^7.6.2",
"react-dom": "^18.3.1",
"react-icons": "^5.2.1",
"react-redux": "^9.1.2",
"react-router-dom": "^6.25.1",
"react-scripts": "5.0.1",
"redux-toolkit": "^1.1.2",
"styled-components": "^6.1.12",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4",
"xlsx": "^0.18.5",
"yup": "^1.4.0"
},
"scripts": {
"start-qa": "env-cmd -f .env.qa react-scripts start",
"start-prod": "env-cmd -f .env.production react-scripts start",
"build-qa": "env-cmd -f .env.qa react-scripts build version --patch",
"build-prod": "yarn env-cmd -f .env.production react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"start-dev": "env-cmd -f .env.development react-scripts start"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

@ -0,0 +1,38 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@ -0,0 +1,9 @@
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();
});

@ -0,0 +1,205 @@
import React, { useEffect, useState } from 'react'
import ItemMenu from './interfaces/Catalogos/IItemMenu'
import { Outlet, useNavigate } from 'react-router-dom'
import { logued } from './Store/features/userStatusSlice/userStatusSlice'
import {
Badge,
Button,
Container,
Form,
Nav,
Navbar,
NavDropdown,
OverlayTrigger,
Popover,
} from 'react-bootstrap'
import usuariosServices from './Services/Catalogos/Usuarios.Services'
import { useSelector, useDispatch } from 'react-redux'
import { RootState } from './Store/store'
import { IconContext } from 'react-icons'
import { BsPersonCircle } from 'react-icons/bs'
import FService from './Componest/Cliente/Services/CatNotificaciones.Services'
import './App.css'
import ImportantImage from './images/fire-flame.gif'
import Submenu from './Componest/Submenu/Submenu'
import { populateCatNotificaciones } from './Store/features/Clientes/1868/CatNotificaciones'
function App() {
const mCatNotificaciones = useSelector(
(state: RootState) => state.CatNotificaciones.CatNotificaciones
)
const navigate = useNavigate()
const dispatch = useDispatch()
let _menu: ItemMenu[] = []
const [mainMenu, setMainMenu] = useState(_menu)
const userLogued = useSelector((state: RootState) => state.userStatus.value)
const [show, setShow] = useState(false)
const [msg, setMsg] = useState('')
const [header, setHeader] = useState('')
const msgColor = 'primary'
const menu = localStorage.getItem('menu') ? localStorage.getItem('menu') : ''
const User = () => {
const stickyValue = window.localStorage.getItem('User')
return stickyValue !== null ? JSON.parse(stickyValue) : ''
}
const [Depto, setDepto] = useState(() => {
const stickyValue = window.localStorage.getItem('Departamento')
return stickyValue !== null
? JSON.parse(stickyValue).substring(0, 4) + '.'
: ''
})
useEffect(() => {
if (menu && userLogued) {
setMainMenu(JSON.parse(menu))
} else {
setMainMenu([])
}
}, [menu, userLogued])
const loadCatNotificaciones = () => {
FService.Get()
.then((response) => {
dispatch(populateCatNotificaciones(response.data))
})
.catch((e: Error) => {
return
})
}
useEffect(() => {
navigate('/')
loadCatNotificaciones()
}, [])
useEffect(() => {
usuariosServices
.validate()
.then((response) => {
if (response.status === 200) {
dispatch(logued(true))
}
})
.catch((e: Error) => {
if (!window.location.href.indexOf('login')) {
localStorage.setItem('menu', '')
localStorage.setItem('token', '')
setHeader('Informativo')
setMsg('Su session ha expirado, necesita volver a loguerse')
setShow(true)
navigate('/')
}
})
}, [dispatch, navigate])
return (
<div className='App'>
<Navbar
className='custom-theme'
style={{ backgroundColor: '#572364' }}
expand='lg'
>
<Container>
<Navbar.Brand href='/' style={{ color: '#FFFFFF' }}>
adminusa
</Navbar.Brand>
<Navbar.Toggle aria-controls='basic-navbar-nav' />
<Navbar.Collapse id='basic-navbar-nav'>
<Nav className='me-auto'>
{mainMenu
? mainMenu.map((itemMenu, index) => {
if (itemMenu.padreId === 0) {
return (
<>
<Submenu
descripcion={itemMenu.descripcion}
key={itemMenu.id}
allItems={mainMenu}
submenu={mainMenu.filter(function (item) {
return item.padreId === itemMenu.id
})}
/>
</>
)
}
})
: ''}
</Nav>
<Nav>
<Form className='d-flex' style={{ color: '#ffffff' }}>
{!userLogued ? (
<>
<Nav.Link style={{ color: '#ffffff' }} href='/#/login'>
Login
</Nav.Link>
</>
) : (
<>
<>
<Nav.Link style={{ color: '#ffffff' }} href='/#/help'>
Help
</Nav.Link>
<Nav.Link style={{ color: '#ffffff' }} href='/#/logout'>
Logout
</Nav.Link>
<div
style={{ paddingTop: '5px', paddingLeft: '20px' }}
></div>
<IconContext.Provider value={{ size: '25px' }}>
<BsPersonCircle />
</IconContext.Provider>
<div style={{ paddingTop: '5px', paddingLeft: '5px' }}>
{Depto}
</div>
</>
<div
style={{
paddingTop:'0',
position: 'relative',
visibility:
mCatNotificaciones.filter(
(notificacion) => notificacion.activo
).length > 0
? 'visible'
: 'hidden',
}}
>
<OverlayTrigger
trigger='click'
key={'bottom'}
placement={'left'}
overlay={
<Popover id={`popover-positioned-${'bottom'}`}>
<Popover.Header as='h3'>{`Adminusa les informa`}</Popover.Header>
<Popover.Body>
{mCatNotificaciones
? mCatNotificaciones
.filter(
(notificacion) => notificacion.activo
)
.map((notificacion) => {
return <div>{notificacion.mensaje}</div>
})
: ''}
</Popover.Body>
</Popover>
}
>
<div className='center-circle'>
<div className='circle pulse'></div>
</div>
</OverlayTrigger>
</div>
</>
)}
</Form>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
<Outlet />
</div>
)
}
export default App

@ -0,0 +1,238 @@
import { useEffect, useState } from 'react'
import { Button, Card, Col, Form, Row } from 'react-bootstrap'
import DataTable from 'react-data-table-component'
import { IconContext } from 'react-icons'
import { BsEraserFill, BsFillPencilFill } from 'react-icons/bs'
import { useDispatch, useSelector } from 'react-redux'
import FService from '../Cliente/Services/CatNotificaciones.Services'
import { RootState } from '../../Store/store'
import { MsgInformativo } from '../../Utils/Toast/msgInformativo'
import ICatNotificaciones from '../../interfaces/ICatNotificaciones'
import {
populateCatNotificaciones,
updateCatNotificaciones,
} from '../../Store/features/Clientes/1868/CatNotificaciones'
export interface ICatNotificacionesProps {}
export default function CatNotificaciones(props: ICatNotificacionesProps) {
const Perfil = () => {
const stickyValue = window.localStorage.getItem('Perfil')
return stickyValue !== null ? JSON.parse(stickyValue) : ''
}
const dispatch = useDispatch()
const mCatNotificaciones = useSelector(
(state: RootState) => state.CatNotificaciones.CatNotificaciones
)
const mProfile = useSelector(
(state: RootState) => state.userStatus.Profile
)
const [ID, setID] = useState(0)
const [Mensaje, setMensaje] = useState('')
const [Direccion, setDireccion] = useState('')
const [Buscar, setBuscar] = useState('')
const [show, setShowMsg] = useState(false)
const [ShowModal, setShowModal] = useState(false)
const [header, setHeader] = useState('')
const [msg, setMsg] = useState('')
const [msgColor, setMsgColor] = useState('primary')
const [Activo, setActivo] = useState(false)
const colData = [
{
name: 'id',
width: '5%',
selector: (row: ICatNotificaciones) => row.id,
sortable: true,
},
{
name: 'Mensaje',
width: '80%',
selector: (row: ICatNotificaciones) => row.mensaje,
},
{
name: 'Edita',
cell: (row: ICatNotificaciones) => (
<div
style={{ textAlign: 'center', cursor: 'pointer', visibility: (mProfile==='Administrador') ? 'visible' : 'hidden' }}
onClick={() => {
setID(row.id)
setMensaje(row.mensaje)
setActivo(row.activo)
}}
>
<IconContext.Provider value={{ color: 'blue', size: '25px' }}>
<BsFillPencilFill />
</IconContext.Provider>
</div>
),
},
{
name: 'Activo',
cell: (row: ICatNotificaciones) => (
<div style={{ textAlign: 'center', cursor: 'pointer' }}>
<Form.Check
type='switch'
id='custom-switch'
label=''
checked={row.activo}
onClick={() => {
save(row.id, row.mensaje, !row.activo)
}}
style={{}}
/>
</div>
),
},
]
const save = (mID: number, mMensaje: string, mActivo: boolean) => {
console.log(mID + ' ' +mMensaje+' '+mActivo)
const data: ICatNotificaciones = {
id: mID,
mensaje: mMensaje ? mMensaje : '',
activo: mActivo
}
FService.Append(data)
.then((response) => {
setHeader('Confirmacion')
setMsg('Los cambios se han guardado exitosamente.')
dispatch(updateCatNotificaciones(response.data))
setID(response.data.id)
setShowMsg(true)
return
})
.catch((e: Error) => {
setHeader('Error')
setMsg('Ocurrio un error: ' + e)
setShowMsg(true)
return
})
}
const loadCatNotificaciones = () => {
FService.Get()
.then((response) => {
dispatch(populateCatNotificaciones(response.data))
})
.catch((e: Error) => {
setHeader('Error')
setMsg('Ocurrio un error: ' + e)
setShowMsg(true)
return
})
}
useEffect(() => {
loadCatNotificaciones()
}, [])
const cleanForm = () => {
setID(0)
setMensaje('')
setDireccion('')
}
return (
<div>
<Row style={{ paddingTop: '10px', visibility: (mProfile==='Administrador') ? 'visible' : 'hidden' }}>
<Col></Col>
<Col xs={10}>
<Card style={{}}>
<Card.Body>
<Card.Text>
<Row>
<Col xs={1}>
<Button
variant='warning'
size='sm'
onClick={() => {
cleanForm()
}}
>
<BsEraserFill />
</Button>{' '}
&nbsp; Mensaje
</Col>
<Col xs={10}>
<Form.Control
type='text'
id='Mensaje'
value={Mensaje}
size='sm'
onChange={(e) => {
setMensaje(e.target.value)
}}
/>
</Col>
<Col xs={1} style={{ textAlign: 'right' }}>
<Button variant='primary' onClick={() => save(ID, Mensaje, Activo)} size='sm'>
Guardar
</Button>
</Col>
</Row>
</Card.Text>
</Card.Body>
</Card>
</Col>
<Col></Col>
</Row>
<Row style={{ paddingTop: '10px' }}>
<Col></Col>
<Col xs={10}>
<Card style={{}}>
<Card.Body>
<Card.Text>
<Row style={{ paddingTop: '5px' }}>
<Col xs={12}>
<Form.Control
type='text'
id='Buscar'
value={Buscar}
placeholder='Search...'
size='sm'
onChange={(e) => {
setBuscar(e.target.value)
}}
/>
</Col>
</Row>
<Row>
<Col xs={12}>
<DataTable
noHeader
defaultSortFieldId={'id'}
defaultSortAsc={true}
pagination
highlightOnHover
columns={colData}
data={mCatNotificaciones.filter(function (row) {
return row.mensaje
.toLowerCase()
.includes(Buscar.toLowerCase())
})}
/>
</Col>
</Row>
</Card.Text>
</Card.Body>
</Card>
</Col>
<Col></Col>
</Row>
<MsgInformativo
show={show}
msg={msg}
header={header}
time={2000}
msgColor={msgColor}
closeToast={() => {
setShowMsg(false)
}}
/>
</div>
)
}

@ -0,0 +1,450 @@
import * as React from 'react'
import { useEffect, useState, useRef } from 'react'
import RelacionPrecuentaCheques from '../../../Services/Catalogos/RelacionPrecuentaCheques'
import { Button, Card, Form, Row, Col, Modal } from 'react-bootstrap'
import { BsSearch, BsFileEarmarkExcel } from 'react-icons/bs'
import { CgAdd } from 'react-icons/cg'
import { useSelector } from 'react-redux'
import { RootState } from '../../../Store/store'
import * as XLSX from 'xlsx'
import DataTable from 'react-data-table-component'
import DtoPrecuentaCheques from './DTO/DTOPrecuentaCheques'
import { MsgInformativo } from '../../../Utils/Toast/msgInformativo'
export interface IRptRelacionBookPrectaProps {}
export default function CatRelacionBookPrecta(
props: IRptRelacionBookPrectaProps
) {
const mInvoices = useSelector(
(state: RootState) => state.CatRelacionBookPrectaSlice
)
const [filtro, setFiltro] = useState('')
const [Data, setData] = useState<Array<DtoPrecuentaCheques>>([])
const [filteredData, setFilteredData] = useState<Array<DtoPrecuentaCheques>>(
[]
)
const [show, setShowMsg] = useState(false)
const [msg, setMsg] = useState('')
const [header, setHeader] = useState('')
const [Precuenta, setPrecuenta] = useState('')
const [Cheques, setCheques] = useState('')
const [TipoOperacion, setTipoOperacion] = useState(1)
// const [msgColor, setMsgColor] = useState('')
const msgColor = 'primary'
const gridRef = useRef<any>(null)
const [showModal, setShowModal] = useState(false)
const [newPrecuenta, setNewPrecuenta] = useState('')
const [newCheques, setNewCheques] = useState('')
const columnsRelacionBookPrecta = [
{
name: 'Precuenta',
width: '40%',
selector: (row: DtoPrecuentaCheques) => row.precuenta,
sortable: true
},
{
name: 'Cheques',
width: '40%',
selector: (row: DtoPrecuentaCheques) => row.cheques,
sortable: true
},
{
name: 'Acciones',
width: '5%',
cell: (row: DtoPrecuentaCheques) => (
<Button
size="sm"
variant="danger"
onClick={() => handleDelete(row.precuenta)}
>
X
</Button>
)
}
]
//comboc box para editar con precuenta
const generarReporte = () => {
const parametros = {
precuenta: TipoOperacion === 1 ? Precuenta : Cheques,
cheques: TipoOperacion === 2 ? Precuenta : Cheques
}
const { precuenta, cheques } = parametros
RelacionPrecuentaCheques.GETRelacionBookPrectaPreChe(
precuenta || '',
cheques || ''
)
.then((response) => {
setData(response.data)
setFilteredData(response.data)
setHeader('Informativo')
setMsg('Se encontró la siguiente información...')
setShowMsg(true)
})
.catch((e: Error) => {
setHeader('Error')
setMsg(`Ocurrió un error: ${e}`)
setShowMsg(true)
})
}
const generarReporte1 = () => {
RelacionPrecuentaCheques.GetAllPrecuentaCheques()
.then((response) => {
setData(response.data)
setFilteredData(response.data)
// setHeader('Informativo')
// setMsg('Se encontró la siguiente información...')
// setShowMsg(true)
})
.catch((e: Error) => {
setHeader('Error')
setMsg(`Ocurrió un error: ${e}`)
setShowMsg(true)
})
}
// useEffect(() => {
// generarReporte1()
// }, [])
const exportExcel = (jsonData: any[], fileName: string) => {
const Heading = [
[
// 'Type',
// 'Date',
// 'Num',
// 'Name',
// 'Memo',
// 'Amount',
// 'Trafico',
// 'Trafico1',
'id',
'Precuenta',
'Cheques'
// 'Concepto',
// 'Importe',
// 'Cantidad',
// 'Tipo',
// 'IdProvedor',
// 'NomProvedor',
// 'TagTabulador',
// 'NombreTabulador',
// 'Rctadeb',
// 'Diferencia'
]
]
const wb = XLSX.utils.book_new()
const ws: XLSX.WorkSheet = XLSX.utils.json_to_sheet([])
XLSX.utils.sheet_add_aoa(ws, Heading)
XLSX.utils.sheet_add_json(ws, jsonData, { origin: 'A2', skipHeader: true })
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
XLSX.writeFile(wb, `${fileName}.xlsx`)
const range = XLSX.utils.decode_range(ws['!ref']!)
for (let C = range.s.c; C <= range.e.c; ++C) {
const address = XLSX.utils.encode_col(C) + '1'
if (!ws[address]) continue
ws[address].v = ws[address].v.toUpperCase()
}
}
const filtraReporte = (e: any) => {
setFiltro(e.target.value)
const filtered = Data.filter(
(item) =>
item.precuenta.toLowerCase().includes(e.target.value.toLowerCase()) ||
item.cheques.toLowerCase().includes(e.target.value.toLowerCase())
)
setFilteredData(filtered)
}
const downloadExcel = () => exportExcel(Data, 'RelacionesBookPrecta')
const precuentaExists = (precuenta: string) => {
return Data.some((item) => item.precuenta === precuenta)
}
const handleSave = () => {
if (newPrecuenta === newCheques) {
setHeader('Informativo')
setMsg('No puede introducir precuentas y cheques iguales')
setShowMsg(true)
return
}
if (precuentaExists(newPrecuenta)) {
setHeader('Informativo')
setMsg('La precuenta ya existe en los registros')
setShowMsg(true)
return
}
RelacionPrecuentaCheques.PostAppedPrecuentaCheques(newPrecuenta, newCheques)
.then((response) => {
setHeader('Informativo')
setMsg('Se ha agregado la nueva relación exitosamente.')
setShowMsg(true)
setNewPrecuenta('')
setNewCheques('')
generarReporte1()
setShowModal(false)
})
.catch((e: Error) => {
setHeader('Error')
setMsg(`Ocurrió un error: ${e}`)
setShowMsg(true)
})
}
const handleOpenModal = () => {
setNewPrecuenta('')
setNewCheques('')
setShowModal(true)
}
const handleCloseModal = () => {
setNewPrecuenta('')
setNewCheques('')
setShowModal(false)
}
const handleDelete = (precuenta: string) => {
RelacionPrecuentaCheques.DeletePrecuentaCheques(precuenta)
.then((response) => {
setHeader('Eliminado')
setMsg('Se ha eliminado la relación exitosamente.')
setShowMsg(true)
generarReporte1()
})
.catch((e: Error) => {
setHeader('Error')
setMsg(`Ocurrió un error: ${e}`)
setShowMsg(true)
})
}
return (
<div className="mt-2">
<Card>
<Card.Body>
<div className="container">
<div
className="row mb-4"
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '1vh'
}}
>
<Card
style={{
paddingTop: '10px',
paddingBottom: '5px',
width: '800px',
height: 'auto'
}}
>
<Row className="align-items-center">
<Col xs={12}>
<Row className="align-items-center">
{/* <Col xs={1} style={{ textAlign: 'right' }}>
<Form.Label className="mb-0">Codigo</Form.Label>
</Col>
<Col xs={2}>
<Form.Control
type="text"
size="sm"
value={Precuenta}
onChange={(e) => setPrecuenta(e.target.value)}
// onClick={generarReporte}
style={{
height: '35px',
width: '120px'
}}
/>
</Col> */}
{/* <Col xs={1} style={{ textAlign: 'right' }}>
<Form.Label className="mb-0">TipoOpe</Form.Label>
</Col>
<Col xs={2}>
<Form.Control
as="select"
onChange={(e) =>
setTipoOperacion(parseInt(e.target.value))
}
className="form-select form-select-sm"
style={{
height: '35px',
width: '110px'
}}
>
<option value="1">Precuenta</option>
<option value="2">Cheques</option>
</Form.Control>
</Col> */}
<Col xs={2}>
<Form.Control
type="text"
size="sm"
placeholder="Search..."
onChange={filtraReporte}
style={{
height: '35px',
width: '230px',
padding: '5px',
marginLeft: '65px'
}}
/>
</Col>
<Col xs={1} style={{ textAlign: 'right' }}>
<Button
variant="primary"
size="sm"
onClick={generarReporte1}
style={{
height: '35px',
width: '80px',
padding: '5px',
marginLeft: '230px'
}}
>
<BsSearch /> Buscar
</Button>
</Col>
<Col xs={1}>
<Button
size="sm"
variant="primary"
onClick={handleOpenModal}
style={{
height: '35px',
width: '70px',
padding: '5px',
backgroundColor: 'orange',
marginLeft: '300px'
}}
>
<CgAdd />
</Button>
</Col>
<Col xs={2}>
<Button
size="sm"
variant="success"
onClick={downloadExcel}
style={{
height: '35px',
width: '70px',
padding: '5px',
marginLeft: '370px'
}}
>
<BsFileEarmarkExcel />
&nbsp;Excel
</Button>
</Col>
</Row>
</Col>
</Row>
</Card>
</div>
<Row>
<Col xs={3}></Col>
<Col xs={6}>
<Card>
<DataTable
noHeader
defaultSortFieldId={'id'}
defaultSortAsc={true}
striped={true}
dense={true}
paginationPerPage={10}
pagination
highlightOnHover
columns={columnsRelacionBookPrecta}
data={filteredData}
pointerOnHover
/>
</Card>
</Col>
<Col xs={3}></Col>
</Row>
</div>
</Card.Body>
</Card>
<Modal show={showModal} onHide={handleCloseModal}>
<Modal.Header closeButton>
<Modal.Title>Relación</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group>
<Form.Label>Precuenta</Form.Label>
<Form.Control
type="text"
value={newPrecuenta}
onChange={(e) => setNewPrecuenta(e.target.value)}
/>
</Form.Group>
<Form.Group>
<Form.Label>Cheques</Form.Label>
<Form.Control
type="text"
value={newCheques}
onChange={(e) => setNewCheques(e.target.value)}
/>
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleCloseModal}>
Cancelar
</Button>
<Button variant="primary" onClick={handleSave}>
Guardar
</Button>
</Modal.Footer>
{/* <Col xs={1} style={{ textAlign: 'right' }}>
<Form.Label className="mb-0">TipoOpe</Form.Label>
</Col>
<Col xs={2}>
<Form.Control
as="select"
onChange={(e) =>
setTipoOperacion(parseInt(e.target.value))
}
className="form-select form-select-sm"
style={{
height: '35px',
width: '110px'
}}
>
<option value="1">Precuenta</option>
<option value="2">Cheques</option>
</Form.Control>
</Col> */}
</Modal>
<MsgInformativo
show={show}
msg={msg}
header={header}
msgColor={msgColor}
closeToast={() => {
setShowMsg(false)
}}
/>
</div>
)
}

@ -0,0 +1,4 @@
export default interface DtoPrecuentaCheques {
precuenta: string,
cheques: string,
}

@ -0,0 +1,25 @@
export default interface DTORelacionBookPrecta {
type: string,
cheques: string,
date: string,
num: string,
name: string,
memo: string,
amount: string,
trafico: string,
trafico1: string,
precuenta: string,
concepto: string,
importe: string,
cantidad: string,
tipo: string,
idProvedor: string,
nomProvedor: string,
tagTabulador: string,
nombreTabulador: string,
rctadeb:string,
diferencia: string,
}

@ -0,0 +1,19 @@
export default interface WorkingHours {
empNo : string,
acNo : string,
name: string,
date : string,
clockIn1 : string,
clockOut1 : string,
clockIn2 : string,
clockOut2 : string,
clocIn3 : string,
clocOut3 : string,
clocIn4 : string,
clocOut4 : string,
clocIn5 : string,
clocOut5 : string,
totalInTime : string,
totalHoursWorked : string
}

@ -0,0 +1,474 @@
import * as React from 'react';
import { useState } from 'react';
import { Button, Card, Form, Col, Row, ToastHeader, } from 'react-bootstrap';
import { BsSearch, BsFileEarmarkExcel } from 'react-icons/bs'
import ExelServices from '../../../Utils/ExelFiles/Exel.services';
import { FiSend } from "react-icons/fi";
import { MsgInformativo } from '../../../Utils/Toast/msgInformativo';
import * as XLSX from 'xlsx';
import DataTable from 'react-data-table-component';
import { DTOWorkingHours } from '../../../DTO/DTOWorkingHours';
import reportesServices from '../../../Services/Reportes/reportes.services';
export default function FileUploadExel() {
const [WorkingHoursFile, setWorkingHoursFile] = useState<File | null>(null);
const [showToast, setShowToast] = useState<boolean>(false);
const [toastMsg, setToastMsg] = useState<string>('');
const [toastHeader, setToastHeader] = useState<string>('');
const [toastColor, setToastColor] = useState<string>('');
const [Inicio, setInicio] = useState(currentDate())
const [Fin, setFin] = useState(currentDate())
const [Data, setData] = useState<Array<DTOWorkingHours>>([])
const [show, setShowMsg] = useState(false)
const [filtro, setFiltro] = useState('')
const [filteredData, setFilteredData] = useState<Array<DTOWorkingHours>>(
[]
)
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
let file = event.target.files?.[0] || null;
if (file && file.name.endsWith('.xls')) {
// Convertir XLS a XLSX usando la biblioteca xlsx
const data = await file.arrayBuffer();
const workbook = XLSX.read(data, { type: 'array' });
const convertedData = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
file = new File([convertedData], file.name.replace('.xls', '.xlsx'), {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});
}
setWorkingHoursFile(file);
};
const columnsConcepts = [
{
name: 'EmpNo',
width: '100px',
selector: (row : DTOWorkingHours ) => row.empNo,
sortable: true,
filter : true
},
{
name: 'AcNo',
width: '80px',
selector :(row:DTOWorkingHours) => row.acNo,
sortable: true ,
filter : true
},
{
name: 'No',
width: '5px',
selector: (row : DTOWorkingHours) => row.no,
sortable: true,
filter : true
},
{
name: 'Name',
width: '150px',
selector: (row : DTOWorkingHours) => row.name,
sortable : true ,
filter : true
},
{
name: 'Date',
width: '150px',
selector : (row : DTOWorkingHours ) => row.date,
sortable: true,
filter : true
},
{
name: 'ClockIn1',
width : '120px',
selector: (row : DTOWorkingHours) => row.clockIn1,
sortable: true ,
filter : true
},
{
name: 'ClockOut1',
width : '120px',
selector : (row : DTOWorkingHours) => row.clockOut1,
sortable : true ,
filter : true
},
{
name: 'ClockIn2',
width : '120px',
selector: (row : DTOWorkingHours) => row.clockIn2,
sortable: true ,
filter : true
},
{
name: 'ClockOut2',
width : '120px',
selector : (row : DTOWorkingHours) => row.clockOut2,
sortable : true,
filter : true
},
{
name: 'ClockIn3',
width : '120px',
selector: (row : DTOWorkingHours) => row.clockIn3,
sortable: true ,
filter : true
},
{
name: 'ClockOut3',
width : '150px',
selector : (row : DTOWorkingHours) => row.clockOut3,
sortable : true,
filter : true
},
{
name: 'ClockIn4',
width : '120px',
selector: (row : DTOWorkingHours) => row.clockIn4,
sortable: true ,
filter : true
},
{
name: 'ClockOut4',
width : '120px',
selector : (row : DTOWorkingHours) => row.clockOut4,
sortable : true,
filter : true
} ,
{
name: 'ClockIn5',
width : '120px',
selector: (row : DTOWorkingHours) => row.clockIn5,
sortable: true ,
filter : true
},
{
name: 'ClockOut5',
width : '120px',
selector : (row : DTOWorkingHours) => row.clockOut5,
sortable : true,
filter : true
},
{
name: 'TotalInTime',
width: '120px',
selector: (row : DTOWorkingHours) => row.totalInTime,
sortable : true ,
filter : true
},
{
name: 'TotalHoursWorked',
width: '130px',
selector : (row : DTOWorkingHours) => row.totalHoursWorked,
sortable : true,
filter : true
}
]
function currentDate (): string {
var today = new Date()
var dd = String(today.getDate()).padEnd(2,'0')
var mm = String(today.getMonth() + 1 ).padStart(2, '0')
var yyyy = today.getFullYear()
return yyyy+'-' + mm + '-' + dd
}
const generarReporte = () => {
reportesServices.getRptWorkingHours(Inicio, Fin)
.then((response) => {
setData(response.data)
setFilteredData(response.data)
setToastMsg('Se econtro la siguiente informacion');
setToastHeader('Informativo');
setToastColor('success');
setShowToast(true);
})
.catch((e:Error) => {
// alert('Ocurrio un Error'+e.message.toString())
setToastMsg('No se ha introducido fechas validas')
setToastHeader('Error')
setToastColor('danger')
setShowToast(true)
return;
} )
}
const donwloadExel = () => {
exportExcel(filteredData, 'Reportes de Horas Trabajadas')
}
const filtraReporte = (e: any ) => {
const searchText = e.target.value.toLowerCase();
setFiltro(searchText)
const filtered = Data.filter((iteam) => {
return (
(iteam.empNo && iteam.empNo.toString().toLocaleLowerCase().includes(searchText)) ||
(iteam.name && iteam.name.toString().toLocaleLowerCase().includes(searchText)) ||
(iteam.date && iteam.date.toString().toLocaleLowerCase().includes(searchText))
)
} )
console.log('filtered data ', filtered )
setFilteredData(filtered)
}
const exportExcel = (jsonData: any[], fileName: string) => {
const Heading = [
[
'EmpNo',
'AcNo',
'No',
'Name',
'Date',
'ClockIn1',
'ClockOut1',
'ClockIn1',
'ClockOut1',
'ClockIn1',
'ClockOut1',
'ClockIn1',
'ClockOut1',
'ClockIn1',
'ClockOut1',
'TotalInTime',
'TotalHoursWorked'
]
]
const wb = XLSX.utils.book_new()
const ws: XLSX.WorkSheet = XLSX.utils.json_to_sheet([])
XLSX.utils.sheet_add_aoa(ws, Heading)
XLSX.utils.sheet_add_json(ws, jsonData, { origin: 'A2', skipHeader: true })
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
XLSX.writeFile(wb, `${fileName}.xlsx`)
const range = XLSX.utils.decode_range(ws['!ref']!)
for (let C = range.s.c; C <= range.e.c; ++C) {
const address = XLSX.utils.encode_col(C) + '1'
if (!ws[address]) continue
ws[address].v = ws[address].v.toUpperCase()
}
}
const handleSendFiles = async () => {
if (!WorkingHoursFile) {
setToastMsg('No hay archivos para enviar');
setToastHeader('Error');
setToastColor('danger');
setShowToast(true);
return;
}
const formDataBook = new FormData();
formDataBook.append('file', WorkingHoursFile);
try {
const responseBook = await ExelServices.uploadWorkingHours(formDataBook);
if (!responseBook || responseBook.status !== 200) {
throw new Error('Error al subir el archivo de horas de trabajo');
}
setToastMsg('Archivo enviado exitosamente');
setToastHeader('Informativo');
setToastColor('success');
setShowToast(true);
setWorkingHoursFile(null);
} catch (error) {
setToastMsg(`Error al enviar archivos: ${(error as Error).message || 'Error desconocido'}`);
setToastHeader('Error');
setToastColor('danger');
setShowToast(true);
}
};
return (
<div className="mt-2">
<Card>
<Card.Body>
<Form>
<div className="d-flex justify-content-around">
<Card
className="text-center p-4 m-2"
style={{ backgroundColor: 'lightgreen', borderRadius: '8px', width: '25%' }}
>
<Form.Group>
<Form.Label className="d-block mb-2" style={{ fontWeight: 'bold' }}>
Arrastra o selecciona el archivo Excel
</Form.Label>
<Form.Control
type="file"
accept=".xlsx, .xls"
onChange={handleFileChange}
style={{ display: 'none' }}
id="workingHoursFileInput"
/>
<label
htmlFor="workingHoursFileInput"
className="btn btn-light d-block"
style={{ cursor: 'pointer', border: '2px solid green', borderRadius: '8px' }}
>
{WorkingHoursFile ? WorkingHoursFile.name : 'Seleccionar archivo'}
</label>
</Form.Group>
</Card>
<Button
variant="success"
onClick={handleSendFiles}
style={{ marginTop: '10px', display: 'block', marginLeft: 'auto', marginRight: 'auto', height: '40px' }}
>
Enviar <FiSend />
</Button>
</div>
</Form>
</Card.Body>
</Card>
<MsgInformativo
show={showToast}
msg={toastMsg}
header={toastHeader}
msgColor={toastColor}
closeToast={setShowToast}
/>
<Card className="mt-3">
<Card.Body>
<Form>
<Row className="align-items-center">
<Col xs={1}>
<Form.Label>Desde</Form.Label>
<Form.Control
defaultValue={Inicio}
type="date"
name="Inicio"
placeholder="Inicio"
title="Inicio"
alt="Inicio"
data-date-format="YYYY-mm-dd"
onChange={(e) => setInicio(e.target.value)}
size="sm"
/>
</Col>
<Col xs={1}>
<Form.Label>Hasta</Form.Label>
<Form.Control
defaultValue={Fin}
type="date"
name="Fin"
placeholder="Fin"
title="Fin"
alt="Fin"
onChange={(e) => setFin(e.target.value)}
size="sm"
/>
</Col>
<Col xs={2}>
<Form.Control
type="text"
size="sm"
placeholder="Search..."
onChange={ (e) => {
filtraReporte(e)
} }
style={{ height: '20px', padding: '5px' }}
/>
</Col>
<Col xs={3}>
<Button
// size="sm"
variant="success"
onClick={donwloadExel}
style={{ width: '30%' }}
>
<BsFileEarmarkExcel />
&nbsp;Excel
</Button>
</Col>
<Col xs={2}>
<Button
variant="primary"
onClick={generarReporte}
style={{ width: '30%' }}
>
<BsSearch />
Buscar
</Button>
</Col>
</Row>
</Form>
</Card.Body>
</Card>
<Card className="mt-3">
<Card.Body>
<div className="ag-theme-alpine" style={{ height: 500, width: '100%' }}>
<DataTable
noHeader
defaultSortFieldId={''}
defaultSortAsc={true}
striped={true}
dense={true}
paginationPerPage={10}
pagination
highlightOnHover
columns={columnsConcepts}
data={filteredData}
pointerOnHover
/>
</div>
</Card.Body>
</Card>
</div>
);
}

@ -0,0 +1,830 @@
import * as React from 'react'
import { useState } from 'react'
import { Button, Card, CardBody, Form, Modal, Col } from 'react-bootstrap'
import * as XLSX from 'xlsx'
import DataTable, { TableColumn } from 'react-data-table-component';
import { MsgInformativo } from '../../Utils/Toast/msgInformativo';
import reportesServices from '../../Services/Reportes/reportes.services';
import ExelServices from '../../Utils/ExelFiles/Exel.services';
import { BsSearch, BsFileEarmarkExcel } from 'react-icons/bs'
import { FiSend } from "react-icons/fi";
import { DTORelPreChe } from '../../DTO/DTORelPreChe';
import { blob } from 'node:stream/consumers';
export interface IFileUploadExelProps {}
export default function FileUploadExel(props : IFileUploadExelProps) {
const [bookFile, setBookFile] = useState<File | null>(null)
const [prectaFile, setPrectaFile] = useState<File | null>(null)
const [showModal, setShowModal] = useState(false)
const [selectedFile, setSelectedFile] = useState<File | null>(null)
const [message, setMessage] = useState<string | null>(null);
const [Data, setData] = useState<Array<DTORelPreChe>>([])
const [filteredData, setFilteredData] = useState<Array<DTORelPreChe>>(
[]
)
const [precuenta, setpPrecuenta] = useState('')
const [cheque, setCheque] = useState('')
const [show, setShowMsg] = useState(false)
const [header, setHeader] = useState('')
const [msg, setMsg] = useState('')
const [filtro, setFiltro] = useState('')
const [msgColor, setMsgColor] = React.useState('primary')
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>, setFile: React.Dispatch<React.SetStateAction<File | null>>) => {
const file = event.target.files?.[0] || null
setFile(file)
}
const handleRemoveFile = (file: File, setFile: React.Dispatch<React.SetStateAction<File | null>>) => {
setFile(null)
setMessage('Archivo eliminado exitosamente')
}
const handleSendFiles = async () => {
if (!bookFile && !prectaFile) {
setMessage('No hay archivos para enviar');
return;
}
// Crear FormData para los archivos
const formDataBook = new FormData();
if (bookFile) {
formDataBook.append('file', bookFile);
}
const formDataPrecta = new FormData();
if (prectaFile) {
formDataPrecta.append('file', prectaFile);
}
try {
// Enviar archivo Book
if (bookFile) {
const responseBook = await ExelServices.uploadBook(formDataBook);
if (!responseBook || responseBook.status !== 200) {
throw new Error('Error al subir el archivo Book');
}
console.log('Archivo Book subido exitosamente:', responseBook.data);
}
// Enviar archivo Precta
if (prectaFile) {
const responsePrecta = await ExelServices.uploadPrecta(formDataPrecta);
if (!responsePrecta || responsePrecta.status !== 200) {
throw new Error('Error al subir el archivo Precta');
}
console.log('Archivo Precta subido exitosamente:', responsePrecta.data);
}
setMessage('Archivos enviados exitosamente');
setBookFile(null);
setPrectaFile(null);
setTimeout(() => {
setMessage(null);
}, 4000);
} catch (error) {
const errorMessage = (error as Error).message || 'Error desconocido';
setMessage(`Error al enviar archivos: ${errorMessage}`);
}
};
const closeToast = (show: boolean): void => {
setShowMsg(false)
}
const columnDefs= [
{
name: <div style={{ textAlign: 'center' }}>Type</div>,
width: '70px',
selector: (row: DTORelPreChe) => row.type,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Cheque</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.cheques,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Date</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.date,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Num</div>,
width: '130px',
selector: (row: DTORelPreChe) => row.num,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Memo</div>,
width: '200px',
selector: (row: DTORelPreChe) => row.memo,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Amount</div>,
width: '150px',
selector: (row: DTORelPreChe) => row.amount,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Trafico</div>,
width: '150px',
selector: (row: DTORelPreChe) => row.trafico,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Trafico1</div>, // Cambié el nombre para evitar duplicados
width: '100px',
selector: (row: DTORelPreChe) => row.trafico1,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Precuenta</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.precuenta,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Concepto</div>,
width: '150px',
selector: (row: DTORelPreChe) => row.concepto,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Importe</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.importe,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Cantidad</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.cantidad,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Tipo</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.tipo,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>IdProvedor</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.idProvedor,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>NomProvedor</div>,
width: '150px',
selector: (row: DTORelPreChe) => row.nomProvedor,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>TagTabulador</div>,
width: '120px',
selector: (row: DTORelPreChe) => row.tagTabulador,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>NombreTabulador</div>,
width: '100px',
selector: (row: DTORelPreChe) => row.nombreTabulador,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Rctadeb</div>,
width: '150px',
selector: (row: DTORelPreChe) => row.rctadeb,
sortable: true,
filter: true,
center: true
},
{
name: <div style={{ textAlign: 'center' }}>Diferencia</div>,
width: '150px',
selector: (row: DTORelPreChe) => row.diferencia,
sortable: true,
filter: true,
center: true
}
];
// const generaReporte = () => {
// reportesServices
// .getRptRelacionPreChe(precuenta, cheque)
// .then((reponse) => {
// setData(reponse.data)
// setFilteredData(reponse.data)
// setHeader('informativo')
// setMsg('Se encontro la siguiente informacion...')
// setShowMsg(true)
// })
// .catch((e: Error) => {
// setHeader('Error')
// setMsg('Ocurrio un error' + e.message )
// setShowMsg(true)
// return
// })
// }
const [selectedOption, setSelectedOption] = useState<string>('Relacion'); // Valor inicial del ComboBox
const handleOptionChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedOption(event.target.value);
};
const generaReporte = () => {
switch (selectedOption) {
case 'Relacion':
reportesServices
.getRptRelacionPreChe(precuenta, cheque)
.then((response) => {
setData(response.data);
setFilteredData(response.data);
setHeader('Informativo');
setMsg('Se encontró la siguiente información...');
setShowMsg(true);
})
.catch((e: Error) => {
setHeader('Error');
setMsg('Ocurrió un error: ' + e.message);
setShowMsg(true);
});
break;
case 'Trafico':
reportesServices
.getRptRelacionesTrafico()
.then((response: any) => {
// Maneja la respuesta de Trafico
setData(response.data);
setFilteredData(response.data);
setHeader('Informativo');
setMsg('Se encontró la siguiente información...');
setShowMsg(true);
})
.catch((e: Error) => {
setHeader('Error');
setMsg('Ocurrió un error: ' + e.message);
setShowMsg(true);
});
break;
case 'NoRelaciones':
reportesServices
.getRptNoRelaciones()
.then((response: any) => {
// Maneja la respuesta de No Relacionados
setData(response.data);
setFilteredData(response.data);
setHeader('Informativo');
setMsg('Se encontró la siguiente información...');
setShowMsg(true);
})
.catch((e: Error) => {
setHeader('Error');
setMsg('Ocurrió un error: ' + e.message);
setShowMsg(true);
});
break;
default:
setHeader('Error');
setMsg('Tipo de reporte no válido');
setShowMsg(true);
break;
}
};
//
// const downloadExcel = () => {
// switch(selectedOption){
// case 'Relacion':
// exportExcel(Data, 'Datos Que se Relacionan');
// break;
// case 'Trafico' :
// exportExcel(Data, 'Relaciones Solo Trafico')
// break;
// case 'NoRelaciones':
// exportExcel(Data, 'No Se Relacionan Datos')
// break
// default:
// setHeader('Error')
// setMsg('No Valido');
// setShowMsg(true);
// break;
// }
// // exportExcel(Data, 'Datos Tabla');
// };
// function exportExcel(
// jsonData: DTORelPreChe[],
// fileName: string
// ): void {
// let Heading = [
// [
// 'Type',
// 'Cheques',
// 'Date',
// 'Num',
// 'Name',
// 'Memo',
// 'Amount',
// 'Trafico',
// 'Trafico',
// 'Precuenta',
// 'Concepto',
// 'Importe',
// 'Cantidad',
// 'Tipo',
// 'IdProvedor',
// 'NomProvedor',
// 'Tagtabulador',
// 'NombreTabulador',
// 'Rctadeb',
// 'Diferencia'
// ]
// ];
// const wb = XLSX.utils.book_new();
// const ws: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]);
// // Añadir encabezados
// XLSX.utils.sheet_add_aoa(ws, Heading);
// // Añadir datos
// XLSX.utils.sheet_add_json(ws, jsonData, { origin: 'A2', skipHeader: true });
// // Asegurarse de que la referencia esté correctamente definida
// ws['!ref'] = XLSX.utils.encode_range({
// s: { c: 0, r: 0 },
// e: { c: Heading[0].length - 1, r: jsonData.length + 1 }
// });
// // Convertir encabezados a mayúsculas
// const range = XLSX.utils.decode_range(ws['!ref']);
// for (let C = range.s.c; C <= range.e.c; ++C) {
// const address = XLSX.utils.encode_col(C) + '1'; // <-- primera fila, columna número C
// if (!ws[address]) continue;
// ws[address].v = ws[address].v.toUpperCase();
// }
// XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
// XLSX.writeFile(wb, fileName + '.xlsx');
// }
const downloadExcel = () => {
switch(selectedOption){
case 'Relacion':
exportExcel(filteredData, 'Datos Que se Relacionan', 'Reporte de Relaciones');
break;
case 'Trafico':
exportExcel(filteredData, 'Relaciones Solo Trafico', 'Reporte de Tráfico');
break;
case 'NoRelaciones':
exportExcel(filteredData, 'No Se Relacionan Datos', 'Reporte de No Relaciones');
break;
default:
setHeader('Error');
setMsg('No Válido');
setShowMsg(true);
break;
}
};
function exportExcel(
jsonData: DTORelPreChe[],
fileName: string,
reportTitle: string
): void {
const Heading = [
[
'Type',
'Cheques',
'Date',
'Num',
'Name',
'Memo',
'Amount',
'Trafico',
'Trafico',
'Precuenta',
'Concepto',
'Importe',
'Cantidad',
'Tipo',
'IdProvedor',
'NomProvedor',
'Tagtabulador',
'NombreTabulador',
'Rctadeb',
'Diferencia'
]
];
const wb = XLSX.utils.book_new();
const ws: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]);
// Añadir el título del reporte
XLSX.utils.sheet_add_aoa(ws, [[reportTitle]], { origin: 'A1' });
// Fusionar celdas para que el título cubra todas las columnas
ws['!merges'] = [
{ s: { r: 0, c: 0 }, e: { r: 0, c: Heading[0].length - 1 } }
];
// Aplicar estilo al título
const titleCell = ws['A1'];
if (titleCell) {
titleCell.s = {
font: { bold: true, sz: 18, color: { rgb: 'FFFFFF' } },
alignment: { horizontal: 'center', vertical: 'center' },
fill: { fgColor: { rgb: '4F81BD' } },
border: {
top: { style: 'thick', color: { rgb: '000000' } },
bottom: { style: 'thick', color: { rgb: '000000' } },
left: { style: 'thick', color: { rgb: '000000' } },
right: { style: 'thick', color: { rgb: '000000' } }
}
};
}
// Añadir encabezados
XLSX.utils.sheet_add_aoa(ws, Heading, { origin: 'A2' });
// Añadir datos filtrados
XLSX.utils.sheet_add_json(ws, jsonData, { origin: 'A3', skipHeader: true });
// Asegurarse de que la referencia esté correctamente definida
ws['!ref'] = XLSX.utils.encode_range({
s: { c: 0, r: 0 },
e: { c: Heading[0].length - 1, r: jsonData.length + 2 }
});
// Convertir encabezados a mayúsculas
const range = XLSX.utils.decode_range(ws['!ref']);
for (let C = range.s.c; C <= range.e.c; ++C) {
const address = XLSX.utils.encode_col(C) + '2';
if (!ws[address]) continue;
ws[address].v = ws[address].v.toUpperCase();
}
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
XLSX.writeFile(wb, fileName + '.xlsx');
}
const filtraReporte = (e: any) => {
const searchText = e.target.value.toLowerCase();
setFiltro(searchText);
const filtered = Data.filter((item) => {
return (
(item.type && item.type.toLowerCase().includes(searchText)) ||
(item.cheques && item.cheques.toString().toLowerCase().includes(searchText)) ||
(item.date && item.date.toString().toLowerCase().includes(searchText)) ||
(item.num && item.num.toString().toLowerCase().includes(searchText)) ||
(item.name && item.name.toString().toLowerCase().includes(searchText)) ||
(item.memo && item.memo.toString().toLowerCase().includes(searchText)) ||
(item.amount && item.amount.toString().toLowerCase().includes(searchText)) ||
(item.trafico && item.trafico.toString().toLowerCase().includes(searchText)) ||
(item.precuenta && item.precuenta.toString().toLowerCase().includes(searchText)) ||
(item.concepto && item.concepto.toString().toLowerCase().includes(searchText)) ||
(item.importe && item.importe.toString().toLowerCase().includes(searchText)) ||
(item.cantidad && item.cantidad.toString().toLowerCase().includes(searchText)) ||
(item.tipo && item.tipo.toString().toLowerCase().includes(searchText)) ||
(item.idProvedor && item.idProvedor.toString().toLowerCase().includes(searchText)) ||
(item.nomProvedor && item.nomProvedor.toString().toLowerCase().includes(searchText)) ||
(item.tagTabulador && item.tagTabulador.toString().toLowerCase().includes(searchText)) ||
(item.nombreTabulador && item.nombreTabulador.toString().toLowerCase().includes(searchText)) ||
(item.rctadeb && item.rctadeb.toString().toLowerCase().includes(searchText)) ||
(item.diferencia && item.diferencia.toString().toLowerCase().includes(searchText))
);
});
console.log('Filtered Data:', filtered);
setFilteredData(filtered);
}
const handleOpenModal = (file: File) => {
setSelectedFile(file)
setShowModal(true)
}
const handleCloseModal = () => {
setSelectedFile(null)
setShowModal(false)
}
const handleDeleteFile = () => {
if (selectedFile) {
if (selectedFile === bookFile) {
handleRemoveFile(selectedFile, setBookFile)
} else if (selectedFile === prectaFile) {
handleRemoveFile(selectedFile, setPrectaFile)
}
setSelectedFile(null)
setShowModal(false)
}
}
return (
<div className="mt-2">
<Card>
<Card.Body>
<Form>
<div className="d-flex justify-content-around">
<Card
className="text-center p-4 m-2"
style={{ backgroundColor: 'lightgreen', borderRadius: '8px', width: '45%' }}
>
<Form.Group>
<Form.Label className="d-block mb-2" style={{ fontWeight: 'bold' }}>
Arrastra o selecciona el archivo Book
</Form.Label>
<Form.Control
type="file"
accept=".xlsx, .xls"
onChange={(e) => handleFileChange(e as React.ChangeEvent<HTMLInputElement>, setBookFile)}
style={{ display: 'none' }}
id="bookFileInput"
/>
<label
htmlFor="bookFileInput"
className="btn btn-light d-block"
style={{ cursor: 'pointer', border: '2px solid green', borderRadius: '8px' }}
>
{bookFile ? bookFile.name : 'Seleccionar archivo'}
</label>
</Form.Group>
</Card>
<Card
className="text-center p-4 m-2"
style={{ backgroundColor: 'lightcoral', borderRadius: '8px', width: '45%' }}
>
<Form.Group>
<Form.Label className="d-block mb-2" style={{ fontWeight: 'bold' }}>
Arrastra o selecciona el archivo Precta
</Form.Label>
<Form.Control
type="file"
accept=".xlsx, .xls"
onChange={(e) => handleFileChange(e as React.ChangeEvent<HTMLInputElement>, setPrectaFile)}
style={{ display: 'none' }}
id="prectaFileInput"
/>
<label
htmlFor="prectaFileInput"
className="btn btn-light d-block"
style={{ cursor: 'pointer', border: '2px solid red', borderRadius: '8px' }}
>
{prectaFile ? prectaFile.name : 'Seleccionar archivo'}
</label>
</Form.Group>
</Card>
</div>
<Button
variant="success"
onClick={handleSendFiles}
style={{ marginTop: '10px', display: 'block', marginLeft: 'auto', marginRight: 'auto' }}
>
Enviar <FiSend />
</Button>
{message && <p className="mt-2">{message}</p>}
</Form>
<div className='row'>
<div className='col-md-1' style={{width: '5px'}}></div>
<div className='col-md-1 d-flex align-items-center' style={{ width: '300px' }}>
<select
value={selectedOption}
onChange={handleOptionChange}
className='form-select me-2'
style={{ width: 'auto' }}
>
<option value="Relacion">Relacion</option>
<option value="Trafico">Trafico</option>
<option value="NoRelaciones">No Relacionado</option>
</select>
<Button
variant='primary'
size="sm"
onClick={generaReporte}
>
Buscar <BsSearch />
</Button>
</div>
{/* <div className='col-md-4' style={{width: '120px'}}>
<Button
variant='primary'
size= "sm"
onClick={() => {
generaReporte()
}}
>
Buscar <BsSearch />
</Button>
</div> */}
<div className='col-md-1' style={{width: 'auto'}}></div>
<div className='col-md-4'>
<Form.Control
type='text'
size="sm"
placeholder='Search...'
onChange={(e) => {
filtraReporte(e)
} }
/>
</div>
<div className="col-md-1" style={{ width: '400px' }}></div>
<div className="col-md-1">
<Button
style={{ width: 'auto', whiteSpace: 'nowrap' }}
size='sm'
variant='success'
onClick={() => {
downloadExcel();
}}
>
Excel <BsFileEarmarkExcel />
</Button>
</div>
</div>
</Card.Body>
</Card>
<Card>
<Card.Body>
<div
className='ag-theme-alpine'
style={{ height: 400, width: '100%', textAlign: 'center'}}
>
<DataTable
columns={columnDefs}
data={filteredData}
defaultSortAsc={true}
striped={true}
dense= {true}
paginationPerPage={10}
pagination
highlightOnHover
pointerOnHover
style={{ height: 300, width: '100%', textAlign: 'center'}}
onRowClicked={(row ) => {
}}
/>
</div>
</Card.Body>
</Card>
{selectedFile && (
<Modal show={showModal} onHide={handleCloseModal}>
<Modal.Header closeButton>
<Modal.Title>{selectedFile.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Contenido del archivo:</p>
{/* Aquí puedes añadir la lógica para mostrar el contenido del archivo si es necesario */}
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleCloseModal}>
Cerrar
</Button>
<Button variant="danger" onClick={handleDeleteFile}>
Eliminar Archivo
</Button>
</Modal.Footer>
</Modal>
)}
<MsgInformativo
show={show}
msg={msg}
header={header}
msgColor={msgColor}
closeToast={closeToast}
/>
</div>
)
}

@ -0,0 +1,30 @@
import http from '../../../Services/common/http-common'
import ICatNotificaciones from '../interfaces/ICatNotificaciones'
//import I1868CatResponsablesCorreos from '../Interfaces/I1868CatResponsablesCorreos'
class CatNotificacionesDataServices {
Get() {
return http.get<ICatNotificaciones[]>(`/CatNotificaciones/CatNotificaciones/Get`)
}
Append(data: ICatNotificaciones) {
return http.post<ICatNotificaciones>(
`/CatNotificaciones/CatNotificaciones/Append`,
data
)
}
/* GetByResponsable(id: number) {
return http.get<I1868CatResponsablesCorreos[]>(
`/CatTransportistas/GetByResponsable?IdResponsable=${id}`
)
}
AppendData(data: I1868CatResponsablesCorreos) {
return http.post<I1868CatResponsablesCorreos[]>(
`/CatTransportistas/AppendData`,
data
)
} */
DeleteEmail(id: number) {
return http.delete<Boolean>(`/CatTransportistas/CatNotificaciones/DeleteEmail?id=${id}`)
}
}
export default new CatNotificacionesDataServices()

@ -0,0 +1,5 @@
export default interface ICatNotificaciones {
id: number,
mensaje: string,
activo: boolean
}

@ -0,0 +1,30 @@
import React, { FC, useEffect, useState } from 'react'
import { Col, Container, Row } from 'react-bootstrap'
// import DashboardCliente from './DashboardCliente'
interface IProps {}
export default function Dashboard(props: IProps) {
const [Perfil, setPerfil] = useState(() => {
const stickyValue = window.localStorage.getItem('Perfil')
return stickyValue !== null ? JSON.parse(stickyValue) : 0
})
const [User, setUser] = useState(() => {
const stickyValue = window.localStorage.getItem('User')
return stickyValue !== null ? JSON.parse(stickyValue) : 0
})
return (
<div>
<br />
<Container>
{/* <Row xs={1} md={3} className='g-4'>
{[['CLIENTE: BookPrecta Internacional', 'Administrador'].includes(Perfil) ? <DashboardCliente /> : ''].map((item) => {
return <React.Fragment>{item}</React.Fragment>
})}
</Row> */}
</Container>
</div>
)
}

@ -0,0 +1,89 @@
import * as React from 'react'
import { Card, Col } from 'react-bootstrap'
import { Link } from 'react-router-dom'
import { FcAlarmClock, FcClock } from 'react-icons/fc'
import { BsBarChart, BsBarChartFill, BsBarChartLineFill } from 'react-icons/bs'
import { IconContext } from 'react-icons'
export interface IDashboardClienteProps {}
export default function DashboardCliente(props: IDashboardClienteProps) {
return (
<>
<Col>
<Card style={{ width: '18rem' }} className='dashboardComponentFont'>
<Card.Header>CRUCES</Card.Header>
<Card.Body style={{ paddingBottom: '50px' }}>
<Card.Title>Tiempos</Card.Title>
{/* <Card.Img variant='top' src='' onClick={() => {}} /> */}
<div style={{ fontSize: '6em' }} className='text-center'>
<IconContext.Provider value={{ color: '#72F056' }}>
<BsBarChartFill />
</IconContext.Provider>
</div>
</Card.Body>
<Card.Footer style={{ paddingRight: '5px' }}>
<Link
to='../KPICruces'
style={{
textDecoration: 'none',
float: 'right',
paddingRight: '10px',
}}
>
Ver mas...
</Link>
</Card.Footer>
</Card>
</Col>
<Col>
<Card style={{ width: '18rem' }} className='dashboardComponentFont'>
<Card.Header>CRUCES</Card.Header>
<Card.Body style={{ paddingBottom: '50px' }}>
<Card.Title>Tiempo promedio</Card.Title>
{/* <Card.Img variant='top' src='' onClick={() => {}} /> */}
<div style={{ fontSize: '6em' }} className='text-center'>
<FcAlarmClock />
</div>
</Card.Body>
<Card.Footer style={{ paddingRight: '5px' }}>
<Link
to='../KPICrucesTotales'
style={{
textDecoration: 'none',
float: 'right',
paddingRight: '10px',
}}
>
Ver mas...
</Link>
</Card.Footer>
</Card>
</Col>
<Col>
<Card style={{ width: '18rem' }} className='dashboardComponentFont'>
<Card.Header>Agente Aduanal</Card.Header>
<Card.Body style={{ paddingBottom: '50px' }}>
<Card.Title>Tiempos</Card.Title>
{/* <Card.Img variant='top' src='' onClick={() => {}} /> */}
<div style={{ fontSize: '6em' }} className='text-center'>
<FcClock />
</div>
</Card.Body>
<Card.Footer style={{ paddingRight: '5px' }}>
<Link
to='../KPIAgenteAduanal'
style={{
textDecoration: 'none',
float: 'right',
paddingRight: '10px',
}}
>
Ver mas...
</Link>
</Card.Footer>
</Card>
</Col>
</>
)
}

@ -0,0 +1,175 @@
import * as React from 'react'
import { Button, Card, Col, Form, Row } from 'react-bootstrap'
import logo from '../../images/grupo-promax-b.png'
import { MsgInformativo } from '../../Utils/Toast/msgInformativo'
import ReactCaptchaa from 'react-captchaa'
import AuthDS from '../../Services/Auth/Auth.Service'
import 'react-captchaa/dist/index.css'
import '../../css/reactCaptcha.css'
import ILogin from '../../interfaces/Ilogin'
import { AxiosError } from 'axios'
import { useNavigate } from 'react-router-dom'
import { useState } from 'react'
export interface IForgotPasswordProps {}
export default function ForgotPassword(props: IForgotPasswordProps) {
const navigate = useNavigate()
const [Usuario, setUsuario] = useState('')
const [Contrasenia, setContrasenia] = useState('')
const [Captcha, setCaptcha] = useState('')
const [CaptchaText, setCaptchaText] = useState('')
const [show, setShow] = useState(false)
const [msg, setMsg] = useState('')
const [header, setHeader] = useState('')
const [msgColor, setMsgColor] = useState('primary')
const validateCaptcha = () => {
if (!Usuario.length) {
setShow(true)
setMsg('El campo usuario no puede estar vacio')
setHeader('Error')
return
}
if (Captcha !== CaptchaText) {
setShow(true)
setMsg('Captcha o usuario incorrecto')
setHeader('Error')
return
}
const data: ILogin = {
Usuario: Usuario,
Contrasena: Contrasenia,
}
AuthDS.forgotPassword(data)
.then((response: any) => {
localStorage.setItem('User', JSON.stringify(Usuario))
navigate('/PIN')
})
.catch((e: AxiosError) => {
setShow(true)
setMsg('Usuario no existe')
setHeader('Error')
})
}
return (
<div>
<Row style={{ paddingTop: '6rem' }}>
<Col xs={12}></Col>
</Row>
<Row>
<Col xs={5}>&nbsp;</Col>
<Col xs={2}>
<div
className='shadow-lg bg-white rounded'
style={{ marginLeft: 'auto', marginRight: 'auto', width:'125%' }}
>
<Card className='Color1'>
<Card.Header>
<Row style={{ backgroundColor: '#ffffff' }}>
<Col xs={12}>
<img
src={logo}
alt='ZINC Internacional'
style={{ width: '70%' }}
></img>
</Col>
</Row>
</Card.Header>
<Card.Body>
<Card.Text>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Form id='login-form' className='form'>
<Row>
<Col>
<Form.Control
id='Usuario'
className='form-control'
placeholder='Usuario'
value={Usuario}
onChange={(e) => {
setUsuario(e.target.value)
}}
/>
</Col>
</Row>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Row>
<Col xs={12}>
<ReactCaptchaa
captchaText={(captchaText: string) => {
setCaptchaText(captchaText)
}}
captchaLength={6}
captchaButtonClick={(e: any) => {}}
onCanvasClick={(e: any) => {}}
height={150}
width={200}
iconName={'FiRefreshCw'}
iconColor={'#fff'}
fontSize={'3em'}
iconSize={'1em'}
containerClassName={'react-captcha'}
iconWrapperClassName={'react-captcha-icon-wrapper'}
canvasClassName={'react-captcha-canvas'}
iconClassName={'react-captcha-icon'}
charactersInclude={
'0123456789abcdefghijklmnopqrstuvwxzABCDEFGHIJKLMNOPQRSTUVWXYZ'
}
/>
</Col>
</Row>
<Row>
<Col xs={12}>
<Form.Control
id='Captcha'
className='form-control'
placeholder='Teclee los caracteres de la imagen'
value={Captcha}
onChange={(e) => {
setCaptcha(e.target.value)
}}
/>
</Col>
</Row>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
</Form>
</Card.Text>
<div className='d-grid gap-1'></div>
<div className='d-grid gap-1'>
<Button
variant='customColor'
size='lg'
onClick={() => {
validateCaptcha()
}}
>
Continuar
</Button>
</div>
</Card.Body>
</Card>
</div>
</Col>
<Col xs={5}>&nbsp;</Col>
</Row>
<MsgInformativo
show={show}
msg={msg}
header={header}
msgColor={msgColor}
time={2000}
closeToast={function (arg: boolean): void {
setShow(false)
}}
/>
</div>
)
}

@ -0,0 +1,244 @@
import * as React from 'react'
import { useNavigate } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux'
import { logued, setProfile } from '../../Store/features/userStatusSlice/userStatusSlice'
import ILogin from '../../interfaces/Ilogin'
import ItemMenu from '../../interfaces/Catalogos/IItemMenu'
import AuthDS from '../../Services/Auth/Auth.Service'
import '../../css/login.css'
import jwt_decode from 'jwt-decode'
import IjwtStructure from '../../interfaces/IjwtStructure'
import { RootState } from '../../Store/store'
import { AxiosError } from 'axios'
import { MsgInformativo } from '../../Utils/Toast/msgInformativo'
import logo from '../../images/grupo-promax-b.png'
import Dashboard from '../Dashboard/Dashboard'
import { Button, Card, Col, Form, Nav, Row } from 'react-bootstrap'
import usuariosServices from '../../Services/Catalogos/Usuarios.Services'
// import FService from '../Cliente/Services/Facturas.Services'
// import { populateCatTransfers } from '../../store/features/Clientes/1868/CatTransfersSlice'
import { useEffect, useState } from 'react'
import Info from '../../../package.json'
export interface ILoginProps {}
export default function Login(props: ILoginProps) {
const dispatch = useDispatch()
const navigate = useNavigate()
let _menu: ItemMenu[] = []
const [mainMenu, setMainMenu] = useState(_menu)
const userLogued = useSelector((state: RootState) => state.userStatus.value)
const [show, setShow] = React.useState(false)
const [Usuario, setUsuario] = React.useState('')
const [Contrasenia, setContrasenia] = React.useState('')
const [msg, setMsg] = React.useState('')
const [header, setHeader] = React.useState('')
const [msgColor, setMsgColor] = React.useState('primary')
const menu = localStorage.getItem('menu') ? localStorage.getItem('menu') : ''
const login = () => {
const credentials: ILogin = {
Usuario: Usuario,
Contrasena: Contrasenia,
}
AuthDS.login(credentials)
.then((response: any) => {
localStorage.setItem('menu', JSON.stringify(response.data.menu))
localStorage.setItem('token', response.data.token)
localStorage.setItem(
'tokenInfo',
JSON.stringify(jwt_decode(response.data.token))
)
var values: IjwtStructure = jwt_decode(response.data.token)
localStorage.setItem('UserId', JSON.stringify(values.UserId))
localStorage.setItem('User', JSON.stringify(values.Usuario))
localStorage.setItem(
'Departamento',
JSON.stringify(values.Departamento)
)
localStorage.setItem('UserType', JSON.stringify(values.UserType))
localStorage.setItem('Perfil', JSON.stringify(values.Perfil))
dispatch(logued(true))
dispatch(setProfile(JSON.stringify(values.Perfil).replace(/"/gi, '')))
// loadTransferData()
})
.catch((e: AxiosError) => {
// AuthDS.loginTransaport(credentials)
// .then((response: any) => {
// localStorage.setItem('menu', JSON.stringify(response.data.menu))
// localStorage.setItem('token', response.data.token)
// localStorage.setItem(
// 'tokenInfo',
// JSON.stringify(jwt_decode(response.data.token))
// )
// var values: IjwtStructure = jwt_decode(response.data.token)
// localStorage.setItem('UserId', JSON.stringify(values.UserId))
// localStorage.setItem('User', JSON.stringify(values.Usuario))
// localStorage.setItem(
// 'Departamento',
// JSON.stringify(values.Departamento)
// )
// localStorage.setItem('UserType', JSON.stringify(values.UserType))
// localStorage.setItem('Perfil', JSON.stringify(values.Perfil))
// dispatch(logued(true))
// dispatch(setProfile(JSON.stringify(values.Perfil).replace(/"/gi, '')))
// // loadTransferData()
// })
// .catch((e: AxiosError) => {
localStorage.setItem('menu', '')
localStorage.setItem('token', '')
setShow(true)
setMsg('Credenciales invalidas!')
setHeader('Error')
if (e.message.includes('400')) {
setMsg('Credenciales invalidas!')
} else if (e.message.includes('401')) {
setMsg(
'Debere cambiar la contraseña, para poder entrar a este sitio'
)
}
// })
})
}
useEffect(() => {
if (menu && userLogued) {
setMainMenu(JSON.parse(menu))
} else {
setMainMenu([])
}
}, [menu, userLogued])
useEffect(() => {
usuariosServices
.validate()
.then((response) => {
if (response.status === 200) {
dispatch(logued(true))
}
})
.catch((e: Error) => {
if (!window.location.href.indexOf('login')) {
localStorage.setItem('menu', '')
localStorage.setItem('token', '')
setHeader('Informativo')
setMsg('Su session ha expirado, necesita volver a loguerse')
setShow(true)
navigate('/')
}
})
}, [dispatch, navigate])
// const loadTransferData = () => {
// FService.getCatTransfers()
// .then((response) => {
// dispatch(populateCatTransfers(response.data))
// return
// })
// .catch((e: Error) => {
// return
// })
// }
return (
<div>
{!userLogued ? (
<div>
<Row style={{ paddingTop: '6rem' }}>
<Col xs={12}></Col>
</Row>
<Row>
<Col xs={5}>&nbsp;</Col>
<Col xs={2}>
<div className='shadow-lg bg-white rounded'>
<Card style={{ width: '100%' }} className='Color1'>
<Card.Header>
<Row style={{ backgroundColor: '#ffffff' }}>
<Col xs={12}>
<img
src={logo}
alt='BookPrecta Internacional'
style={{ width: '70%' }}
></img>
</Col>
</Row>
</Card.Header>
<Card.Body>
<Card.Text>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Form id='login-form' className='form'>
<Row>
<Col>
<Form.Control
id='Usuario'
className='form-control'
placeholder='Usuario'
value={Usuario}
onChange={(e) => {
setUsuario(e.target.value)
}}
/>
</Col>
</Row>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Row>
<Col xs={12}>
<Form.Control
id='Contrasena'
className='form-control'
placeholder='Contraseña'
type='password'
value={Contrasenia}
onChange={(e) => {
setContrasenia(e.target.value)
}}
/>
</Col>
</Row>
</Form>
{/* <Nav.Link style={{color: '#002f87'}} href='/#/forgotPassword'>¿Olvido contraseña?</Nav.Link> */}
</Card.Text>
<div className='d-grid gap-1'>
</div>
<div className='d-grid gap-1'>
<Button
variant='customColor'
size='lg'
onClick={() => {
login()
}}
>
login
</Button>
</div>
<Nav.Link style={{color: '#002f87'}} href='/#/forgotPassword'>¿Olvido contraseña?</Nav.Link>
<div style={{textAlign:'right'}}>v{Info.version}</div>
</Card.Body>
</Card>
</div>
</Col>
<Col xs={5}>&nbsp;</Col>
</Row>
<MsgInformativo
show={show}
msg={msg}
header={header}
msgColor={msgColor}
closeToast={function (arg: boolean): void {
setShow(false)
}}
/>
</div>
) : (
<div>
<Dashboard />
</div>
)}
</div>
)
}

@ -0,0 +1,140 @@
import * as React from 'react'
import { Alert, Button, Card, Col, Form, Row } from 'react-bootstrap'
import logo from '../../images/grupo-promax-b.png'
import { MsgInformativo } from '../../Utils/Toast/msgInformativo'
import AuthDS from '../../Services/Auth/Auth.Service'
import { useState } from 'react'
import { DTOPINUsuario } from '../../DTO/DTOPINUsuario'
import { useNavigate } from 'react-router-dom'
import { AxiosError } from 'axios'
export interface IPINProps {}
export default function PIN(props: IPINProps) {
const navigate = useNavigate()
const [User, setUser] = useState(() => {
const stickyValue = window.localStorage.getItem('User')
return stickyValue !== null ? JSON.parse(stickyValue) : ''
})
const [Usuario, setUsuario] = useState(User)
const [PIN, setPIN] = useState('')
const [show, setShow] = useState(false)
const [msg, setMsg] = useState('')
const [header, setHeader] = useState('')
const [msgColor, setMsgColor] = useState('primary')
const validatePIN = () => {
if (!PIN.length) {
setShow(true)
setMsg('El campo PIN no puede estar vacio')
setHeader('Error')
return false
}
const data: DTOPINUsuario = {
pin: parseInt(PIN),
usuario: Usuario,
}
console.log(JSON.stringify(data))
AuthDS.validatePIN(data)
.then((response: any) => {
localStorage.removeItem('User')
localStorage.setItem('PIN', PIN)
navigate('/Reset')
})
.catch((e: any) => {
setShow(true)
setMsg('PIN invalido!')
setHeader('Error')
return false
})
}
return (
<div>
<Row style={{ paddingTop: '6rem' }}>
<Col xs={12}></Col>
</Row>
<Row>
<Col xs={5}>&nbsp;</Col>
<Col xs={2}>
<div className='shadow-lg bg-white rounded'>
<Card style={{ width: '135%' }} className='Color1'>
<Card.Header>
<Row style={{ backgroundColor: '#ffffff' }}>
<Col xs={12}>
<img
src={logo}
alt='BookPrecta Internacional'
style={{ width: '70%' }}
></img>
</Col>
</Row>
</Card.Header>
<Card.Body>
<Card.Text>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Form id='login-form' className='form'>
<Row>
<Col xs={12}>
<Form.Control
id='PIN'
className='form-control'
placeholder='PIN'
value={PIN}
onChange={(e) => {
setPIN(e.target.value)
}}
/>
</Col>
</Row>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
</Form>
</Card.Text>
<div className='d-grid gap-1'></div>
<div className='d-grid gap-1'>
<Button
variant='customColor'
size='lg'
onClick={() => {
validatePIN()
}}
>
Continuar
</Button>
</div>
</Card.Body>
</Card>
</div>
</Col>
<Col xs={5}>&nbsp;</Col>
</Row>
<Row style={{paddingTop:'100px'}}><Col xs={12}></Col></Row>
<Row>
<Col xs={2}></Col>
<Col xs={8}>
<Alert variant='warning'>
Se le ha enviado un PIN de seguridad a su cuenta de correo.
Favor de revisar en su bandeja de correo no deseado en caso
no encontrarlo. La cuenta de correo que usamos es: noreply@gemcousa.mx
</Alert>
</Col>
<Col xs={2}></Col>
</Row>
<MsgInformativo
show={show}
msg={msg}
header={header}
msgColor={msgColor}
time={2000}
closeToast={function (arg: boolean): void {
setShow(false)
}}
/>
</div>
)
}

@ -0,0 +1,197 @@
import React, { FC, useState } from 'react'
import {
Button,
Card,
Col,
Form,
Row,
Toast,
ToastContainer,
} from 'react-bootstrap'
import { MsgInformativo } from '../../Utils/Toast/msgInformativo'
import DTOUsuario from '../../DTO/DTOUsuario'
import logo from '../../images/grupo-promax-b.png'
import AuthDS from '../../Services/Auth/Auth.Service'
import { DTOResetPassword } from '../../DTO/DTOResetPassword'
interface IProps {}
export default function ResetCredentials(props: IProps) {
const [User, setUser] = useState(() => {
const stickyValue = window.localStorage.getItem('User')
return stickyValue !== null ? JSON.parse(stickyValue) : ''
})
const [PIN, setPIN] = useState(() => {
const stickyValue = window.localStorage.getItem('PIN')
return stickyValue !== null ? JSON.parse(stickyValue) : ''
})
const [header, setHeader] = useState('Error!')
const [msgColor, setMsgColor] = useState('primary')
const [showMsg, setShowMsg] = useState(false)
const [msg, setMsg] = useState('')
const [Usuario, setUsuario] = useState(User)
const [Contrasena, setContrasena] = useState('')
const [ConfirmaContrasena, setConfirmaContrasena] = useState('')
const [show, setShow] = useState(false)
const validaFormulario = () => {
if (Contrasena.length===0 || ConfirmaContrasena.length===0) {
setShow(true)
setMsg('La contraseña no puede estar vacia!')
setHeader('Error')
return
}
if (Contrasena !== ConfirmaContrasena) {
setShow(true)
setMsg('Contraseña no coincide con la confirmacion!')
setHeader('Error')
return
}
const data: DTOResetPassword = {
pin: PIN,
contrasena: Contrasena,
}
AuthDS.resetPassword(data)
.then((response) => {
if (response.status == 200) {
setShow(true)
setMsg('La contraseña se cambio exitosamente!')
setHeader('Confirmacion')
return false
}
})
.catch((e: Error) => {
setShow(true)
setMsg('Ocurrio un error')
setHeader('Error')
return false
})
}
const closeToast = (show: boolean): void => {
setShowMsg(false)
}
return (
<div>
<div>
<Row style={{ paddingTop: '6rem' }}>
<Col xs={12}></Col>
</Row>
<Row>
<Col xs={5}>&nbsp;</Col>
<Col xs={2}>
<div className='shadow-lg bg-white rounded'>
<Card style={{ width: '100%' }} className='Color1'>
<Card.Header>
<Row style={{ backgroundColor: '#ffffff' }}>
<Col xs={12}>
<img
src={logo}
alt=' BookPrecta Internacional'
style={{ width: '70%' }}
></img>
</Col>
</Row>
</Card.Header>
<Card.Body>
<Card.Text>
<Row
style={{
backgroundColor: '#572364',
color: '#ffffff',
fontSize: '19px',
}}
>
<Col xs={12}>Proporcione su nueva contraseña?</Col>
</Row>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Form id='login-form' className='form'>
<Row style={{ height: '0px' }}>
<Col>
<Form.Control
style={{ visibility: 'hidden' }}
id='PIN'
className='form-control'
placeholder='PIN'
value={PIN}
/>
</Col>
</Row>
<Row>
<Col xs={12}>
<Form.Control
id='Contrasena'
className='form-control'
placeholder='Contraseña'
type='password'
value={Contrasena}
onChange={(e) => {
setContrasena(e.target.value)
}}
/>
</Col>
</Row>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Row>
<Col xs={12}>
<Form.Control
id='Contrasena'
className='form-control'
placeholder='Confirme contraseña'
type='password'
value={ConfirmaContrasena}
onChange={(e) => {
setConfirmaContrasena(e.target.value)
}}
/>
</Col>
</Row>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
</Form>
</Card.Text>
<div className='d-grid gap-2'>
<Button
variant='customColor'
size='lg'
onClick={() => {
validaFormulario()
}}
>
reset
</Button>
</div>
</Card.Body>
</Card>
</div>
</Col>
<Col xs={5}>&nbsp;</Col>
</Row>
<MsgInformativo
show={show}
msg={msg}
time={2000}
header={header}
msgColor={msgColor}
closeToast={function (arg: boolean): void {
setShow(false)
}}
/>
</div>
{/* <MsgInformativo
show={showMsg}
time={2000}
msg={msg}
header={header}
msgColor={msgColor}
closeToast={closeToast}
/> */}
</div>
)
}

@ -0,0 +1,21 @@
import { FC, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { useDispatch } from 'react-redux'
import { logued } from '../../Store/features/userStatusSlice/userStatusSlice'
interface IProps {}
const Logout: FC<IProps> = (props) => {
const dispatch = useDispatch()
let navigate = useNavigate()
useEffect(() => {
window.localStorage.clear()
dispatch(logued(false))
navigate('/')
})
return <div></div>
}
export default Logout

@ -0,0 +1,37 @@
import { FC } from 'react'
import { NavDropdown } from 'react-bootstrap'
import IUsuariosPerfilesMenu from '../../interfaces/IPerfilesMenu'
interface IProps {
menu: IUsuariosPerfilesMenu[] | undefined
}
const MenuUsuario: FC<IProps> = (props) => {
return (
<div>
{props.menu
? props.menu.map((mainMenu) => {
return mainMenu.padreId === 0 ? (
<NavDropdown title={mainMenu.descripcion} id='basic-nav-dropdown'>
{props.menu
? props.menu.map((item) => {
return item.padreId === mainMenu.itemMenu ? (
<NavDropdown.Item key={item.id} href={item.url}>
{item.descripcion}
</NavDropdown.Item>
) : (
''
)
})
: null}
</NavDropdown>
) : (
''
)
})
: null}
</div>
)
}
export default MenuUsuario

@ -0,0 +1,233 @@
import React, { FC, useEffect, useState } from 'react'
import { Alert, Button, Col, Form, Modal, Row, Table } from 'react-bootstrap'
import DataTable from 'react-data-table-component'
import { IRegister } from '../../../interfaces/IRegister'
import usuariosServices from '../../../Services/Catalogos/Usuarios.Services'
import PerfilesServices from '../../../Services/Catalogos/PerfilesMenu.Services'
import { IPerfil } from '../../../interfaces/Catalogos/IPerfiles'
import { IconContext } from 'react-icons'
import {
BsCheckCircleFill,
BsCheckLg,
BsFillPersonCheckFill,
BsFillPersonDashFill
} from 'react-icons/bs'
interface IProps {
show: boolean
CloseModal: (arg: boolean) => void
GetUserInfo: (arg: IRegister) => void
}
export const UserList: React.FC<IProps> = (props) => {
const [sDialog, setsDialog] = React.useState(true)
const [Usuarios, setUsuarios] = React.useState<IRegister[]>()
const [Data, setData] = useState<IRegister[]>([])
const [DataPerfiles, setDataPerfiles] = useState<IPerfil[]>([])
const [DataOriginal, setDataOriginal] = useState<IRegister[]>([])
const [filtro, setFiltro] = useState('')
const columnsConcepts = [
{
name: 'id',
width: '70px',
cell: (row: IRegister) => (
<div
style={{ width: '100%' }}
onClick={() => {
props.GetUserInfo(row)
}}
>
{row.id}
</div>
),
sortable: true
},
{
name: 'Usuario',
width: '200px',
cell: (row: IRegister) => (
<div
style={{ width: '100%' }}
onClick={() => {
props.GetUserInfo(row)
}}
>
{row.usuario}
</div>
),
sortable: true
},
{
name: 'Nombre',
width: '250px',
cell: (row: IRegister) => (
<div
style={{ width: '100%' }}
onClick={() => {
props.GetUserInfo(row)
}}
>
{row.nombre}
</div>
),
sortable: true
},
{
name: 'Correo',
width: '250px',
cell: (row: IRegister) => (
<div
style={{ width: '100%' }}
onClick={() => {
props.GetUserInfo(row)
}}
>
{row.correo}
</div>
),
sortable: true
},
{
name: 'Perfil',
width: '250px',
cell: (row: IRegister) => (
<div
style={{ width: '100%' }}
onClick={() => {
props.GetUserInfo(row)
}}
>
{getProfile(row.idPerfil)}
</div>
),
sortable: true
},
{
name: 'Estatus',
width: '90px',
cell: (row: IRegister) => (
<div
style={{ width: '100%', textAlign:'center' }}
onClick={() => {
props.GetUserInfo(row)
}}
>
{row.activo == 1 ? (
<IconContext.Provider value={{ color: 'green', size: '20px' }}>
<BsCheckCircleFill />
</IconContext.Provider>
) : (
<IconContext.Provider value={{ color: 'red', size: '20px' }}>
<BsFillPersonDashFill />
</IconContext.Provider>
)}
</div>
),
sortable: true
}
]
const getProfile = (Id: number) => {
const NoAsignado = ' - NO ASIGNADO -'
if (Id === 0) return NoAsignado
else if (DataPerfiles) {
const Profile = DataPerfiles.filter((item) => item.id === Id)
console.log(Profile)
return Profile ? Profile[0].perfil : NoAsignado
}
return NoAsignado
}
useEffect(() => {
usuariosServices
.getAllUsuarios()
.then((response) => {
setData(response.data)
setDataOriginal(response.data)
})
.catch((e: Error) => {
console.log(e)
})
PerfilesServices.getAllPerfiles()
.then((response) => {
setDataPerfiles(response.data)
})
.catch((e: Error) => {
console.log(e)
})
}, [props.show])
const filtraReporte = (e: any) => {
setFiltro(e.target.value)
if (e.target.value.length > 0) {
setData(
Data.filter(function (row) {
return (
row.id.toString().includes(e.target.value) ||
row.usuario.toLowerCase().includes(e.target.value) ||
row.nombre.toLowerCase().includes(e.target.value) ||
row.correo.toLowerCase().includes(e.target.value)
)
})
)
} else {
setData(DataOriginal)
}
}
return props.show ? (
<Modal
{...props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
dialogClassName={'modal-70w'}
>
<Modal.Header>
<Modal.Title id="contained-modal-title-vcenter"></Modal.Title>
</Modal.Header>
<Alert>
<Row>
<Col xs={2}>
<h5>Lista de usuarios</h5>
</Col>
<Col xs={10}>
<Form.Control
type="text"
size="sm"
placeholder="Search..."
onChange={(e) => {
filtraReporte(e)
}}
/>
</Col>
</Row>
</Alert>
<Modal.Body>
<DataTable
noHeader
defaultSortFieldId={'id'}
defaultSortAsc={true}
striped={true}
dense={true}
paginationPerPage={10}
pagination
highlightOnHover
columns={columnsConcepts}
data={Data}
pointerOnHover
/>
</Modal.Body>
<Modal.Footer>
<Button
onClick={() => {
props.CloseModal(false)
}}
>
Close
</Button>
</Modal.Footer>
</Modal>
) : null
}

@ -0,0 +1,251 @@
import React, { FC, useEffect } from 'react'
import { Button, Modal, Table } from 'react-bootstrap'
import IPerfilesMenu from '../../../interfaces//IPerfilesMenu'
import perfilesMenuServices from '../../../Services/Catalogos/PerfilesMenu.Services'
import { IPerfil } from '../../../interfaces/Catalogos/IPerfiles'
import { NuevoPerfil } from './nuevoPerfil/NuevoPerfil'
import { NuevoItemMenu } from './nuevoItemMenu/NuevoItemMenu'
import DTOItemMenuPerfil from '../../../DTO/DTOItemMenuPerfil'
import '../../../css/menu2.css'
import '../../../css/generic01.css'
interface IProps {
show: boolean
CloseModal: (arg: boolean) => void
CloseModalPerfiles: (arg: boolean) => void
}
interface IPropsChild {
item: IPerfilesMenu
menu: IPerfilesMenu[]
IdPerfil: number
}
const MenuChild: React.FC<IPropsChild> = (props) => {
const [DialogNewItemMenu, setDialogNewItemMenu] = React.useState(false)
const [ItemMenu, setItemMenu] = React.useState(0)
function addItemMenu(id: number, e: any) {
const data: DTOItemMenuPerfil = {
IdPerfil: props.IdPerfil,
itemMenu: id,
asignado: e.currentTarget.checked,
}
perfilesMenuServices
.toggleItemMenu(data)
.then((response) => {})
.catch((e: Error) => {})
}
const createItemMenu = (value: boolean): void => {
alert('crea item menu')
}
const CloseModalItemMenu = (show: boolean): void => {
setDialogNewItemMenu(false)
}
return (
<>
<li>
<input
className='form-check-input'
type='checkbox'
value=''
defaultChecked={props.item.agrupado == 1 ? true : false}
id={'Chk' + props.item.id}
onClick={(e) => {
addItemMenu(props.item.id, e)
}}
/>
&nbsp;
<a href='javascript:;'>
{props.item.descripcion}
<span
onClick={() => {
setItemMenu(props.item.id)
setDialogNewItemMenu(true)
}}
>
... +
</span>
</a>
<ul>
{props.menu.map((m, index) =>
m.padreId === props.item.id ? (
<li>
<input
className='form-check-input'
type='checkbox'
value=''
defaultChecked={m.agrupado == 1 ? true : false}
id={'Chk' + m.id}
onClick={(e) => {
addItemMenu(m.id, e)
}}
/>
&nbsp;
<a href='javascript:;'>
{m.descripcion}
<span
onClick={() => {
setItemMenu(m.id)
setDialogNewItemMenu(true)
}}
>
... ++
</span>
</a>
<ul>
{props.menu
.filter((m2) => m2.padreId === m.id)
.map((m2, index) => (
<li>
<input
className='form-check-input'
type='checkbox'
value=''
defaultChecked={m2.agrupado == 1 ? true : false}
id={'Chk_lv2' + m2.id}
onClick={(e) => {
addItemMenu(m2.id, e)
}}
/>
&nbsp;
<a href=''>{m2.descripcion}</a>
</li>
))}
</ul>
</li>
) : (
''
)
)}
</ul>
</li>
<NuevoItemMenu
show={DialogNewItemMenu}
ItemMenu={ItemMenu}
CloseModalPerfiles={CloseModalItemMenu}
/>
</>
)
}
export const AdmonPerfiles: React.FC<IProps> = (props) => {
const [sDialog, setsDialog] = React.useState(true)
const [DialogNewProfile, setDialogNewProfile] = React.useState(false)
const [Menu, setMenu] = React.useState<IPerfilesMenu[]>()
const [IdPerfil, setIdPerfil] = React.useState(0)
const [Perfiles, setPerfiles] = React.useState<IPerfil[]>()
useEffect(() => {
perfilesMenuServices
.getAllPerfiles()
.then((response) => {
setPerfiles(response.data)
})
.catch((e: Error) => {})
loadPerfil(0)
}, [props.show])
function loadPerfil(id: number) {
setMenu([])
perfilesMenuServices
.getPerfilMenuById(id)
.then((response) => {
setMenu(response.data)
})
.catch((e: Error) => {
console.log(e)
})
}
const createProfile = (value: boolean): void => {
alert('crea nuevo perfil')
}
const CloseModalPerfiles = (show: boolean): void => {
setDialogNewProfile(false)
}
const onChangePerfil = (e: any): void => {
setIdPerfil(e.currentTarget.value)
loadPerfil(e.currentTarget.value)
}
return props.show ? (
<>
<Modal
{...props}
size='lg'
aria-labelledby='contained-modal-title-vcenter'
centered
contentClassName=''
>
<Modal.Header>
<Modal.Title id='contained-modal-title-vcenter'>
<div className='container'>
<div className='row'>Administrador de perfiles</div>
<div className='row'>
<div className='col-auto'>
<select
className='form-select'
aria-label='Perfiles'
onChange={onChangePerfil}
>
{Perfiles?.map((p) => {
return <option value={p.id}>{p.perfil}</option>
})}
</select>
</div>
<div className='col'></div>
<div className='col-auto'>
<button
type='button'
className='btn btn-primary'
onClick={() => {
setDialogNewProfile(true)
}}
>
Nuevo
</button>
</div>
</div>
</div>
</Modal.Title>
</Modal.Header>
<Modal.Body className='divPerfiles'>
<div className='tree' style={{ backgroundColor: '#FFFFFF' }}>
<ul>
<li>
<a href='#'>Menu</a>
<ul>
{Menu?.map((item, index) =>
item.padreId === 0 ? (
<MenuChild menu={Menu} item={item} IdPerfil={IdPerfil} />
) : (
''
)
)}
</ul>
</li>
</ul>
</div>
</Modal.Body>
<Modal.Footer>
<Button
onClick={() => {
props.CloseModal(false)
}}
>
Close
</Button>
</Modal.Footer>
</Modal>
<NuevoPerfil
show={DialogNewProfile}
createProfile={createProfile}
CloseModalPerfiles={CloseModalPerfiles}
/>
</>
) : null
}

@ -0,0 +1,195 @@
import React, { FC, useEffect } from 'react'
import { Button, Modal, Toast, ToastContainer } from 'react-bootstrap'
import { propTypes } from 'react-bootstrap/esm/Image'
// import { IPerfil } from '../../../../Interfaces/Catalogos/IPerfiles'
// import pefilesMenuServices from '../../../../Services/Catalogos/PerfilesMenu.Services'
import perfilesMenuServices from '../../../../Services/Catalogos/PerfilesMenu.Services'
import DTOPerfilCreate from '../../../../DTO/DTOPerfilCreate'
import IPerfilesMenu from '../../../../interfaces/IPerfilesMenu'
import IItemMenu from '../../../../interfaces//Catalogos/IItemMenu'
interface IProps {
show: boolean
ItemMenu: number
CloseModalPerfiles: (arg: boolean) => void
}
export const NuevoItemMenu: FC<IProps> = (props) => {
const [ItemMenu, setItemMenu] = React.useState(props.ItemMenu)
const [descripcion, setDescripcion] = React.useState('')
const [posicion, setPosicion] = React.useState(1)
const [url, setUrl] = React.useState('')
const [MenuItems, setMenuItems] = React.useState<IPerfilesMenu[]>()
const [msgError, setMsgError] = React.useState('')
const [msgDialog, setMsgDialog] = React.useState(false)
useEffect(() => {
console.log('props=' + JSON.stringify(props))
}, [props])
useEffect(() => {
perfilesMenuServices
.getMenu()
.then((response) => {
setMenuItems(response.data)
console.log(response.data)
})
.catch((e: Error) => {
console.log(e)
})
setItemMenu(props.ItemMenu)
}, [props.show])
function validatePerfil() {
var msg = 'Proporcione: '
if (!descripcion.length) msg += 'la descripcion / '
if (!url.length) msg += 'la URL'
if (msg != 'Proporcione: ') {
setMsgError(msg)
setMsgDialog(true)
}
const data: IItemMenu = {
id: 0,
padreId: ItemMenu,
posicion: posicion,
descripcion: descripcion,
url: url,
}
perfilesMenuServices
.createItemMenu(data)
.then((response) => {
if (response.status == 200)
alert('El item de menu se creo existosamente!')
console.log(response.data)
})
.catch((e: Error) => {
console.log(e)
})
console.log(ItemMenu + ' ' + descripcion + ' ' + posicion + ' ' + url)
}
const onChangeItem = (e: any): void => {
//value: number = e.currentTarget.value;
setItemMenu(e.currentTarget.value)
}
return (
<Modal show={props.show}>
<Modal.Header>
<Modal.Title>Nuevo item de menu</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className='row'>
<form>
<div className='mb-3'>
<label className='form-label'>El item sera hijo de:</label>
<select
className='form-select'
aria-label='Perfiles'
defaultValue={ItemMenu}
onChange={onChangeItem}
value={ItemMenu}
>
<option value='0'>Menu</option>
{MenuItems?.map((m) => {
return m.id === props.ItemMenu ? (
<option value={m.id}>{m.descripcion}</option>
) : null
})}
</select>
</div>
<div className='mb-3'>
<label className='form-label'>Descripcion</label>
<input
className='form-control'
id='Descripcion'
aria-describedby='Descripcion'
onChange={(e) => {
setDescripcion(e.currentTarget.value)
}}
/>
</div>
<div className='mb-3'>
<label className='form-label'>Posicion</label>
<select
className='form-select'
aria-label='Perfiles'
onChange={(e) => {
setPosicion(parseInt(e.currentTarget.value))
}}
>
{[...Array(41)].map((x, i) =>
i > 0 ? <option value={i}>{i}</option> : null
)}
</select>
</div>
<div className='mb-3'>
<label className='form-label'>Url</label>
<input
className='form-control'
id='url'
aria-describedby='url'
onChange={(e) => {
setUrl(e.target.value)
}}
/>
</div>
</form>
</div>
</Modal.Body>
<Modal.Footer>
<div className='row'>
<div className='col'>
<Button
variant='secondary'
onClick={() => {
props.CloseModalPerfiles(false)
}}
>
Cerrar
</Button>
</div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'>
<Button
variant='primary'
onClick={() => {
//props.createProfile(true);
validatePerfil()
}}
>
Guardar
</Button>
</div>
</div>
</Modal.Footer>
<ToastContainer position={'middle-center'}>
<Toast
onClose={() => setMsgDialog(false)}
show={msgDialog}
delay={3000}
bg='dark'
autohide
>
<Toast.Header>
<strong className='me-auto'>Error!</strong>
</Toast.Header>
<Toast.Body style={{ backgroundColor: '#F8F9F9' }}>
{msgError}
</Toast.Body>
</Toast>
</ToastContainer>
</Modal>
)
}

@ -0,0 +1,125 @@
import React, { FC, useEffect } from 'react'
import { Button, Modal } from 'react-bootstrap'
import { propTypes } from 'react-bootstrap/esm/Image'
import { IPerfil } from '../../../../interfaces/Catalogos/IPerfiles'
import perfilesMenuServices from '../../../../Services/Catalogos/PerfilesMenu.Services'
import DTOPerfilCreate from '../../../../DTO/DTOPerfilCreate'
interface IProps {
show: boolean
CloseModalPerfiles: (arg: boolean) => void
createProfile: (value: true) => void
}
export const NuevoPerfil: FC<IProps> = (props) => {
const [IdPerfil, setIdPerfil] = React.useState(0)
const [nombrePerfil, setnombrePerfil] = React.useState('')
const [Perfiles, setPerfiles] = React.useState<IPerfil[]>()
useEffect(() => {
perfilesMenuServices
.getAllPerfiles()
.then((response) => {
setPerfiles(response.data)
console.log(response.data)
})
.catch((e: Error) => {
console.log(e)
})
}, [props.show])
function validatePerfil() {
if (!nombrePerfil.length) alert('Proporcione el nombre del perfil')
const data: DTOPerfilCreate = {
Perfil: nombrePerfil,
IdPerfilClonado: IdPerfil,
}
perfilesMenuServices
.createPerfil(data)
.then((response) => {
if (response.status == 200) alert('El perfil se creo existosamente')
console.log(response.data)
})
.catch((e: Error) => {
console.log(e)
})
}
const onChangePerfil = (e: any): void => {
setIdPerfil(e.currentTarget.value)
}
return (
<Modal show={props.show}>
<Modal.Header>
<Modal.Title>Nuevo perfil</Modal.Title>
</Modal.Header>
<Modal.Body>
<div className='row'>
<form>
<div className='mb-3'>
<label className='form-label'>
Clona informacion del perfil:
</label>
<select
className='form-select'
aria-label='Perfiles'
onChange={onChangePerfil}
>
{Perfiles?.map((p) => {
return <option value={p.id}>{p.perfil}</option>
})}
</select>
</div>
<div className='mb-3'>
<label className='form-label'>Nombre</label>
<input
type='email'
className='form-control'
id='exampleInputEmail1'
aria-describedby='emailHelp'
onChange={(e) => {
setnombrePerfil(e.currentTarget.value)
}}
/>
</div>
</form>
</div>
</Modal.Body>
<Modal.Footer>
<div className='row'>
<div className='col'>
<Button
variant='secondary'
onClick={() => {
props.CloseModalPerfiles(false)
}}
>
Cerrar
</Button>
</div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'>
<Button
variant='primary'
onClick={() => {
//props.createProfile(true);
validatePerfil()
}}
>
Guardar
</Button>
</div>
</div>
</Modal.Footer>
</Modal>
)
}

@ -0,0 +1,847 @@
import * as React from 'react'
import { Formik, Form, Field } from 'formik'
import '../../css/generic01.css'
import * as Yup from 'yup'
import { IRegister } from '../../interfaces/IRegister'
import {
Accordion,
Alert,
Button,
Card,
Form as Frm,
Modal,
Tab,
Table,
Tabs,
Toast,
ToastContainer,
} from 'react-bootstrap'
import { useEffect, useState } from 'react'
import IPerfilesMenu from '../../interfaces/IPerfilesMenu'
import { IPerfil } from '../../interfaces/Catalogos/IPerfiles'
// import PerfilesMenuServices from '../../Services/Catalogos/PerfilesMenu.Services'
import PerfilesMenuServices from '../../Services/Catalogos/PerfilesMenu.Services'
// import ClientesServices from '../../Services/Catalogos/Clientes.Services'
import usuariosServices from '../../Services/Catalogos/Usuarios.Services'
import MenuUsuario from '../MenuUsuario/MenuUsuario'
// import IClientes from '../../Interfaces/Catalogos/IClientes'
import DTOUsuarioCliente from '../../DTO/DTOUsuarioCliente'
// import ITransportistas from '../../Interfaces/Catalogos/ITransportitas'
// import IProveedores from '../../Interfaces/Catalogos/IProveedores'
// import DTOasignaClienteProveedor from '../../DTO/DTOasignaClienteProveedor'
// import DTOClienteTransportista from '../../DTO/DTOClienteTransportita'
import ITokenInfo from '../../interfaces/Utils/ITokenInfo'
import { UserList } from './UserList/UserList'
import DTOUsuariosShort from '../../DTO/DTOUsuariosShort'
import DTOClonarUsuario from '../../DTO/DTOClonarUsuario'
import { AdmonPerfiles } from './admonPerfiles/AdmonPerfiles'
import { Form as FormCtrl } from 'react-bootstrap'
interface IProps {}
const SignupSchema = Yup.object().shape({
usuario: Yup.string()
.min(6, 'Usuario demasiado corto')
.max(50, 'Usuario demasiado largo')
.required('Requerido'),
nombre: Yup.string()
.min(6, 'Nombre de usuario demasiado corto')
.max(100, 'Nombre de usuario demasiado largo')
.required('Requerido'),
contrasena: Yup.string()
.min(6, 'Contraseña demasiado corta')
.max(50, 'Contraseña demasiado larga'),
correo: Yup.string().email('Correo invalido').required('Requirido'),
})
export default function Register(props: IProps) {
const [UserId, setUserId] = useState(() => {
const stickyValue = window.localStorage.getItem('UserId')
return stickyValue !== null ? JSON.parse(stickyValue) : 0
})
const [showDialog, setShowDialog] = React.useState(false)
const [modalUserList, setModalUserList] = React.useState(false)
const [modalAdmonPerfiles, setmodalAdmonPerfiles] = React.useState(false)
const [msgDialog, setmsgDialog] = React.useState('')
const [Asignaciones, setAsignacion] = useState(false)
const [IdUsuario, setIdUsuario] = useState(0)
const [Usuario, setUsuario] = useState('')
const [Nombre, setNombre] = useState('')
const [Contrasena, setContrasena] = useState('')
const [Correo, setCorreo] = useState('')
const [TipoUsuario, setTipoUsuario] = useState(2)
const [Activo, setActivo] = useState(1)
const [FechaAlta, setFechaAlta] = useState('')
const [UsuarioAlta, setUsuarioAlta] = useState(0)
const [FechaModifico, setFechaModifico] = useState('')
const [UsuarioModifico, setUsuarioModifico] = useState(0)
const [FechaElimino, setFechaElimino] = useState('')
const [UsuarioElimino, setUsuarioElimino] = useState(0)
const [MotivoElimino, setMotivoelimino] = useState('')
const [IdModulo, setIdModulo] = useState(0)
const [Dept, setDept] = useState(0)
const [TMercancia, setTMercancia] = useState(0)
const [FechaUltimaVisita, setFechaUltimaVisita] = useState('')
const [Visitas, setVisitas] = useState(0)
const [Internos, setInternos] = useState(0)
const [PermisoEspecial, setPermisoEspecial] = useState(0)
const [EstadoConfiguracion, setEstadoConfiguracion] = useState(0)
const [FechaValidacionConf, setFechaValidacionConf] = useState('')
const [RealizoEncuesta, setRealizoEncuesta] = useState('')
const [EncuestaActiva, setEncuestaActiva] = useState(0)
const [FechaLimiteEncuesta, setFechaLimiteEnuesta] = useState('')
const [CodigoAccesoM, setCodigoAccesoM] = useState('')
const [TokenAccesoM, setTokenAccesoM] = useState('')
const [DeviceToken, setDeviceToken] = useState('')
const [IdPerfil, setIdPerfil] = useState(0)
const [user2Clone, setUser2Clone] = React.useState(0)
const [perfiles, setPerfiles] = useState<IPerfil[]>([
{
id: 0,
perfil: '-SELECCIONE-',
},
])
// const [clientes, setClientes] = useState<IClientes[]>([])
// const [transportistas, setTransportistas] = useState<ITransportistas[]>([])
// const [proveedores, setProveedores] = useState<IProveedores[]>([])
const [comboUsuarios, setcomboUsuarios] = useState<DTOUsuariosShort[]>([])
const [toastPerfil, setToastPerfil] = useState(false)
const [UsuariosPerfilesMenu, setUsuariosPerfilesMenu] =
useState<IPerfilesMenu[]>()
const [perfilActual, setPerfilActual] = useState<IPerfilesMenu[]>()
const [showConfirmation, setShowConfirmation] = useState(false)
const [usuarioDestino, setUsuarioDestino] = useState('')
const [Search, setSearch] = useState('')
var initialValues: IRegister = {
id: IdUsuario,
usuario: Usuario,
nombre: Nombre,
contrasena: Contrasena,
correo: Correo,
tipoUsuario: TipoUsuario,
activo: Activo,
fechaAlta: currentDate(),
usuarioAlta: IdUsuario,
fechaModifico: currentDate(),
usuarioModifico: UsuarioModifico,
fechaElimino: FechaElimino,
usuarioElimino: 0,
motivoElimino: MotivoElimino,
idModulo: IdModulo,
dept: Dept,
tmercancia: TMercancia,
fechaUltimaVisita: FechaUltimaVisita,
visitas: Visitas,
internos: Internos,
permisoEspecial: PermisoEspecial,
estadoConfiguracion: EstadoConfiguracion,
fechaValidacionConf: FechaValidacionConf,
realizoEncuesta: RealizoEncuesta,
encuestaActiva: EncuestaActiva,
fechaLimiteEncuesta: FechaLimiteEncuesta,
codigoAccesoM: CodigoAccesoM,
tokenAccesoM: TokenAccesoM,
deviceToken: DeviceToken,
idPerfil: IdPerfil,
}
const initialValuesPerfiles: IPerfil = {
id: IdPerfil,
perfil: '',
}
function getUsuario() {
const item = localStorage.getItem('tokenInfo')
let Usr = ''
if (item) {
const registro: ITokenInfo = JSON.parse(item)
Usr = registro.Usuario
}
return Usr
}
/* useEffect(() => {
if (!isNaN(IdUsuario)) {
PerfilesMenuServices.getAllPerfilesMenu()
.then((response) => {
setUsuariosPerfilesMenu(response.data)
})
.catch((e: Error) => { })
}
}, []) */
useEffect(() => {
if (!isNaN(IdUsuario)) {
PerfilesMenuServices.getAllPerfiles()
.then((response) => {
setPerfiles(response.data)
})
.catch((e: Error) => {})
}
}, [])
useEffect(() => {
usuariosServices
.getAllUsuariosShort()
.then((response) => {
setcomboUsuarios(response.data)
})
.catch((e: Error) => {})
}, [])
/* useEffect(() => {
if (IdUsuario > 0) {
ClientesServices.getUsuariosAsignados(IdUsuario)
.then((response) => {
setClientes(response.data)
})
.catch((e: Error) => { })
PerfilesMenuServices.getAllTransportitas(IdUsuario)
.then((response) => {
setTransportistas(response.data)
})
.catch((e: Error) => { })
PerfilesMenuServices.getAllProveedores(IdUsuario)
.then((response) => {
setProveedores(response.data)
})
.catch((e: Error) => { })
}
}, [IdUsuario]) */
/* const handleSelect = (e: any) => {
setPerfiles(e)
} */
function currentDate(): string {
var today = new Date()
var dd = String(today.getDate()).padStart(2, '0')
var mm = String(today.getMonth() + 1).padStart(2, '0') //January is 0!
var yyyy = today.getFullYear()
return mm + '/' + dd + '/' + yyyy
}
/* const validateForm = (values: IRegister) => {
const errors = { usuario: '', nombre: '', contrasena: '', correo: '' }
if (!values.usuario) {
errors.usuario = 'Campo Usuario es requerido'
} else if (values.usuario.length > 50) {
errors.usuario = 'Debe contener 50 caracteres o menos'
}
if (!values.nombre) {
errors.nombre = 'Campo Nombre es requerido'
} else if (values.nombre.length > 100) {
errors.nombre = 'Debe contener 100 caracteres o menos'
}
if (!values.correo) {
errors.correo = 'Campo correo es requerido'
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.correo)
) {
errors.correo = 'Correo invalido'
}
return errors
}
*/
function toggleShowPerfil() {
setToastPerfil(!toastPerfil)
}
function construyePerfil(values: IPerfil) {
if (UsuariosPerfilesMenu) {
console.log(UsuariosPerfilesMenu)
var opcionesPerfil = UsuariosPerfilesMenu.filter(function (el) {
return el.idPerfil == values.id
})
setPerfilActual(opcionesPerfil)
}
}
async function addCliente(id: number, e: any) {
const asignacionUsuarioCliente: DTOUsuarioCliente = {
sClave: id,
IdUsuario: IdUsuario,
agregar: e.currentTarget.checked,
}
// ClientesServices.create(asignacionUsuarioCliente)
// .then((response) => {
// loadProveedores()
// })
// .catch((e: Error) => {
// console.log(e)
// })
// }
// async function asignaClienteProveedor(
// sClaveCliente: string,
// sClave: string,
// e: any
// ) {
// const data: DTOasignaClienteProveedor = {
// IdUsuario: IdUsuario,
// sClaveCliente: sClaveCliente,
// sClave: sClave,
// asignado: e.currentTarget.checked,
// }
// console.log('data= ' + JSON.stringify(data))
// ClientesServices.asignaClienteProveedor(data)
// .then((response) => {
// console.log('Asignacion ' + JSON.stringify(response))
// })
// .catch((e: Error) => {})
}
async function asignaClienteTransportista(sClave: string, e: any) {
// const data: DTOClienteTransportista = {
// IdUsuario: IdUsuario,
// sClave: sClave,
// asignado: e.currentTarget.checked,
// }
// ClientesServices.asignaClienteTransportista(data)
// .then((response) => {
// console.log('Asignacion ' + JSON.stringify(response))
// })
// .catch((e: Error) => {})
}
function loadProveedores() {
// console.log('Entro a cargar proveedores ')
// PerfilesMenuServices.getAllProveedores(1)
// .then((response) => {
// setProveedores(response.data)
// })
// .catch((e: Error) => {})
}
function createUser(data: IRegister) {
usuariosServices
.create(data)
.then((response) => {
// console.log(JSON.stringify(response));
if (response.status === 200) {
setmsgDialog('El usuario ha sido guardado existosamente')
setShowDialog(true)
}
})
.catch((e: Error) => {
setmsgDialog('Ocurrio un error: ' + e)
setShowDialog(true)
})
}
const CloseModal = (show: boolean): void => {
setModalUserList(false)
}
const CloseModalAP = (show: boolean): void => {
setmodalAdmonPerfiles(false)
}
const CloseModalPerfiles = (show: boolean): void => {
//setmodalAdmonPerfiles(false);
}
//function loadAllUserInfo(id: number) {}
const GetUserInfo = (data: IRegister): void => {
setIdUsuario(data.id)
setUsuario(data.usuario)
setNombre(data.nombre)
setContrasena(data.contrasena)
setCorreo(data.correo)
setIdPerfil(data.idPerfil)
setTipoUsuario(data.tipoUsuario)
console.log('info usuario=' + JSON.stringify(data))
//loadAllUserInfo(data.id)
}
const clonaInformacion = (): void => {
if (IdPerfil == 0) {
setToastPerfil(true)
setmsgDialog('')
return
} else setShowConfirmation(true)
}
const ChangeUser2Clone = (e: any): void => {
setUser2Clone(e.target.value)
const usr = comboUsuarios.filter((item) => item.id == e.target.value)
setUsuarioDestino(usr[0].usuario)
}
const handleClose = () => setShowConfirmation(false)
const procedeClonacion = () => {
const data: DTOClonarUsuario = {
idUsuarioOrigen: IdUsuario,
idUsuarioDestino: user2Clone,
}
usuariosServices
.clonarUsuario(data)
.then((response) => {
if (response.status == 200) {
setToastPerfil(true)
setmsgDialog('Usuario clonado existosamente')
}
})
.catch((e: Error) => {
console.log(e)
})
setShowConfirmation(false)
}
const onChangePerfil = (e: any): void => {
setIdPerfil(e.currentTarget.value)
}
return (
<div className='container' style={{ paddingTop: '10px' }}>
<div className='row'>
<div className='col'>
<Card>
<Card.Body>
<Formik
enableReinitialize
initialValues={initialValues}
validationSchema={SignupSchema}
onSubmit={(values, actions) => {
console.log(values, actions)
createUser(values)
}}
// validate={validateForm}
>
{(formik) => {
const {
errors,
touched,
isValid,
dirty,
values,
handleSubmit,
} = formik
return (
<Form
id='login-form'
className='form'
onSubmit={handleSubmit}
>
<Accordion defaultActiveKey='0'>
<Accordion.Item eventKey='0'>
<Accordion.Header>
Informacion obligatoria
</Accordion.Header>
<Accordion.Body>
<div className='row'>
<div className='col'>
<Button
variant='primary'
onClick={() => setModalUserList(true)}
>
Ver usuarios
</Button>
<UserList
show={modalUserList}
CloseModal={CloseModal}
GetUserInfo={GetUserInfo}
/>
</div>
<div className='col'>
<Button
variant='btn btn-secondary'
onClick={() => setmodalAdmonPerfiles(true)}
>
Admon perfiles
</Button>
<div>
<AdmonPerfiles
show={modalAdmonPerfiles}
CloseModal={CloseModalAP}
CloseModalPerfiles={CloseModalPerfiles}
/>
</div>
</div>
</div>
<div className='row'>
<div className='col'>
<div className='form-group'>
<div className='label'>ID</div>
<Field
id='ID'
name='ID'
className='form-control'
placeholder=''
value={formik.values.id}
disabled='disabled'
/>
</div>
</div>
<div className='col'>
<div className='form-group'>
<label
className='text-info'
htmlFor='usuario'
style={{ color: '#000000' }}
>
Usuario
</label>
<Field
id='usuario'
name='usuario'
className='form-control'
placeholder='usuario'
/>
{errors.usuario && touched.usuario ? (
<div>
{' '}
<span style={{ color: '#FF3346' }}>
{' '}
* {errors.usuario}{' '}
</span>{' '}
</div>
) : null}
</div>
</div>
</div>
<div className='row'>
<div className='col'>
<div className='form-group'>
<label className='text-info' htmlFor='Nombre' style={{ color: '#572364' }} >
Nombre
</label>
<Field
id='nombre'
name='nombre'
className='form-control'
placeholder='nombre'
/>
{errors.nombre && touched.nombre ? (
<div>
{' '}
<span style={{ color: '#FF3346' }}>
{' '}
* {errors.nombre}{' '}
</span>{' '}
</div>
) : null}
</div>
</div>
<div className='col'>
<div className='form-group'>
<label
className='text-info'
htmlFor='password'
>
Contraseña
</label>
<Field
id='contrasena'
name='contrasena'
className='form-control'
placeholder='contraseña'
type='password'
disabled='diabled'
/>
</div>
</div>
</div>
<div className='row'>
<div className='col'>
<div className='form-group'>
<label className='text-info' htmlFor='correo'>
Correo
</label>
<Field
id='correo'
name='correo'
className='form-control'
placeholder='correo'
/>
{errors.correo && touched.correo ? (
<span style={{ color: '#FF3346' }}>
{' '}
<div>* {errors.correo}</div>{' '}
</span>
) : null}
</div>
</div>
<div className='col'>
<div className='form-group'>
<label
className='text-info'
htmlFor='tipousuario'
>
Tipo usuario
</label>
<FormCtrl.Control
as='select'
id='tipousuario'
name='tipousuario'
value={formik.values.tipoUsuario}
onChange={(e) =>
setTipoUsuario(parseInt(e.target.value))
}
className='form-select form-select-sm'
>
<option value='1'>Administrador</option>
<option value='2'>Operacional</option>
{/* <option value='3'>GEMCO</option>
<option value='4'>BROKER</option> */}
</FormCtrl.Control>
</div>
</div>
</div>
<div className='row'>
<div className='col'>
<div className='form-group'>
<label className='text-info' htmlFor='activo'>
Activo
</label>
<Field
as='select'
name='activo'
className='form-control'
>
<option value='1'>Activo</option>
<option value='0'>Inactivo</option>
</Field>
</div>
</div>
<div className='col'>
{' '}
<div className='form-group'>
<label
className='text-info'
htmlFor='fechaAlta'
>
Fecha alta
</label>
<Field
id='fechaAlta'
name='fechaAlta'
readOnly='readOnly'
className='form-control'
placeholder='fecha alta'
defaultValue={currentDate()}
/>
</div>
</div>
</div>
<div className='row'>
<div className='col'>
<div className='form-group'>
<label
className='text-info'
htmlFor='usuarioAlta'
>
Usuario alta
</label>
<Field
as='select'
name='usuarioAlta'
className='form-control'
>
<option value={IdUsuario}>
{getUsuario()}
</option>
</Field>
</div>
</div>
<div className='col'>
<div className='form-group'>
<label
className='text-info'
htmlFor='fechaModifico'
>
Fecha modifico
</label>
<Field
id='fechaModifico'
name='fechaModifico'
readOnly='readOnly'
className='form-control'
placeholder='Fecha modifico'
defaultValue={currentDate()}
/>
</div>
</div>
</div>
</Accordion.Body>
</Accordion.Item>
</Accordion>
<div className='row'>
<br />
</div>
<div className='row'>
<div className='col'></div>
<div className='col'></div>
<div className='col'>
<button
type='submit'
className='btn btn-primary btn-lg btn-block'
>
Guardar
</button>
</div>
</div>
</Form>
)
}}
</Formik>
</Card.Body>
</Card>
</div>
<div className='col'>
<Card style={IdUsuario > 0 ? {} : { display: 'none' }}>
<Card.Body>
<div className='row'>
<div className='col'>
<div className='row'>
<div className='form-group'>
<Alert variant='primary'>
<Alert.Heading>
Seleccione el perfil que utilizara el usuario
</Alert.Heading>
</Alert>
<br />
<div className='form-group col-md-12'>
<Formik
initialValues={initialValuesPerfiles}
onSubmit={(values: any, actions: any) => {
console.log({ values, actions })
construyePerfil(values)
actions.setSubmitting(false)
}}
>
<Form id='FrmPerfiles' className='form'>
<div className='form-group'>
<Field
as='select'
id='id'
name='id'
className='form-select form-select-sm'
placeholder='Perfil'
value={IdPerfil}
onChange={onChangePerfil}
>
{perfiles.map((p) => {
return (
<option value={p.id}>{p.perfil}</option>
)
})}
</Field>
</div>
<br />
{/* <Button type="submit" variant="primary">
Preview
</Button>
<br /> */}
</Form>
</Formik>
</div>
</div>
</div>
</div>
{/* <div className="col">
<MenuUsuario menu={perfilActual} />
</div> */}
</div>
<br />
{/* <div className="row">
<div className="col">
<Button
type="submit"
variant="primary"
onClick={() => {
clonaInformacion()
}}
>
Clonar informacion para:
</Button>
</div>
<div className="col">
<select
className="form-select"
aria-label="Default select example"
value={user2Clone}
onChange={ChangeUser2Clone}
>
<option value={0}>-Seleccione-</option>
{comboUsuarios.map((u) => {
return <option value={u.id}>{u.usuario}</option>
})}
</select>
</div>
</div> */}
<ToastContainer position='middle-center'>
<Toast show={toastPerfil} onClose={toggleShowPerfil}>
<Toast.Header>
<strong className='me-auto'>Error!</strong>
</Toast.Header>
<Toast.Body>
Seleccione un perfil, para poder continuar...
</Toast.Body>
</Toast>
</ToastContainer>
</Card.Body>
</Card>
</div>
</div>
<ToastContainer position={'middle-center'}>
<Toast
onClose={() => setShowDialog(false)}
show={showDialog}
delay={3000}
bg='dark'
autohide
>
<Toast.Header>
<strong className='me-auto'>Informacion</strong>
</Toast.Header>
<Toast.Body style={{ backgroundColor: '#F8F9F9' }}>
{msgDialog}
</Toast.Body>
</Toast>
</ToastContainer>
<Modal show={showConfirmation} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Favor de confirmar</Modal.Title>
</Modal.Header>
<Modal.Body>
¿Esta seguro de que desea clonar la informacion de : <br />[ {Usuario}{' '}
] para ... [ {usuarioDestino} ] ?
</Modal.Body>
<Modal.Footer>
<div className='row'>
<div className='col'>
<Button variant='secondary' onClick={handleClose}>
No
</Button>
</div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'></div>
<div className='col'>
<Button variant='primary' onClick={procedeClonacion}>
Si
</Button>
</div>
</div>
</Modal.Footer>
</Modal>
</div>
)
}

@ -0,0 +1,445 @@
import * as react from 'react'
import { useState } from 'react'
import reportesServices from '../../../Services/Reportes/reportes.services'
import DataTable from 'react-data-table-component'
import {DTOTotalHours} from '../../../DTO/Reportes/DTOTotalHours'
import * as XLSX from 'xlsx'
import { MsgInformativo } from '../../../Utils/Toast/msgInformativo'
import { Button, Card, Form, Col, Row, ToastHeader, CardBody, } from 'react-bootstrap';
import { BsSearch, BsFileEarmarkExcel } from 'react-icons/bs'
import { DTOWorkingHours } from '../../../DTO/DTOWorkingHours'
export default function RptTotalHours ()
{
const [Inicio, setInicio] = useState(currentDate())
const [Fin , setFin] = useState(currentDate)
const [filtro, setFiltro] = useState('')
const [filteredData, setFilteredData] = useState<Array<DTOTotalHours>> (
[]
)
const [filteredDataDet, setFilteredDataDet] = useState <Array<DTOWorkingHours>>(
[]
)
const [Data, setData] = useState<Array<DTOTotalHours>> ([])
const [DataDet , setDataDet ] = useState <Array <DTOWorkingHours>> ([])
const [showToast, setShowToast] = useState<boolean>(false);
const [toastMsg, setToastMsg] = useState<string>('');
const [toastHeader, setToastHeader] = useState<string>('');
const [toastColor, setToastColor] = useState<string>('');
function currentDate (): string {
var today = new Date()
var dd = String(today.getDate()).padEnd(2,'0')
var mm = String(today.getMonth() + 1 ).padStart(2, '0')
var yyyy = today.getFullYear()
return yyyy+'-' + mm + '-' + dd
}
const generarRptRes = () => {
reportesServices.getRptTotalHours(Inicio, Fin)
.then((response) => {
setData(response.data)
setFilteredData(response.data)
setToastMsg('Se econtro la siguiente informacion');
setToastHeader('Informativo');
setToastColor('success');
setShowToast(true);
})
.catch((e:Error) => {
// alert('Ocurrio un Error'+e.message.toString())
setToastMsg('No se ha introducido fechas validas')
setToastHeader('Error')
setToastColor('danger')
setShowToast(true)
return;
} )
}
const generarRptDet = () => {
reportesServices.getRptWorkingHours(Inicio, Fin)
.then((response) => {
setDataDet(response.data);
})
.catch((e: Error) => {
setToastMsg('Fechas No Validas');
setToastHeader('Error');
setToastColor('danger');
setShowToast(true);
});
};
const columnsConcepts = [
{
name: 'EmpNo',
width : '100px',
selector : (row : DTOTotalHours ) => row.empNo,
sortable: true,
filter : true
},
{
name: 'AcNo',
width : '100px',
selector : (row : DTOTotalHours) => row.acNo,
sortable : true,
filter : true
},
{
name: 'Name',
width : '200px',
selector: (row: DTOTotalHours) => row.name,
sortable: true,
filter: true
},
{
name: 'TotalHoursAccumulated',
width: '200px',
selector : (row: DTOTotalHours ) => row.totalHoursAccumulated,
sortable : true,
filter : true
},
{
name: 'TotalHoursWithMilitaryMinutes',
with: '100px',
selector : (row: DTOTotalHours) => row.totalHoursWithMilitaryMinutes,
filter : true
}
]
const columnsConceptsDet = [
[
{
name: 'Name' ,
selector : (row: DTOWorkingHours ) => row.name,
sortable : true,
filter : true
},
{
name: 'EmpNo',
selector : (row : DTOWorkingHours ) => row.empNo,
sortable: true,
filter : true
}
]
]
// const donwloadExel = () => {
// exportExcel(filteredData, 'ReporteTotalHoras' )
// }
// const exportExcel = (jsonData: any[], fileName: string) => {
// const Heading = [
// [
// 'EmpNo',
// 'AcNo',
// 'No',
// 'TotalHoursAccumuled',
// 'TotalHoursWithMilitaryMinutes'
// ]
// ]
// const Heading1 = [[
// 'EmpNo', 'AcNo', 'Name', 'Date', 'ClockIn1', 'ClockOut1 ' ,'ClockIn1', 'ClockOut1 ' ,
// 'ClockIn2', 'ClockOut2 ', 'ClockIn3', 'ClockOut3 ', 'ClockIn4', 'ClockOut4 ',
// 'ClockIn5', 'ClockOut5 '
// ]]
// const wb = XLSX.utils.book_new()
// const ws: XLSX.WorkSheet = XLSX.utils.json_to_sheet([])
// XLSX.utils.sheet_add_aoa(ws, Heading)
// XLSX.utils.sheet_add_json(ws, jsonData, { origin: 'A2', skipHeader: true })
// XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
// XLSX.writeFile(wb, `${fileName}.xlsx`)
// const range = XLSX.utils.decode_range(ws['!ref']!)
// for (let C = range.s.c; C <= range.e.c; ++C) {
// const address = XLSX.utils.encode_col(C) + '1'
// if (!ws[address]) continue
// ws[address].v = ws[address].v.toUpperCase()
// }
// }
const donwloadExel = () => {
exportExcel(filteredData, DataDet, 'ReporteTotal');
};
const exportExcel = (jsonData1: any[], jsonData2: any[], fileName: string) => {
const Heading1 = [
[
'EmpNo',
'AcNo',
'No',
'TotalHoursAccumuled',
'TotalHoursWithMilitaryMinutes'
]
];
const Heading2 = [
[
'EmpNo', 'AcNo', 'Name', 'Date', 'ClockIn1', 'ClockOut1', 'ClockIn1', 'ClockOut1',
'ClockIn2', 'ClockOut2', 'ClockIn3', 'ClockOut3', 'ClockIn4', 'ClockOut4',
'ClockIn5', 'ClockOut5' , 'TotalInTime'
]
];
// Crear libro de trabajo
const wb = XLSX.utils.book_new();
// Hoja 1
const ws1: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]);
XLSX.utils.sheet_add_aoa(ws1, Heading1);
XLSX.utils.sheet_add_json(ws1, jsonData1, { origin: 'A2', skipHeader: true });
XLSX.utils.book_append_sheet(wb, ws1, 'Resumen');
// Hoja 2
const ws2: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]);
XLSX.utils.sheet_add_aoa(ws2, Heading2);
XLSX.utils.sheet_add_json(ws2, jsonData2, { origin: 'A2', skipHeader: true });
XLSX.utils.book_append_sheet(wb, ws2, 'Detalle');
// Convertir títulos a mayúsculas en ambas hojas
const capitalizeHeaders = (ws: XLSX.WorkSheet) => {
const range = XLSX.utils.decode_range(ws['!ref']!);
for (let C = range.s.c; C <= range.e.c; ++C) {
const address = XLSX.utils.encode_col(C) + '1';
if (!ws[address]) continue;
ws[address].v = ws[address].v.toUpperCase();
}
};
capitalizeHeaders(ws1);
capitalizeHeaders(ws2);
// Escribir y descargar el archivo Excel
XLSX.writeFile(wb, `${fileName}.xlsx`);
};
const filtraReporte1 = (e: any) => {
const searchText = e.target.value.toLowerCase();
setFiltro(searchText)
const filtered = DataDet.filter((iteam) => {
return (
(iteam.empNo && iteam.empNo.toString().toLocaleUpperCase().includes(searchText)) ||
(iteam.name && iteam.name.toString().toLocaleLowerCase().includes(searchText) )
)
} )
setFilteredDataDet(filtered)
}
const filtraReporte = (e: any) => {
const searchText = e.target.value.toLowerCase();
setFiltro(searchText)
const filtered = Data.filter((iteam) => {
return (
(iteam.empNo && iteam.empNo.toString().toLocaleUpperCase().includes(searchText)) ||
(iteam.name && iteam.name.toString().toLocaleLowerCase().includes(searchText) )
)
} )
setFilteredData(filtered)
}
const generReportes = () => {
generarRptRes()
generarRptDet()
}
// const filtros = (e: any) => {
// filtraReporte(e);
// filtraReporte1(e);
// }
return(
<div className='mt-2'>
{/* <Card className="mt-3"> */}
<Card.Body>
<Form>
<Row className="align-items-center">
<Col xs={1}>
{/* <Form.Label>Desde</Form.Label> */}
<Col style={{textAlign: 'center'}} >Desde</Col>
<Form.Control
defaultValue={Inicio}
type="date"
name="Inicio"
placeholder="Inicio"
title="Inicio"
alt="Inicio"
data-date-format="YYYY-mm-dd"
onChange={(e) => setInicio(e.target.value)}
size="sm"
/>
</Col>
<Col xs={2}>
{/* <Form.Label>Hasta</Form.Label> */}
<Col style={{textAlign: 'center'}} >Hasta</Col>
<Form.Control
defaultValue={Fin}
type="date"
name="Fin"
placeholder="Fin"
title="Fin"
alt="Fin"
onChange={(e) => setFin(e.target.value)}
size="sm"
/>
</Col>
<Col xs={2}>
<Form.Control
type="text"
size="sm"
placeholder="Search..."
onChange={ (e) => {
filtraReporte(e)
} }
// onChange={filtros}
style={{ height: '10px', padding: '5px' }}
/>
</Col>
<Col xs={2}>
<Button
// size="sm"
variant="success"
onClick={donwloadExel}
style={{ width: '35%' }}
>
<BsFileEarmarkExcel />
&nbsp;Excel
</Button>
</Col>
<Col xs={2}>
<Button
variant="primary"
onClick={generReportes}
style={{ width: '40%' }}
>
<BsSearch />
Buscar
</Button>
</Col>
</Row>
</Form>
</Card.Body>
{/* </Card> */}
<MsgInformativo
show={showToast}
msg={toastMsg}
header={toastHeader}
msgColor={toastColor}
closeToast={setShowToast}
/>
<Card className='mt-3'>
<Card.Body>
<div className='ag-theme-alpine' style={{ height: 500, width: '100%'}}>
<DataTable
noHeader
defaultSortFieldId={''}
defaultSortAsc = {true}
striped= {true}
dense = {true}
paginationPerPage={10}
pagination
highlightOnHover
columns={columnsConcepts}
data={filteredData}
pointerOnHover
/>
</div>
</Card.Body>
</Card>
</div>
)
}

@ -0,0 +1,62 @@
import * as React from 'react'
import { NavDropdown } from 'react-bootstrap'
import ItemMenu from '../../interfaces/Catalogos/IItemMenu'
interface ISubmenuProps {
submenu: ItemMenu[]
descripcion: string
allItems: ItemMenu[]
}
const Submenu: React.FunctionComponent<ISubmenuProps> = (props) => {
const esPadre = (ItemSubmenu: ItemMenu, allItems: ItemMenu[]) => {
var arrHijos = allItems.filter(function (item) {
return ItemSubmenu.id === item.padreId
})
if (arrHijos.length) return true
else return false
}
return (
<div>
{
<>
<NavDropdown title={props.descripcion} id="basic-nav-dropdown">
{props.submenu.map((item, index) => {
return !esPadre(item, props.allItems) ? (
<>
<NavDropdown.Item key={item.id} href={'/#/' + item.url}>
{item.descripcion}
</NavDropdown.Item>
</>
) : (
<>
<NavDropdown
title={item.descripcion}
id="secondlevel"
className=""
drop="end"
>
{props.allItems
.filter(function (row) {
return row.padreId === item.id
})
.map((row, index) => {
return (
<NavDropdown.Item key={row.id} href={'/#/' + row.url}>
{row.descripcion}
</NavDropdown.Item>
)
})}
</NavDropdown>
</>
)
})}
</NavDropdown>
</>
}
</div>
)
}
export default Submenu

@ -0,0 +1,260 @@
import { useEffect, useState } from 'react'
import { Alert, Button, Card, Col, Form, Modal, Row } from 'react-bootstrap'
import UsuariosDS from '../../Services/Catalogos/Usuarios.Services'
import { MsgInformativo } from '../../Utils/Toast/msgInformativo'
import DTOUsuariosShort from '../../DTO/DTOUsuariosShort'
import { IconContext } from 'react-icons'
import {
BsCheckCircleFill,
BsFillPencilFill,
BsFillXCircleFill,
} from 'react-icons/bs'
import DataTable from 'react-data-table-component'
import { IUsuario } from '../../interfaces/IUsuario'
export interface IUserControlProps {}
export default function UserControl(props: IUserControlProps) {
const [Usuario, setUsuario] = useState('')
const [IDEstatus, setIDEstatus] = useState(false)
const [IDUser, setIDUser] = useState(0)
const [header, setHerader] = useState('Error!')
const [msgColor, setMsgColor] = useState('Primary')
const [showMsg, setShowMsg] = useState(false)
const [ModalDisableUser, setModalDisableUser] = useState(false)
const [UsersData, setUsersData] = useState<DTOUsuariosShort[]>([])
const [msg, setMsg] = useState('')
const colData = [
{
name: 'id',
width: '100px',
selector: (row: DTOUsuariosShort) => row.id,
sortable: true,
},
{
name: 'Usuario',
selector: (row: DTOUsuariosShort) => row.usuario,
},
{
name: '',
width: '80px',
cell: (row: DTOUsuariosShort) => (
<div
style={{ textAlign: 'center', cursor: 'pointer' }}
onClick={() => {
setIDUser(row.id)
setIDEstatus(row.activo)
setUsuario(row.usuario)
}}
>
<IconContext.Provider value={{ color: 'blue', size: '25px' }}>
<BsFillPencilFill />
</IconContext.Provider>
</div>
),
},
{
name: 'Activo',
width: '80px',
cell: (row: DTOUsuariosShort) => (
<div
style={{ textAlign: 'center', cursor: 'pointer' }}
onClick={() => {
setIDUser(row.id)
setIDEstatus(row.activo)
setUsuario(row.usuario)
setModalDisableUser(true)
}}
>
{row.activo ? (
<IconContext.Provider value={{ color: 'green', size: '25px' }}>
<BsCheckCircleFill />
</IconContext.Provider>
) : (
<IconContext.Provider value={{ color: 'red', size: '25px' }}>
<BsFillXCircleFill />
</IconContext.Provider>
)}
</div>
),
},
]
const loadUsers = () => {
UsuariosDS.getAllUsuariosShort()
.then((response) => {
//console.log(response.data)
setUsersData(response.data)
})
.catch((e: Error) => {
setMsg('Ocurrio un error: ' + e.toString())
setShowMsg(true)
})
}
useEffect(() => {
loadUsers()
}, [])
const disableUser = () => {
UsuariosDS.disableUser(IDUser)
.then((response) => {
setModalDisableUser(false)
loadUsers()
})
.catch((e: Error) => {
setMsg('Ocurrio un error: ' + e.toString())
setShowMsg(true)
})
}
const createUser = () => {
const data: IUsuario = {
id: IDUser,
usuario: Usuario,
nombre: Usuario,
correo: Usuario
}
UsuariosDS.create(data)
.then((response) => {
setModalDisableUser(false)
loadUsers()
})
.catch((e: Error) => {
setMsg('Ocurrio un error: ' + e.toString())
setShowMsg(true)
})
}
function closeToast(arg: boolean): void {
throw new Error('Function not implemented.')
}
return (
<div>
<Row>
<Col xs={12}>&nbsp;</Col>
</Row>
<Row>
<Col></Col>
<Col xs={4}>
<Card>
<Card.Header style={{ fontWeight: 'bold', fontSize: '20px' }}>
Control de usuarios
</Card.Header>
<Card.Body>
<Card.Text>
<Row>
<Col xs={2}>Usuario</Col>
<Col xs={10}>
<Form.Control
id='Usuario'
className='form-control'
placeholder='Usuario'
value={Usuario}
onChange={(e) => {
setUsuario(e.target.value)
}}
/>
</Col>
</Row>
</Card.Text>
<Row>
<Col xs={10}></Col>
<Col xs={2}>
<Button variant='primary' onClick={()=>{createUser()}}>Guarda</Button>
</Col>
</Row>
</Card.Body>
</Card>
</Col>
<Col xs={3}></Col>
<Col xs={3}>
<Card>
<Card.Header style={{ fontWeight: 'bold', fontSize: '20px' }}>
Lista de usuarios
</Card.Header>
<Card.Body>
<Card.Text>
<Row>
<Col xs={12}>
<DataTable
noHeader
defaultSortFieldId={'id'}
defaultSortAsc={true}
pagination
highlightOnHover
columns={colData}
data={UsersData.filter(function (row) {
return row
})}
/>
</Col>
</Row>
</Card.Text>
</Card.Body>
</Card>
</Col>
<Col></Col>
</Row>
<Modal
show={ModalDisableUser}
onHide={() => setModalDisableUser(false)}
size='lg'
>
<Modal.Body>
<Card className='labelSize13px'>
<Card.Body>
<Card>
<Row>
<Col xs={12}>
<Alert variant='warning' style={{ textAlign: 'center' }}>
<h6>
Esta seguro de { IDEstatus ? 'deshabilitar' : 'habilitar'} este este usuario ({Usuario})?
<br />
</h6>
</Alert>
</Col>
</Row>
<Row style={{ paddingTop: '10px', paddingBottom: '10px' }}>
<Col></Col>
<Col xs={1}>
<Button
variant='secondary'
style={{ textAlign: 'right' }}
onClick={() => {
setModalDisableUser(false)
}}
>
Cerrar
</Button>
</Col>
<Col xs={7}></Col>
<Col xs={3}>
<Button
variant={IDEstatus ? 'danger' : 'primary'}
onClick={() => {
disableUser()
}}
>
{ IDEstatus ? 'Deshabilitar' : 'Habilitar'}
</Button>
</Col>
</Row>
</Card>
</Card.Body>
</Card>
</Modal.Body>
</Modal>
<MsgInformativo
show={showMsg}
msg={msg}
header={header}
msgColor={msgColor} closeToast={()=> {}} />
</div>
)
}

@ -0,0 +1,5 @@
export class TargetURL {
get() {
return process.env.REACT_APP_API
}
}

@ -0,0 +1,4 @@
export default interface DTOClonarUsuario {
idUsuarioOrigen: number;
idUsuarioDestino: number;
}

@ -0,0 +1,5 @@
export default interface DTPItemMenuPerfil {
IdPerfil: number;
itemMenu: number;
asignado: boolean;
}

@ -0,0 +1,4 @@
export interface DTOPINUsuario {
pin: number,
usuario: string
}

@ -0,0 +1,4 @@
export default interface DTOPerfilCreate {
Perfil: string;
IdPerfilClonado: number;
}

@ -0,0 +1,26 @@
export interface DTORelPreChe {
type : string,
cheques : string,
date : string,
num : string,
name : string,
memo : string,
amount : string,
trafico : string,
trafico1 : string,
precuenta : string,
concepto : string,
importe : string,
cantidad : string,
tipo : string,
idProvedor : string,
nomProvedor : string,
tagTabulador : string,
nombreTabulador : string,
rctadeb : string,
diferencia : string;
}

@ -0,0 +1,4 @@
export interface DTOResetPassword {
pin: number,
contrasena: string
}

@ -0,0 +1,4 @@
export default interface DTOUsuario {
Usuario: string;
Contrasena : string;
}

@ -0,0 +1,5 @@
export default interface IDTOUsuarioCliente {
sClave: number;
IdUsuario: number;
agregar: boolean;
}

@ -0,0 +1,5 @@
export default interface DTOUsuariosShort {
id: number,
usuario: string,
activo: boolean
}

@ -0,0 +1,21 @@
export interface DTOWorkingHours {
empNo : string,
acNo : string,
no : string,
name: string,
date: string,
clockIn1: string,
clockOut1: string,
clockIn2: string,
clockOut2: string,
clockIn3: string,
clockOut3: string,
clockIn4: string,
clockOut4: string,
clockIn5: string,
clockOut5: string,
totalInTime : string,
totalHoursWorked : string
}

@ -0,0 +1,11 @@
export interface DTOTotalHours {
empNo : string ,
acNo : string,
name : string,
totalHoursAccumulated : string
totalHoursWithMilitaryMinutes : string
}

@ -0,0 +1,36 @@
import http from "../common/http-common";
import ILogin from "../../interfaces/Ilogin"
import ItemMenuData from "../../interfaces/Catalogos/IItemMenu";
import Token from '../../interfaces/token'
import IRespuesta from "../../interfaces/IRespuesta";
import { DTOPINUsuario } from "../../DTO/DTOPINUsuario";
import DTOUsuario from "../../DTO/DTOUsuario";
import { DTOResetPassword } from "../../DTO/DTOResetPassword";
class authDataService {
constructor() {
// super();
type token = string;
type returnData = [ItemMenuData[], Token]
}
login(data: ILogin) {
return http.post<[ItemMenuData[], Token]>("/Auth", data);
}
// loginTransaport(data: ILogin) {
// return http.post<[ItemMenuData[], Token]>("/Auth/AreYouTransport", data);
// }
forgotPassword(data: ILogin) {
return http.post<IRespuesta>("/Auth/forgotPassword", data);
}
validatePIN(data: DTOPINUsuario) {
return http.post<IRespuesta>("/Auth/validatePIN", data);
}
resetPassword(data: DTOResetPassword) {
return http.post<DTOUsuario>("/Auth/resetPassword", data);
}
}
export default new authDataService();

@ -0,0 +1,52 @@
import http from '../common/http-common'
import ILogin from '../../interfaces/Ilogin'
// import ItemMenuData from '../../Interfaces/Catalogos/IItemMenu'
import IPerfilesMenu from '../../interfaces/IPerfilesMenu'
import { IPerfil } from '../../interfaces/Catalogos/IPerfiles'
// import ITransportista from '../../Interfaces/Catalogos/ITransportitas'
// import IProveedores from '../../Interfaces/Catalogos/IProveedores'
import DTOPerfilCreate from '../../DTO/DTOPerfilCreate'
import DTOItemMenuPerfil from '../../DTO/DTOItemMenuPerfil'
import IItemMenu from '../../interfaces/Catalogos/IItemMenu'
//import DTOasignaClienteProveedor from '../DTO/DTOasignaClienteProveedor'
class PerfilesMenuService {
/**
*
*/
constructor() {
// super();
type token = string
type returnData = [IPerfilesMenu[]]
}
getAllPerfiles() {
return http.get<IPerfil[]>('/Perfiles/getPerfiles')
}
getMenu() {
return http.get<IPerfilesMenu[]>('/Perfiles/getMenu')
}
getPerfilMenuById(id: number) {
return http.get<IPerfilesMenu[]>(`/Perfiles/getPerfilMenuById?id=${id}`)
}
getAllPerfilesMenu() {
return http.get<IPerfilesMenu[]>('/Perfiles/getAllPerfilesMenu')
}
// getAllTransportitas(id: number) {
// return http.get<ITransportista[]>(`/Perfiles/getAllTransportistas?id=${id}`)
// }
// getAllProveedores(id: number) {
// return http.get<IProveedores[]>(`/Perfiles/getAllProveedores/?id=${id}`)
// }
createItemMenu(data: IItemMenu) {
return http.post<[IItemMenu]>('/Perfiles/createItemMenu', data)
}
createPerfil(data: DTOPerfilCreate) {
return http.post<[DTOPerfilCreate[]]>('/Perfiles/createPerfil', data)
}
toggleItemMenu(data: DTOItemMenuPerfil) {
return http.post<[DTOItemMenuPerfil[]]>('/Perfiles/asignaItemMenu', data)
}
}
export default new PerfilesMenuService()

@ -0,0 +1,37 @@
import http from '../common/http-common'
import DTORelacionBookPrecta from '../../Componest/Catalogos/CatRelacionBookPrecta/DTO/DTORelacionBookPrecta'
import DtoPrecuentaCheques from '../../Componest/Catalogos/CatRelacionBookPrecta/DTO/DTOPrecuentaCheques'
class RelacionChequesPrecuenta{
GETRelacionBookPrecta(Inicio: string, Fin: string){
return http.get<DTORelacionBookPrecta[]>(`/CatalogoRelaciones/GetAll?Inicio=${Inicio}&Fin=${Fin}`)
}
GETRelacionBookPrectaPreChe(Precuenta:string, Cheques: string)
{
return http.get<DTORelacionBookPrecta[]>(`/Catalogos/CatRelacionesBookPrecta/GetAllPreChe?Precuenta=${Precuenta}&Cheques=${Cheques}`)
}
PostAppedPrecuentaCheques(Precuenta: string, Cheques: string )
{
return http.post<DtoPrecuentaCheques[]> (`/Catalogos/CatRelacionesBookPrecta/PrecuentaChequesAppend?Precuenta=${Precuenta}&Cheques=${Cheques}`)
}
GetAllPrecuentaCheques()
{
return http.get <DtoPrecuentaCheques[]> ('/Catalogos/CatRelacionesBookPrecta/GetAllPrecuentaCheques')
}
DeletePrecuentaCheques(Precuenta: string)
{
return http.delete <DtoPrecuentaCheques[]> (`/Catalogos/CatRelacionesBookPrecta/DeleteAllPrecuentaCheques?Precuenta=${Precuenta}`)
}
}
export default new RelacionChequesPrecuenta()

@ -0,0 +1,50 @@
import http from "../common/http-common";
import { IRegister } from "../../interfaces/IRegister";
import DTOUsuariosShort from "../../DTO/DTOUsuariosShort";
import DTOClonarUsuario from "../../DTO/DTOClonarUsuario";
import DTOUsuario from "../../DTO/DTOUsuario";
import { IUsuario } from "../../interfaces/IUsuario";
class usuariosService {
constructor() {
}
validate() {
return http.get<null>("/Auth/validate");
}
getAllUsuarios() {
return http.get<IRegister[]>("/Usuarios/getAllUsuarios");
}
getAllUsuariosShort() {
return http.get<DTOUsuariosShort[]>("/Usuarios/getAllUsuariosShort");
}
create(data: IUsuario) {
return http.post<[IRegister[]]>("/Usuarios/createUsuario", data);
}
clonarUsuario(data: DTOClonarUsuario) {
return http.post<[DTOClonarUsuario[]]>("/Usuarios/clonarUsuario", data);
}
disableUser(id: number) {
return http.put<boolean>(`/Usuarios/disableUser?id=${id}`);
}
/* get(id: string) {
return http.get<ITutorialData>(`/tutorials/${id}`);
}
create(data: ILogin) {
return http.post<[ItemMenuData[]]>("/Auth", data);
}
update(data: ITutorialData, id: any) {
return http.put<any>(`/tutorials/${id}`, data);
}
delete(id: any) {
return http.delete<any>(`/tutorials/${id}`);
}
deleteAll() {
return http.delete<any>(`/tutorials`);
}
findByTitle(title: string) {
return http.get<Array<ITutorialData>>(`/tutorials?title=${title}`);
}*/
}
export default new usuariosService();

@ -0,0 +1,52 @@
import DtoPrecuentaCheques from '../../Componest/Catalogos/CatRelacionBookPrecta/DTO/DTOPrecuentaCheques'
import { DTORelPreChe } from '../../DTO/DTORelPreChe'
import { DTOWorkingHours } from '../../DTO/DTOWorkingHours'
import { DTOTotalHours } from '../../DTO/Reportes/DTOTotalHours'
import http from '../common/http-common'
class reportsDataService {
getRptRelacionPreChe(Precuenta : string, Cheques: string )
{
return http.get<Array<DTORelPreChe>>(
`/Catalogos/CatRelacionesBookPrecta/GetAllPreChe`
)
}
getRptRelacionesTrafico()
{
return http.get<Array<DTORelPreChe>>(
`/Reportes/GetAllSoloTrafico`
)
}
getRptNoRelaciones()
{
return http.get<Array<DtoPrecuentaCheques>>(
`/Reportes/GetAllNoRelaciones`
)
}
getRptWorkingHours(Inicio : string , Fin: string )
{
return http.get<Array<DTOWorkingHours>> (
`/Reportes/GetAllWorkingHours?Inicio=${Inicio}&Fin=${Fin} `
)
}
getRptTotalHours(Inicio : string , Fin : string)
{
return http.get<Array<DTOTotalHours>> (
`/Reportes/TotalHours?Inicio=${Inicio}&Fin=${Fin}`)
}
}
export default new reportsDataService()

@ -0,0 +1,61 @@
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) {
const Excluded = ['login', 'Reset', 'forgotPassword', 'PIN']
const currentUrl = window.location.href
var urlExceptuado = new RegExp(Excluded.join('|')).test(currentUrl)
if (401 === error.response.status && !urlExceptuado) {
localStorage.setItem('menu', '')
localStorage.setItem('token', '')
window.location.href = '/#/login'
} else {
return Promise.reject(error)
}
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)
}
) */
instance.interceptors.request.use(
(config) => {
let token = window.localStorage.getItem('token')
if (token) {
config.headers!!.Authorization = `Bearer ${token}`
} else {
config.headers!!.Authorization = ``
}
return config
},
(error) => {
return Promise.reject(error)
}
)
export default instance

@ -0,0 +1,12 @@
import { createSlice } from '@reduxjs/toolkit';
const rptRelacionBookPrectaSlice = createSlice({
name: 'rptRelacionBookPrecta',
initialState: {},
reducers: {
// define tus reducers aquí
}
});
export const { /* exporta tus acciones aquí */ } = rptRelacionBookPrectaSlice.actions;
export default rptRelacionBookPrectaSlice.reducer;

@ -0,0 +1,46 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import ICatNotificaciones from '../../../../Componest/Cliente/interfaces/ICatNotificaciones'
const CatNotificaciones: ICatNotificaciones[] = []
const initialState = { CatNotificaciones }
export const CatNotificacionesSlice = createSlice({
name: 'CatNotificaciones',
initialState: initialState,
reducers: {
populateCatNotificaciones: (state, action: PayloadAction<ICatNotificaciones[]>) => {
action.payload.forEach((newItem) => {
var Existe = state.CatNotificaciones.find(function (onMemoryItem) {
return onMemoryItem.id === newItem.id
})
if (!Existe) state.CatNotificaciones.push(newItem)
})
},
addCatNotificaciones: (state, action: PayloadAction<ICatNotificaciones>) => {
var Existe = state.CatNotificaciones.find(function (item) {
return item.id === action.payload.id
})
if (!Existe) state.CatNotificaciones.push(action.payload)
},
updateCatNotificaciones: (state, action: PayloadAction<ICatNotificaciones>) => {
const i = state.CatNotificaciones.findIndex(
(_element) => _element.id === action.payload.id
)
if (i > -1) state.CatNotificaciones[i] = action.payload
else state.CatNotificaciones.push(action.payload)
},
deleteCatNotificaciones: (state, action: PayloadAction<number>) => {
const newArr = state.CatNotificaciones.filter(
(data) => data.id != action.payload
)
state.CatNotificaciones = newArr
},
},
})
export const {
addCatNotificaciones,
populateCatNotificaciones,
updateCatNotificaciones,
deleteCatNotificaciones,
} = CatNotificacionesSlice.actions
export default CatNotificacionesSlice.reducer

@ -0,0 +1,6 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from '../store'
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

@ -0,0 +1,24 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { RootState } from '../../store'
const initialState = {
value: false,
Profile: '',
}
export const userStatusSlice = createSlice({
name: 'userStatus',
initialState,
reducers: {
logued: (state, action: PayloadAction<boolean>) => {
state.value = action.payload;
},
setProfile: (state, action: PayloadAction<string>) => {
state.Profile = action.payload;
},
},
})
export const { logued, setProfile } = userStatusSlice.actions;
export const selectuserStatus = (state: RootState) => state.userStatus.value
export default userStatusSlice.reducer;

@ -0,0 +1,130 @@
import { configureStore } from '@reduxjs/toolkit';
import userStatusReducer from './features/userStatusSlice/userStatusSlice'
// import Cat1868DestinosSlice from './features/Clientes/1868/Cat1868DestinosSlice'
// import Cat1868ResponsablesSlice from './features/Clientes/1868/Cat1868ResponsablesSlice'
// import Cat1868ClaveSATSlice from './features/Clientes/1868/Cat1868ClaveSATSlice'
// import Data1868FacturaDetalleSlice from './features/Clientes/1868/Data1868FacturaDetalleSlice'
// import CatTransfersSlice from './features/Clientes/1868/CatTransfersSlice'
import CatRelacionBookPrectaSlice from './features/CatRelacionBookPrectaSlice'
import CatNotificacionesSlice from './features/Clientes/1868/CatNotificaciones';
const store = configureStore({
reducer: {
userStatus: userStatusReducer,
// Cat1868Destinos: Cat1868DestinosSlice,
// Cat1868Responsables: Cat1868ResponsablesSlice,
// Cat1868ClaveSAT: Cat1868ClaveSATSlice,
// Data1868FacturaDetalle: Data1868FacturaDetalleSlice,
// CatTransfers: CatTransfersSlice,
CatRelacionBookPrectaSlice: CatRelacionBookPrectaSlice,
CatNotificaciones: CatNotificacionesSlice
}
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export default store
// -- codigp de componente de lso archivos
// // src/components/ExcelUploader.tsx
// import React, { useState } from 'react';
// import { useDropzone } from 'react-dropzone';
// import * as XLSX from 'xlsx';
// const ExcelUploader: React.FC = () => {
// const [bookFile, setBookFile] = useState<File | null>(null);
// const [prectaFile, setPrectaFile] = useState<File | null>(null);
// const [bookData, setBookData] = useState<any[]>([]);
// const [prectaData, setPrectaData] = useState<any[]>([]);
// const onDropBook = (acceptedFiles: File[]) => {
// setBookFile(acceptedFiles[0]);
// readExcelFile(acceptedFiles[0], setBookData);
// };
// const onDropPrecta = (acceptedFiles: File[]) => {
// setPrectaFile(acceptedFiles[0]);
// readExcelFile(acceptedFiles[0], setPrectaData);
// };
// const readExcelFile = (file: File, setData: React.Dispatch<React.SetStateAction<any[]>>) => {
// const reader = new FileReader();
// reader.onload = (e) => {
// const binaryStr = e.target?.result;
// if (binaryStr) {
// const workbook = XLSX.read(binaryStr, { type: 'binary' });
// const sheetName = workbook.SheetNames[0];
// const sheet = workbook.Sheets[sheetName];
// const data = XLSX.utils.sheet_to_json(sheet);
// setData(data);
// }
// };
// reader.readAsBinaryString(file);
// };
// return (
// <div>
// <h2>Cargar archivos Excel</h2>
// <div style={{ display: 'flex', justifyContent: 'space-between' }}>
// <div>
// <h3>Book</h3>
// <Dropzone onDrop={onDropBook} />
// {bookFile && <p>Archivo cargado: {bookFile.name}</p>}
// </div>
// <div>
// <h3>Precta</h3>
// <Dropzone onDrop={onDropPrecta} />
// {prectaFile && <p>Archivo cargado: {prectaFile.name}</p>}
// </div>
// </div>
// <div>
// <h3>Datos de Book</h3>
// <pre>{JSON.stringify(bookData, null, 2)}</pre>
// </div>
// <div>
// <h3>Datos de Precta</h3>
// <pre>{JSON.stringify(prectaData, null, 2)}</pre>
// </div>
// </div>
// );
// };
// interface DropzoneProps {
// onDrop: (acceptedFiles: File[]) => void;
// }
// const Dropzone: React.FC<DropzoneProps> = ({ onDrop }) => {
// const { getRootProps, getInputProps } = useDropzone({ onDrop });
// return (
// <div {...getRootProps()} style={dropzoneStyle}>
// <input {...getInputProps()} />
// <p>Arrastra un archivo aquí, o haz clic para seleccionar un archivo</p>
// </div>
// );
// };
// const dropzoneStyle: React.CSSProperties = {
// border: '2px dashed #007bff',
// borderRadius: '5px',
// padding: '20px',
// textAlign: 'center',
// cursor: 'pointer',
// width: '200px',
// height: '100px'
// };
// export default ExcelUploader;

@ -0,0 +1,35 @@
import http from '../../Services/common/http-common'
class uploadExel{
uploadBook(formDataBook: FormData) {
return http.post('/Excel/uploadBook', formDataBook, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
uploadPrecta(formDataBook: FormData) {
return http.post('/Excel/uploadPrecta', formDataBook, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
uploadWorkingHours(formDataBook: FormData)
{
return http.post('/Excel/UploadWorkingHours', formDataBook, {
headers: {
'Content-Type' : 'multipart/form-data'
}
} )
}
}
export default new uploadExel()

@ -0,0 +1,51 @@
import React, { FC } from 'react'
import { Toast, ToastContainer } from 'react-bootstrap'
import { IconContext } from 'react-icons'
import { BsFillExclamationSquareFill, BsXOctagonFill } from 'react-icons/bs'
interface IProps {
show: boolean
msg: string
header: string
msgColor: string
time?: number
closeToast: (arg: boolean) => void
}
export const MsgInformativo: FC<IProps> = (props) => {
return (
<div>
<ToastContainer position={'middle-center'}>
<Toast
show={props.show}
delay={props.time}
bg={props.msgColor}
autohide
onClose={() => {
props.closeToast(false)
}}
>
<Toast.Header>
<strong className='me-auto'>
{props.header.toString().includes('Error') ? (
<IconContext.Provider value={{ color: 'red', size: '20px' }}>
<BsXOctagonFill />
</IconContext.Provider>
) : null}
{props.header.toString().includes('Informativo') ? (
<IconContext.Provider value={{ color: 'blue', size: '20px' }}>
<BsFillExclamationSquareFill />
</IconContext.Provider>
) : null}
&nbsp;
<span style={{ color: props.header == 'Error' ? 'red' : '' }}>{props.header}</span>
</strong>
</Toast.Header>
<Toast.Body style={{ backgroundColor: '#FFFFFF' }}>
<div className={props.msgColor == 'warning' ? 'alert alert-warning' : ''}>{props.msg}</div>
</Toast.Body>
</Toast>
</ToastContainer>
</div>
)
}

@ -0,0 +1,292 @@
@media print {
.areaImprimible {
visibility: hidden
}
}
.labelSize13px {
font-size: 13px;
padding: 5px 5px 5px 5px;
}
.modal-50w {
width: 50%;
max-width: none !important;
}
.modal-70w {
width: 70%;
max-width: none !important;
}
.modal-90w {
width: 90%;
/* max-height: 90% !important; */
max-height: 'calc(100vh - 50px)' !important;
}
.modal-innerDiv {
/* height: 95%; */
max-height: 'calc(100vh - 50px)' !important;
}
.react-bootstrap-table {
height: 250px !important;
overflow-y: scroll;
}
.dropzone {
background-color: #D2F9FC;
border: 1px dashed hsl(234, 96%, 33%);
padding: 8% 5% 10% 10%;
border-radius: 10px;
width: 450px;
height: 100px;
}
.dropzoneFileManager {
background-color: #D2F9FC;
border: 1px dashed hsl(234, 96%, 33%);
/* padding: 3% 5% 5% 10%;
*/ border-radius: 10px;
width: 750px;
/* height: 150px; */
padding-top: 1em;
text-align: center;
}
.moneyField { background-color: #F5FFED; }
th,
td {
text-align: left;
}
tr:nth-child(odd) { background-color: #f5f5f5; }
.hideDiv {
visibility: 'hidden';
height: '0px';
width: '0px';
}
.hideRow {
height: 0px;
visibility: hidden;
}
.showRow {
padding-top: 5px;
}
.showDiv {
height: '100px';
overflow: auto;
}
.userModal {
width: 50vw;
height: 50vw;
max-width: 50vw;
max-height: 50vw;
overflow: scroll;
}
.userModal2 {
width: 1000px;
height: 1000px;
overflow: scroll;
}
.readyColor { background-color: #D4D6D2; }
.pendingColor { background-color: #FFFFFF; }
.hideEverything {
visibility: 'hidden';
display: 'none';
background-color: #000000;
}
.showEverything {
visibility: 'visible'
}
.customPadding {
padding-bottom: '5px';
padding-top: '15px';
}
.heightZero {
height: 0px;
}
.myFlexyTable {
width: 2000px;
overflow: scroll;
}
.myFlexyTable tr {
height: 10px;
}
.formatNumber {
font-size: 20;
}
input.numbersOnly {
font-size: '15px';
background-color: '#F5FFED';
border: '1px solid #f00';
}
.parent {
position: relative;
margin-top: 0px;
z-index: 1;
}
.child {
position: absolute;
margin-top: 30px;
width: 400px;
height: 150px;
background: rgb(245, 248, 248);
border-radius: 5px 5px 5px 5px;
padding: 2px;
border-style: outset;
overflow: auto;
}
.cleanLi {
list-style-type: none;
padding-left: 10px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 12px;
cursor: pointer;
}
.sorroundImage {
border: 1px solid #CED4DA;
}
.genericSelect {
padding-left: 3px;
font-size: 13px;
font-style: italic;
font-family: cursive;
}
.bg-RECHAZOS_PARA_CORRESPONSAL {
background-color: #EB984E !important;
}
.bg-CORRESPONSAL_NORMAL {
background-color: #ABEB4E !important;
}
.bg-RECHAZOS_POR_CONTABILIDAD {
background-color: #ff0000 !important;
}
.btn-uploadExcel {
color: #e9f0e6;
background-color: rgb(16, 101, 101);
border-color: #5bc2c2
}
.btn-uploadExcelCorresponsal {
color: #a3e488;
background-color: rgb(29, 151, 72);
border-color: #5bc2c2
}
.btn-uploadPDF {
color: #dedfc5;
background-color: rgb(199, 66, 66);
border-color: #f40707
}
.rdtPicker {
display: none;
position: absolute;
width: 250px;
padding: 4px;
margin-top: 1px;
z-index: 99999 !important;
background: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border: 1px solid #f9f9f9;
}
.react-datepicker-wrapper,
.react-datepicker__input-container,
.react-datepicker__input-container input {
display: block;
width: 100%;
}
.genericinput {
width: 125px;
}
.divPerfiles {
height: 550px;
overflow: auto;
background-color: #000000;
}
.tableAvisoCruce {
font-family: Verdana;
font-size: 14px;
border: 1px solid #000000;
background-color: #ffffff;
width: 1000px;
}
.tableAvisoCruce,
td,
th {
border: 1px solid black;
height: 25px;
}
.tableAvisoCruceHeader {
background-color: #756d6d;
font-weight: bold;
text-align: center;
}
.tableAvisoCrucefNormal {
font-weight: normal;
}
.tableAvisoCruceHyF {
text-align: center;
border: 1px solid white;
}
.allScreen {
background-color: #FFFFFF;
height: 1330px;
}
.tdAvisoCruceWordWrap {
word-break: break-all;
}
.textareaCR {
white-space: pre-wrap;
word-wrap: break-word;
}
.colAlignRight {
text-align: right;
}
.blueCardBorder {
border-color: #1D6DC2;
}
.dashboardComponentFont {
font-family: 'Kanit';
}
.text-info {
color: #000000 !important;
}

@ -0,0 +1,53 @@
@media all and (min-width: 480px) {
.Login {
padding: 60px 0;
}
.Login form {
margin: 0 auto;
max-width: 320px;
}
#login .container #login-row #login-column #login-box {
margin-top: 120px;
max-width: 320px;
/* height: 560px; */
border: 1px solid #9c9c9c;
background-color: #eaeaea;
}
#login .container #login-row #login-column #login-box #login-form {
padding: 20px;
}
#login
.container
#login-row
#login-column
#login-box
#login-form
#register-link {
margin-top: -85px;
}
.table-wrapper {
max-height: 400px;
overflow: auto;
display: inline-block;
}
.table-earnings {
background: #f3f5f6;
}
.control-label {
text-align: left !important; /* !important added for priority in SO snippet. */
}
.right-label {
text-align: right !important; /* !important added for priority in SO snippet. */
}
.navbarlinks {
background-color: #f3f5f6;
}
#basic-nav-dropdown {
color:#fff;
}
.Color1 {
border-color: #870053;
}
}

@ -0,0 +1,68 @@
.tree li {
margin: 0px 0;
list-style-type: none;
position: relative;
padding: 20px 5px 0px 5px;
}
.tree li::before {
content: "";
position: absolute;
top: 0;
width: 1px;
height: 100%;
right: auto;
left: -20px;
border-left: 1px solid #ccc;
bottom: 50px;
}
.tree li::after {
content: "";
position: absolute;
top: 30px;
width: 25px;
height: 20px;
right: auto;
left: -20px;
border-top: 1px solid #ccc;
}
.tree li a {
display: inline-block;
border: 1px solid #ccc;
padding: 5px 10px;
text-decoration: none;
color: #666;
font-family: arial, verdana, tahoma;
font-size: 11px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
}
/*Remove connectors before root*/
.tree > ul > li::before,
.tree > ul > li::after {
border: 0;
}
/*Remove connectors after last child*/
.tree li:last-child::before {
height: 30px;
}
/*Time for some hover effects*/
/*We will apply the hover effect the the lineage of the element also*/
.tree li a:hover,
.tree li a:hover + ul li a {
background: #c8e4f8;
color: #000;
border: 1px solid #94a0b4;
}
/*Connector styles on hover*/
.tree li a:hover + ul li::after,
.tree li a:hover + ul li::before,
.tree li a:hover + ul::before,
.tree li a:hover + ul ul::before {
border-color: #94a0b4;
}

@ -0,0 +1,12 @@
/* .react-captcha {
background-color: #000000;
}
*/
/* .react-captcha-icon-wrapper {
}
*/
.react-captcha-canvas{
background-color: rgb(232, 235, 235);
color: #fff;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 KiB

@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

@ -0,0 +1,59 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import 'bootstrap/dist/css/bootstrap.min.css'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'
import { HashRouter, Route, Routes } from 'react-router-dom'
import { Provider } from 'react-redux'
import store from './Store/store'
import Dashboard from './Componest/Dashboard/Dashboard'
import Login from './Componest/Loging/Login'
import Logout from './Componest/Logout/logout'
import ResetCredentials from './Componest/Loging/ResetCredentials'
import Register from './Componest/Register/register'
import UserControl from './Componest/UserControl/UserControl'
import ForgotPassword from './Componest/Loging/ForgotPassword'
import PIN from './Componest/Loging/PIN'
import CatNotificaciones from './Componest/Catalogos/CatNotificaciones'
import CatRelacionBookPrecta from './Componest/Catalogos/CatRelacionBookPrecta/CatRelacionBookPrecta'
import FileUploadExel from './Componest/Catalogos/FileUploadExel'
import FileUploadExelWorkingHours from './Componest/Catalogos/CatWorkingHours/FileUploadExelWorkingHours'
import RptTotalHours from './Componest/Reportes/RptTotalHours/RptTotalHours'
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
function PageNotFound() {
return (
<div style={{ textAlign: 'center', paddingTop: '300px' }}>
<h2>Sorry, no matching page</h2>
</div>
)
}
root.render(
<Provider store={store}>
<React.StrictMode>
<HashRouter>
<Routes>
<Route path='/' element={<App />}>
<Route path='/' element={<Dashboard />} />
<Route path='/login' element={<Login />} />
<Route path='/forgotPassword' element={<ForgotPassword />} />
<Route path='/PIN' element={<PIN />} />
<Route path='/logout' element={<Logout />} />
<Route path ='/Reset' element={<ResetCredentials />} />
<Route path='/Register' element={<Register />} />
<Route path='/CatNotificaciones' element={<CatNotificaciones/>} />
<Route path='/RptTotalHours' element = {<RptTotalHours/>} />
<Route path='FileUploadExel' element= {<FileUploadExel/>} />
<Route path='/UserControl' element={<UserControl />} />
<Route path='/CatRelacionBookPrecta' element ={<CatRelacionBookPrecta />} />
<Route path='*' element={<PageNotFound />} />
<Route path='FileUploadExelWorkingHours' element = {<FileUploadExelWorkingHours/>} />
</Route>
</Routes>
</HashRouter>
</React.StrictMode>
</Provider>
)
reportWebVitals()

@ -0,0 +1,7 @@
export default interface ItemMenuData {
id: number;
padreId: number;
posicion: number;
descripcion: string;
url: string;
}

@ -0,0 +1,4 @@
export interface IPerfil {
id: number;
perfil: string;
}

@ -0,0 +1,5 @@
export default interface ICatNotificaciones {
id: number,
mensaje: string,
activo: boolean
}

@ -0,0 +1,12 @@
export default interface IPerfilesMenu {
id: number;
idPerfil: number;
itemMenu: number;
perfil: string;
descripcion: string;
padreId: number;
posicion: number;
url: string;
habilitado: number;
agrupado: number;
}

@ -0,0 +1,32 @@
export interface IRegister {
id: number;
usuario: string;
nombre: string;
contrasena: string;
correo: string;
tipoUsuario: number;
activo: number;
fechaAlta: string;
usuarioAlta: number;
fechaModifico: string;
usuarioModifico: number;
fechaElimino: string;
usuarioElimino: number;
motivoElimino: string;
idModulo: number;
dept: number;
tmercancia: number;
fechaUltimaVisita: string;
visitas: number;
internos: number;
permisoEspecial: number;
estadoConfiguracion: number;
fechaValidacionConf: string;
realizoEncuesta: string;
encuestaActiva: number;
fechaLimiteEncuesta: string;
codigoAccesoM: string;
tokenAccesoM: string;
deviceToken: string;
idPerfil: number;
}

@ -0,0 +1,3 @@
export default interface IRespuesta {
respuesta: string
}

@ -0,0 +1,6 @@
export interface IUsuario {
id: number,
usuario: string,
nombre: string,
correo: string
}

@ -0,0 +1,10 @@
export default interface IjwtStructure {
sub: string;
jti: string;
iat: string;
UserId: number;
Usuario: string;
Departamento: string;
UserType: number,
Perfil: string
}

@ -0,0 +1,4 @@
export default interface ILogin {
Usuario: string;
Contrasena: string;
}

@ -0,0 +1,12 @@
import { SpawnSyncOptionsWithBufferEncoding } from "child_process";
export default interface ITokenInfo {
UserId: string;
Usuario: string;
aud: string;
exp: number;
iat: string;
iss: string;
jti: string;
sub: string;
}

@ -0,0 +1,51 @@
import React, { FC } from 'react'
import { Toast, ToastContainer } from 'react-bootstrap'
import { IconContext } from 'react-icons'
import { BsFillExclamationSquareFill, BsXOctagonFill } from 'react-icons/bs'
interface IProps {
show: boolean
msg: string
header: string
msgColor: string
time?: number
closeToast: (arg: boolean) => void
}
export const MsgInformativo: FC<IProps> = (props) => {
return (
<div>
<ToastContainer position={'middle-center'} style={{zIndex:'99999 !important'}} >
<Toast
show={props.show}
delay={props.time}
bg={props.msgColor}
autohide
onClose={() => {
props.closeToast(false)
}}
>
<Toast.Header>
<strong className='me-auto'>
{props.header.toString().includes('Error') ? (
<IconContext.Provider value={{ color: 'red', size: '20px' }}>
<BsXOctagonFill />
</IconContext.Provider>
) : null}
{props.header.toString().includes('Informativo') ? (
<IconContext.Provider value={{ color: 'blue', size: '20px' }}>
<BsFillExclamationSquareFill />
</IconContext.Provider>
) : null}
&nbsp;
<span style={{ color: props.header == 'Error' ? 'red' : '' }}>{props.header}</span>
</strong>
</Toast.Header>
<Toast.Body style={{ backgroundColor: '#FFFFFF' }}>
<div className={props.msgColor == 'warning' ? 'alert alert-warning' : ''}>{props.msg}</div>
</Toast.Body>
</Toast>
</ToastContainer>
</div>
)
}

@ -0,0 +1,3 @@
export default interface token {
token: string;
}

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -0,0 +1 @@
/// <reference types="react-scripts" />

@ -0,0 +1,15 @@
import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

@ -0,0 +1,5 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}

10446
yarn.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save