feat: ✨ Login implementation
This commit is contained in:
parent
db28a17bf8
commit
36757bd163
30
.vscode/settings.json
vendored
30
.vscode/settings.json
vendored
@ -7,7 +7,31 @@
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.addMissingImports": true,
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
"source.addMissingImports": "explicit",
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.activeBackground": "#0894ba",
|
||||
"activityBar.background": "#0894ba",
|
||||
"activityBar.foreground": "#e7e7e7",
|
||||
"activityBar.inactiveForeground": "#e7e7e799",
|
||||
"activityBarBadge.background": "#99077a",
|
||||
"activityBarBadge.foreground": "#e7e7e7",
|
||||
"commandCenter.border": "#e7e7e799",
|
||||
"sash.hoverBorder": "#0894ba",
|
||||
"statusBar.background": "#066d89",
|
||||
"statusBar.foreground": "#e7e7e7",
|
||||
"statusBarItem.hoverBackground": "#0894ba",
|
||||
"statusBarItem.remoteBackground": "#066d89",
|
||||
"statusBarItem.remoteForeground": "#e7e7e7",
|
||||
"titleBar.activeBackground": "#066d89",
|
||||
"titleBar.activeForeground": "#e7e7e7",
|
||||
"titleBar.inactiveBackground": "#066d8999",
|
||||
"titleBar.inactiveForeground": "#e7e7e799"
|
||||
},
|
||||
"peacock.color": "#066d89",
|
||||
"cSpell.words": [
|
||||
"orbis",
|
||||
"Orbis"
|
||||
]
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"constants": {
|
||||
"plataforma": "web",
|
||||
"publicPath": "/smartoperation",
|
||||
"publicPath": "/orbistemplate",
|
||||
"urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
||||
"urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
||||
"urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
||||
"appTitle": "SmartOperation",
|
||||
"idApp": "smartoperation",
|
||||
"appTitle": "OrbisTemplate",
|
||||
"idApp": "orbistemplate",
|
||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||
"maxMbUpload": 4,
|
||||
"defaultLocale": "es"
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"constants": {
|
||||
"plataforma": "web",
|
||||
"publicPath": "/smartoperation",
|
||||
"publicPath": "/orbistemplate",
|
||||
"urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||
"urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||
"urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||
"appTitle": "SmartOperation",
|
||||
"idApp": "smartoperation",
|
||||
"appTitle": "OrbisTemplate",
|
||||
"idApp": "orbistemplate",
|
||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||
"maxMbUpload": 4,
|
||||
"defaultLocale": "es"
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"constants": {
|
||||
"plataforma": "web",
|
||||
"publicPath": "/smartoperation",
|
||||
"publicPath": "/orbistemplate",
|
||||
"urlServerImages" : "https://localhost:3000/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||
"urlWebApi": "https://localhost:3000/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||
"urlUploadApi": "https://localhost:3000/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||
"appTitle": "SmartOperation",
|
||||
"idApp": "smartoperation",
|
||||
"appTitle": "OrbisTemplate",
|
||||
"idApp": "orbistemplate",
|
||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||
"maxMbUpload": 4,
|
||||
"defaultLocale": "es"
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"constants": {
|
||||
"plataforma": "web",
|
||||
"publicPath": "/smartoperation",
|
||||
"publicPath": "/orbistemplate",
|
||||
"urlServerImages" : "https://www.via-asesores.com/smartoperation/orbisapi/dtsrv/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
||||
"urlWebApi": "https://www.via-asesores.com/smartoperation/orbisapi/api/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
||||
"urlUploadApi": "https://www.via-asesores.com/smartoperation/orbisapi/upload/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
||||
"appTitle": "SmartOperation",
|
||||
"idApp": "smartoperation",
|
||||
"appTitle": "OrbisTemplate",
|
||||
"idApp": "orbistemplate",
|
||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||
"maxMbUpload": 4,
|
||||
"defaultLocale": "es"
|
||||
|
@ -12,17 +12,6 @@ const rewrites = async () => {
|
||||
]
|
||||
}
|
||||
|
||||
const redirects = async () => {
|
||||
return [
|
||||
{
|
||||
source: '/mantenimientos',
|
||||
destination: constants.publicPath,
|
||||
basePath: true,
|
||||
permanent: false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const nextConfig = {
|
||||
env: {
|
||||
...constants
|
||||
|
14
package.json
14
package.json
@ -25,9 +25,21 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.17",
|
||||
"config": "^3.3.9",
|
||||
"js-cookie": "^3.0.5",
|
||||
"js-md5": "^0.8.3",
|
||||
"next": "14.0.4",
|
||||
"node-forge": "^1.3.1",
|
||||
"pristinejs": "^1.1.0",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
"react-dom": "^18",
|
||||
"react-dropzone-component": "^3.2.0",
|
||||
"react-icons": "^4.12.0",
|
||||
"react-simple-hook-store": "^0.0.6",
|
||||
"react-toastify": "^9.1.3",
|
||||
"rosetta": "^1.1.0",
|
||||
"vComponents": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/v-components.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
|
141
src/components/Login/FormLogin.jsx
Normal file
141
src/components/Login/FormLogin.jsx
Normal file
@ -0,0 +1,141 @@
|
||||
import Pristine from 'pristinejs'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { UserIcon, EyeIcon, EyeSlashIcon, KeyIcon } from '@heroicons/react/24/solid'
|
||||
import functions from 'v-functions'
|
||||
import useI18n from '@/hooks/useI18n'
|
||||
import presets from '@/utils/globalPresets'
|
||||
import useHasMounted from '@/hooks/useHasMounted'
|
||||
|
||||
let validateLogin = null
|
||||
|
||||
const FormLogin = ({ onLogin }) => {
|
||||
const i18n = useI18n()
|
||||
const hasMounted = useHasMounted()
|
||||
const [viewPassword, setViewPassword] = useState(false)
|
||||
const [isInputValid, setIsInputValid] = useState(false)
|
||||
|
||||
const validate = (event) => {
|
||||
if (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
if (validateLogin && validateLogin !== null) {
|
||||
const resulValidate = validateLogin.validate()
|
||||
setIsInputValid(resulValidate)
|
||||
}
|
||||
}
|
||||
|
||||
const doLogin = (event) => {
|
||||
if (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
if (isInputValid === true) {
|
||||
const emailLogin = document.getElementById('usuario')
|
||||
const passwordLogin = document.getElementById('clave')
|
||||
const datos = {
|
||||
email: functions.toUpperCaseAndTrim(emailLogin.value),
|
||||
password: functions.trim(passwordLogin.value)
|
||||
}
|
||||
setIsInputValid(false) // para prevenir doble click
|
||||
onLogin(datos)
|
||||
}
|
||||
}
|
||||
|
||||
// when page is mounted
|
||||
useEffect(() => {
|
||||
if (hasMounted) {
|
||||
const helem = document.getElementById('frmLogin')
|
||||
validateLogin = new Pristine(helem, presets.pristine, false)
|
||||
const helemUsuario = document.getElementById('usuario')
|
||||
helemUsuario.focus()
|
||||
}
|
||||
}, [hasMounted])
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
validate(event)
|
||||
if (isInputValid === true) {
|
||||
doLogin(event)
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyDown)
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<form id="frmLogin" name="frmLogin" method="post" onSubmit={(event) => doLogin(event)} noValidate >
|
||||
<div className="flex w-full flex-col space-y-4 px-4 ">
|
||||
<div className="form-group flex flex-col">
|
||||
<div className="via-label">
|
||||
{ i18n.t('login.user') }
|
||||
<div className="inline-flex font-semibold text-red-500">(*)</div>
|
||||
</div>
|
||||
<div className="relative w-full">
|
||||
<input
|
||||
id="usuario"
|
||||
name="usuario"
|
||||
required
|
||||
placeholder=" "
|
||||
type="email"
|
||||
data-pristine-required-message={i18n.t('login.validacion_correo')}
|
||||
className={'via-input'}
|
||||
onChange={(e) => { validate(e) }}
|
||||
/>
|
||||
<button
|
||||
className={'via-append-input'}
|
||||
onClick={(e) => { e.stopPropagation() }}
|
||||
disabled
|
||||
>
|
||||
<UserIcon className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group flex flex-col">
|
||||
<div className={'via-label'}>
|
||||
{ i18n.t('login.password') }
|
||||
<div className="inline-flex font-semibold text-red-500">(*)</div>
|
||||
</div>
|
||||
<div className="relative w-full">
|
||||
<input
|
||||
id="clave"
|
||||
name="clave"
|
||||
required
|
||||
placeholder=" "
|
||||
type={viewPassword === false ? 'password' : 'text'}
|
||||
data-pristine-required-message={i18n.t('login.validacion_password')}
|
||||
className={'via-input'}
|
||||
onChange={(e) => { validate(e) }}
|
||||
/>
|
||||
<button
|
||||
className={'via-append-input'}
|
||||
onClick={(e) => { e.stopPropagation(); e.preventDefault(); setViewPassword(!viewPassword) }}
|
||||
>
|
||||
{ viewPassword === false && <EyeIcon className="h-5 w-5" /> }
|
||||
{ viewPassword === true && <EyeSlashIcon className="h-5 w-5" /> }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={'via-div-actions'}>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!isInputValid}
|
||||
className={`${'via-button'} ${(isInputValid ? 'bg-cyan-900' : 'bg-red-400')} mx-0 w-full justify-center`}
|
||||
>
|
||||
<KeyIcon className="h-5 w-5 pr-2" />
|
||||
{ i18n.t('login.connect') }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default FormLogin
|
163
src/components/SessionTimeout/index.jsx
Normal file
163
src/components/SessionTimeout/index.jsx
Normal file
@ -0,0 +1,163 @@
|
||||
import React, { Fragment, useEffect, useRef, useState } from 'react'
|
||||
import { Dialog, Transition } from '@headlessui/react'
|
||||
import PropTypes from 'prop-types'
|
||||
import useHasMounted from '@/hooks/useHasMounted'
|
||||
|
||||
export default function SessionTimeout ({ i18n, user, onTimeout, onCancelTimeout }) {
|
||||
const TIME = 30
|
||||
const hasMounted = useHasMounted()
|
||||
const countTimerRef = useRef()
|
||||
const [tick, setTick] = useState(0)
|
||||
const [countTimer, setCountTimer] = useState() // contador que lleva el control de tiempo en segundos para mostrar antes de cerrar sesion
|
||||
const [timerIsOn, setTimerIsOn] = useState(false) // verifica si el dialogo debe ser mostrado
|
||||
const idleTimer = useRef(null) // variable de control para el proceso de conteo
|
||||
|
||||
// realiza el conteo regresivo
|
||||
const timedCount = () => {
|
||||
if (countTimerRef.current <= 0) {
|
||||
clearInterval(idleTimer.current)
|
||||
setTimerIsOn(false)
|
||||
setCountTimer(TIME)
|
||||
onTimeout()
|
||||
return
|
||||
}
|
||||
setCountTimer(countTimerRef.current - 1)
|
||||
}
|
||||
|
||||
// inicia el conteo regresivo
|
||||
const startIdleMonitor = (expiracion = 0) => {
|
||||
if (expiracion < TIME * 1000) {
|
||||
countTimerRef.current = Math.round(expiracion / 1000) // tiempo restante
|
||||
} else {
|
||||
countTimerRef.current = TIME
|
||||
}
|
||||
setCountTimer(countTimerRef.current)
|
||||
setTimerIsOn(true)
|
||||
timedCount()
|
||||
idleTimer.current = setInterval(timedCount, 1000)
|
||||
}
|
||||
|
||||
const calendarizeIdle = () => {
|
||||
// const fecha_inicio_sesion = new Date(user.fecha_inicio_sesion.slice(0, -1)) // uso de localtime quita Z al final del string
|
||||
const fecha_fin_sesion = new Date(user?.fecha_fin_sesion?.slice(0, -1)) // uso de localtime quita Z al final del string
|
||||
// const fecha_fin_sesion = new Date(user.fecha_fin_sesion)
|
||||
const expiracion = Math.round(fecha_fin_sesion.getTime() - (new Date()).getTime()) // valida cuando se realiza un F5 o reload del navegador (user.tiempo_expiracion * 60 * 1000)
|
||||
if (expiracion <= 0) {
|
||||
return // no debe calendarizar porque la sesion ya vencio
|
||||
}
|
||||
const timeInMillis = expiracion - (TIME * 1000)
|
||||
const processTimer = setTimeout(startIdleMonitor, timeInMillis > 0 ? timeInMillis : 0, expiracion)
|
||||
return () => clearTimeout(processTimer)
|
||||
}
|
||||
|
||||
// cancela el conteo regresivo aumentando el tiempo de expiracion
|
||||
const stopIdleMonitor = async () => {
|
||||
await onCancelTimeout()
|
||||
clearInterval(idleTimer.current)
|
||||
setTimerIsOn(false)
|
||||
setCountTimer(TIME)
|
||||
// force rerender to update view
|
||||
setTick((tick) => tick + 1)
|
||||
// await new Promise(resolve => setTimeout(resolve, 2000)) // espera obligada para actualizacion DB
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (timerIsOn === false && tick > 0) {
|
||||
return calendarizeIdle()
|
||||
}
|
||||
}, [timerIsOn, tick])
|
||||
|
||||
useEffect(() => {
|
||||
countTimerRef.current = countTimer
|
||||
}, [countTimer])
|
||||
|
||||
useEffect(() => {
|
||||
if (!user || user === null) {
|
||||
if (idleTimer && idleTimer.current) {
|
||||
clearInterval(idleTimer.current)
|
||||
}
|
||||
}
|
||||
return () => clearInterval(idleTimer.current)
|
||||
}, [user])
|
||||
|
||||
useEffect(() => {
|
||||
if (hasMounted) {
|
||||
return calendarizeIdle()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [hasMounted])
|
||||
|
||||
return (
|
||||
<>
|
||||
{ timerIsOn && timerIsOn === true &&
|
||||
<Transition appear show as={Fragment}>
|
||||
<Dialog as='div' className='relative' style={{ zIndex: 999 }} onClose={() => { }}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter='ease-out duration-300'
|
||||
enterFrom='opacity-0'
|
||||
enterTo='opacity-100'
|
||||
leave='ease-in duration-200'
|
||||
leaveFrom='opacity-100'
|
||||
leaveTo='opacity-0'
|
||||
>
|
||||
<div className='fixed inset-0 bg-black/25' />
|
||||
</Transition.Child>
|
||||
|
||||
<div className='fixed inset-0 overflow-y-auto'>
|
||||
<div className='flex min-h-full items-center justify-center p-4 text-center'>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter='ease-out duration-300'
|
||||
enterFrom='opacity-0 scale-95'
|
||||
enterTo='opacity-100 scale-100'
|
||||
leave='ease-in duration-200'
|
||||
leaveFrom='opacity-100 scale-100'
|
||||
leaveTo='opacity-0 scale-95'
|
||||
>
|
||||
<Dialog.Panel className='w-full max-w-md overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all'>
|
||||
<Dialog.Title
|
||||
as='h3'
|
||||
className='text-lg font-medium leading-6 text-gray-900'
|
||||
>
|
||||
{i18n.t('common.sessionToFinish')}
|
||||
</Dialog.Title>
|
||||
<div className='mt-2'>
|
||||
<p className='text-lg font-extrabold text-gray-500'>
|
||||
{countTimer}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className='mt-4 flex w-full flex-row-reverse'>
|
||||
<button
|
||||
type='button'
|
||||
className='mr-2 inline-flex justify-center rounded-md border border-transparent bg-red-100 px-4 py-2 text-sm font-medium text-red-900 hover:bg-red-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2'
|
||||
onClick={() => { stopIdleMonitor() }}
|
||||
>
|
||||
{i18n.t('common.sessionContinue')}
|
||||
</button>
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
SessionTimeout.propTypes = {
|
||||
i18n: PropTypes.object,
|
||||
user: PropTypes.object,
|
||||
onTimeout: PropTypes.func,
|
||||
onCancelTimeout: PropTypes.func
|
||||
}
|
||||
|
||||
SessionTimeout.defaultProps = {
|
||||
i18n: { t: () => { return 'txtNone' } },
|
||||
user: {},
|
||||
onTimeout: () => {},
|
||||
onCancelTimeout: () => {}
|
||||
}
|
115
src/components/widgets/UserOptionsMenu.jsx
Normal file
115
src/components/widgets/UserOptionsMenu.jsx
Normal file
@ -0,0 +1,115 @@
|
||||
import React from 'react'
|
||||
import { Menu } from '@headlessui/react'
|
||||
import { MdOutlineCheckBox, MdOutlineCheckBoxOutlineBlank, MdOutlineLightMode, MdDarkMode } from 'react-icons/md'
|
||||
import { TbColorPicker, TbLanguage } from 'react-icons/tb'
|
||||
|
||||
const UserOptionsMenu = ({ setPreferences, theme, i18n }) => {
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center justify-center text-gray-900">
|
||||
<TbColorPicker className="mr-2 h-5 w-5" aria-hidden="true" />
|
||||
Tema
|
||||
</div>
|
||||
<div className="mb-4 grid grid-cols-2 gap-2 p-1">
|
||||
<Menu.Item>
|
||||
<button
|
||||
className={`${
|
||||
theme === 'light'
|
||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||
onClick={async () => {
|
||||
setPreferences('light')
|
||||
}}
|
||||
>
|
||||
<MdOutlineLightMode className="mr-2 h-5 w-5" aria-hidden="true" />
|
||||
Claro
|
||||
</button>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<button
|
||||
className={`${
|
||||
theme === 'dark'
|
||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||
onClick={() => {
|
||||
setPreferences('dark')
|
||||
}}
|
||||
>
|
||||
<MdDarkMode className="mr-2 h-5 w-5" aria-hidden="true" />
|
||||
Oscuro
|
||||
</button>
|
||||
</Menu.Item>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-center text-gray-900">
|
||||
<TbLanguage className="mr-2 h-5 w-5" aria-hidden="true" />
|
||||
Idioma
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-2 p-1">
|
||||
<Menu.Item>
|
||||
<button
|
||||
className={`${
|
||||
i18n.activeLocale === 'es'
|
||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||
onClick={async () => {
|
||||
setPreferences('es')
|
||||
}}
|
||||
>
|
||||
{
|
||||
i18n.activeLocale === 'es'
|
||||
? (
|
||||
<MdOutlineCheckBox
|
||||
className="mr-2 h-5 w-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<MdOutlineCheckBoxOutlineBlank
|
||||
className="mr-2 h-5 w-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)
|
||||
}
|
||||
Español
|
||||
</button>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<button
|
||||
className={`${
|
||||
i18n.activeLocale === 'en'
|
||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||
onClick={() => {
|
||||
setPreferences('en')
|
||||
}}
|
||||
>
|
||||
{
|
||||
i18n.activeLocale === 'en'
|
||||
? (
|
||||
<MdOutlineCheckBox
|
||||
className="mr-2 h-5 w-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<MdOutlineCheckBoxOutlineBlank
|
||||
className='mr-2 h-5 w-5'
|
||||
aria-hidden='true'
|
||||
/>
|
||||
)
|
||||
}
|
||||
Ingles
|
||||
</button>
|
||||
</Menu.Item>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default UserOptionsMenu
|
@ -65,7 +65,7 @@ export const RouteProvider = ({ children }) => {
|
||||
breadcrumbsListArr,
|
||||
addBreadcrumb,
|
||||
truncateBreadcrumbs,
|
||||
breadcrumbsList // Incluir breadcrumbsList en el valor del contexto
|
||||
breadcrumbsList
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -16,7 +16,7 @@ export const { useStore, store } = createStore<IState, IActions>(
|
||||
{
|
||||
title: '',
|
||||
usuarioPermisos: null,
|
||||
valueEasyMDE: null
|
||||
valueEasyMDE: ''
|
||||
},
|
||||
{
|
||||
setTitle: (store, newState) => {
|
||||
|
@ -14,24 +14,24 @@ import { toast } from 'react-toastify'
|
||||
|
||||
export const LayoutContext = createContext()
|
||||
|
||||
const Footer = dynamic(() => { return import('vComponents/dist/Footer') }, { ssr: false })
|
||||
const Sidebar = dynamic(() => { return import('vComponents/dist/Sidebar') }, { ssr: false })
|
||||
const Navbar = dynamic(() => { return import('vComponents/dist/Navbar') }, { ssr: false })
|
||||
const Footer = dynamic(() => { return import('vComponents/Footer') }, { ssr: false })
|
||||
const Sidebar = dynamic(() => { return import('vComponents/Sidebar') }, { ssr: false })
|
||||
const Navbar = dynamic(() => { return import('vComponents/Navbar') }, { ssr: false })
|
||||
|
||||
const ResponsiveContainer = ({ children }) => {
|
||||
const router = useRouter()
|
||||
const loading = useLoading()
|
||||
const hasMounted = useHasMounted()
|
||||
const i18n = useI18n()
|
||||
const [_i18n, setI18n] = useState({ t: () => { return 'txtNone' } })
|
||||
|
||||
const [sidebarOpen, setSidebarOpen] = useState(true)
|
||||
const [menu, setMenu] = useState([])
|
||||
const [title, setTitle] = useStore(s => s.title, a => a.setTitle)
|
||||
const [userObj, setUserObj] = useState()
|
||||
const [token, setToken] = useState('')
|
||||
const [theme, setTheme] = useState(null)
|
||||
const [theme, setTheme] = useState('light')
|
||||
const [constanteObj, setConstanteObj] = useState('')
|
||||
const [appVersion, setAppVersion] = useState('1.0.0')
|
||||
|
||||
const doLogout = async () => {
|
||||
const redirectPath = await environment.logout()
|
||||
@ -84,39 +84,24 @@ const ResponsiveContainer = ({ children }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const onBackKeyDown = () => {
|
||||
if (router.asPath === '/') {
|
||||
// cuando esta en la pagina principal cierra la app
|
||||
if (navigator.app) {
|
||||
navigator.app.exitApp()
|
||||
} else if (navigator.device) {
|
||||
navigator.device.exitApp()
|
||||
} else {
|
||||
window.close()
|
||||
}
|
||||
} else {
|
||||
window.history.back()
|
||||
}
|
||||
}
|
||||
|
||||
const validaPermisosRuta = async (token) => {
|
||||
if (router.pathname.includes('/admin')) {
|
||||
loading.start()
|
||||
const tienePermiso = await environment.validaPermisos(token, 'S', 'N', 'N', 'N')
|
||||
loading.stop()
|
||||
if (tienePermiso === false) {
|
||||
router.push(presets.locations.welcome)
|
||||
}
|
||||
}
|
||||
if (router.pathname.includes('/mantenimientos')) {
|
||||
loading.start()
|
||||
const tienePermiso = await environment.validaPermisos(token, 'N', 'S', 'N', 'N')
|
||||
loading.stop()
|
||||
if (tienePermiso === false) {
|
||||
router.push(presets.locations.welcome)
|
||||
}
|
||||
}
|
||||
}
|
||||
// const validaPermisosRuta = async (token) => {
|
||||
// if (router.pathname.includes('/admin')) {
|
||||
// loading.start()
|
||||
// const tienePermiso = await environment.validaPermisos(token, 'S', 'N', 'N', 'N')
|
||||
// loading.stop()
|
||||
// if (tienePermiso === false) {
|
||||
// router.push(presets.locations.welcome)
|
||||
// }
|
||||
// }
|
||||
// if (router.pathname.includes('/mantenimientos')) {
|
||||
// loading.start()
|
||||
// const tienePermiso = await environment.validaPermisos(token, 'N', 'S', 'N', 'N')
|
||||
// loading.stop()
|
||||
// if (tienePermiso === false) {
|
||||
// router.push(presets.locations.welcome)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
const getMenu = async () => {
|
||||
loading.start()
|
||||
@ -173,10 +158,6 @@ const ResponsiveContainer = ({ children }) => {
|
||||
setTitle
|
||||
}), [userObj, setUserObj, constanteObj, setConstanteObj, token, setToken, setTheme, setTitle])
|
||||
|
||||
useEffect(() => {
|
||||
setI18n(i18n)
|
||||
}, [i18n])
|
||||
|
||||
useEffect(() => {
|
||||
getMenu()
|
||||
}, [token])
|
||||
@ -187,59 +168,70 @@ const ResponsiveContainer = ({ children }) => {
|
||||
getEnv().then(() => {
|
||||
getMenu()
|
||||
})
|
||||
setAppVersion(process.env.NEXT_PUBLIC_VERSION)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [hasMounted])
|
||||
|
||||
useEffect(() => {
|
||||
if (process.browser && window.cordova) {
|
||||
document.addEventListener('backbutton', onBackKeyDown, false)
|
||||
const handleStart = (url) => {
|
||||
// tienePermisosParaRuta(url)
|
||||
loading.start()
|
||||
}
|
||||
})
|
||||
|
||||
const handleComplete = () => {
|
||||
loading.stop()
|
||||
}
|
||||
|
||||
router.events.on('routeChangeStart', handleStart)
|
||||
router.events.on('routeChangeComplete', handleComplete)
|
||||
router.events.on('routeChangeError', handleComplete)
|
||||
|
||||
return () => {
|
||||
router.events.off('routeChangeStart', handleStart)
|
||||
router.events.off('routeChangeComplete', handleComplete)
|
||||
router.events.off('routeChangeError', handleComplete)
|
||||
}
|
||||
}, [router])
|
||||
|
||||
return (
|
||||
<LayoutContext.Provider value={containerWrapper}>
|
||||
|
||||
<div className={`flex h-screen overflow-hidden ${getTheme()}`} >
|
||||
<div className={`flex h-screen overflow-hidden text-theme-text-principal ${getTheme()}`}>
|
||||
{/* Sidebar */}
|
||||
{
|
||||
userObj && userObj.nombre_usuario &&
|
||||
|
||||
{ userObj && userObj.nombre_usuario &&
|
||||
<Sidebar
|
||||
sidebarOpen={sidebarOpen}
|
||||
setSidebarOpen={setSidebarOpen}
|
||||
menu={menu}
|
||||
sidebarStyles={'via-bg-sidebar'}
|
||||
appTitleStyles='via-apptitle-sidebar'
|
||||
userInfoStyles='via-userinfo-sidebar'
|
||||
appTitleStyles='via-app-title-sidebar'
|
||||
userInfoStyles='via-user-info-sidebar'
|
||||
optionStyles={'via-options-sidebar'}
|
||||
iconOptionStyles={'via-icons-sidebar'}
|
||||
suboptionStyles={'via-suboptions-sidebar'}
|
||||
iconSuboptionStyles={'via-icons-subsidebar'}
|
||||
suboptionStyles={'via-sub-options-sidebar'}
|
||||
iconSuboptionStyles={'via-icons-sub-sidebar'}
|
||||
onClickLogout={() => doLogout()}
|
||||
setTitle={setTitle}
|
||||
userObj={userObj}
|
||||
environment={environment}
|
||||
presets={presets}
|
||||
router={router}
|
||||
i18n={_i18n}
|
||||
i18n={i18n}
|
||||
/>
|
||||
}
|
||||
|
||||
{/* Content area */}
|
||||
<div className={`${sidebarOpen ? 'relative' : 'absolute'} flex h-screen w-full flex-1 flex-col overflow-y-auto overflow-x-hidden bg-gray-100 dark:bg-gray-700`}>
|
||||
|
||||
{/* Site header */}
|
||||
{userObj && userObj.nombre_usuario &&
|
||||
|
||||
<Navbar
|
||||
sidebarOpen={sidebarOpen}
|
||||
setSidebarOpen={setSidebarOpen}
|
||||
navbarStyles="border-b via-navbar"
|
||||
navbarStyles="via-navbar"
|
||||
menuButtonStyles="via-menu-btn-navbar"
|
||||
userMenuButtonStyles="via-usermenu-btn-navbar"
|
||||
userOptionStyles="via-useroptions-navbar"
|
||||
userOptionSelectedStyles="via-useroptions-selected-navbar"
|
||||
userMenuButtonStyles="via-user-menu-btn-navbar"
|
||||
userOptionStyles="via-user-options-navbar"
|
||||
userOptionSelectedStyles="via-user-options-selected-navbar"
|
||||
onClickLogout={() => doLogout()}
|
||||
onClickProfile={() => router.push(`${presets.locations.profile}/${environment.getTime()}`)}
|
||||
MenuOptions={() => <UserOptionsMenu setPreferences={setPreferences} theme={theme} i18n={i18n} />}
|
||||
@ -247,24 +239,21 @@ const ResponsiveContainer = ({ children }) => {
|
||||
userObj={userObj}
|
||||
router={router}
|
||||
presets={presets}
|
||||
|
||||
/>
|
||||
|
||||
}
|
||||
|
||||
<main>
|
||||
<div className={userObj && userObj.nombre_usuario ? 'responsive-container' : ''}>
|
||||
<div className={userObj && userObj.nombre_usuario ? 'responsive-container' : 'hidden'}>
|
||||
{children}
|
||||
</div>
|
||||
</main>
|
||||
{
|
||||
userObj && userObj.nombre_usuario &&
|
||||
<SessionTimeout i18n={_i18n} user={userObj} onTimeout={() => onTimeout()} onCancelTimeout={() => onCancelTimeout()} />
|
||||
|
||||
{ userObj && userObj.nombre_usuario &&
|
||||
<SessionTimeout i18n={i18n} user={userObj} onTimeout={() => onTimeout()} onCancelTimeout={() => onCancelTimeout()} />
|
||||
}
|
||||
</div>
|
||||
|
||||
<Footer version={appVersion} label={i18n.t('common.version') || 'version'} />
|
||||
</div>
|
||||
<Footer />
|
||||
</LayoutContext.Provider>
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,33 @@
|
||||
import { RouteProvider } from '@/hooks/useRoute'
|
||||
import ResponsiveContainer from '@/layout/ResponsiveContainer'
|
||||
import LoadingProvider from '@/plugins/LoadingContext'
|
||||
import I18nProvider from '@/plugins/i18nContext'
|
||||
import '@/styles/globals.css'
|
||||
import type { AppProps } from 'next/app'
|
||||
import Head from 'next/head'
|
||||
import 'vComponents/styles/generated/output.css'
|
||||
import 'vComponents/styles/generated/bgColors.min.css'
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
return <Component {...pageProps} />
|
||||
import { ToastContainer } from 'react-toastify'
|
||||
|
||||
export default function App ({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<link rel="icon" href="https://wiki.via-asesores.com/logo-orbis_min.png" type="image/x-icon" />
|
||||
<title>Orbis Template</title>
|
||||
</Head>
|
||||
|
||||
<I18nProvider locale={'es'} dict={''}>
|
||||
<LoadingProvider>
|
||||
<ToastContainer />
|
||||
<ResponsiveContainer>
|
||||
<RouteProvider>
|
||||
<Component {...pageProps} />
|
||||
</RouteProvider>
|
||||
</ResponsiveContainer>
|
||||
</LoadingProvider>
|
||||
</I18nProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
export default function Document () {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Html lang="es">
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
|
115
src/pages/index.jsx
Normal file
115
src/pages/index.jsx
Normal file
@ -0,0 +1,115 @@
|
||||
import Image from 'next/image'
|
||||
import { useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { toast } from 'react-toastify'
|
||||
import md5 from 'js-md5'
|
||||
import { execute } from '@/helper/clientApi'
|
||||
import useI18n from '@/hooks/useI18n'
|
||||
import useLoading from '@/hooks/useLoading'
|
||||
import FormLogin from '@/components/Login/FormLogin'
|
||||
import presets from '@/utils/globalPresets'
|
||||
import environment from '@/utils/environment'
|
||||
import useGlobalContainer from '@/hooks/useGlobalContainer'
|
||||
import useHasMounted from '@/hooks/useHasMounted'
|
||||
|
||||
const LoginPage = () => {
|
||||
const global = useGlobalContainer()
|
||||
const router = useRouter()
|
||||
const i18n = useI18n()
|
||||
const loading = useLoading()
|
||||
const hasMounted = useHasMounted()
|
||||
const homePath = presets.locations.welcome
|
||||
|
||||
const loginUsuario = async (datos) => {
|
||||
loading.start()
|
||||
if (datos && datos !== null) {
|
||||
const hash = md5.create()
|
||||
hash.update(datos.password.trim())
|
||||
try {
|
||||
const resultado = await execute('SPR_LOGIN', [datos.email.toLowerCase().trim(), hash.hex()])
|
||||
loading.stop()
|
||||
if (resultado === undefined) {
|
||||
toast.error(i18n.t('common.errorApi'), presets.toaster)
|
||||
return
|
||||
}
|
||||
if (resultado[0].status === 'ERROR') {
|
||||
toast.error(resultado[0].message, presets.toaster)
|
||||
} else if (resultado[0].status === 'WARNING') {
|
||||
toast.warning(resultado[0].message, presets.toaster)
|
||||
} else if (resultado[0].token) {
|
||||
const user = {
|
||||
email: resultado[0].correo_electronico,
|
||||
nombre_usuario: resultado[0].nombre_completo,
|
||||
// img_user: resultado[0].foto,
|
||||
token: resultado[0].token,
|
||||
es_admin: resultado[0].es_admin,
|
||||
compania: resultado[0].nombre_compania,
|
||||
departamento: resultado[0].nombre_departamento,
|
||||
tiempo_expiracion: resultado[0].tiempo_expiracion,
|
||||
fecha_inicio_sesion: resultado[0].fecha_inicio_sesion,
|
||||
fecha_fin_sesion: resultado[0].fecha_fin_sesion,
|
||||
theme: resultado[0].theme,
|
||||
i18n: process.env.defaultLocale
|
||||
}
|
||||
const constante = {
|
||||
apptitle: process.env.apptitle,
|
||||
max_mb_upload: process.env.maxMbUpload
|
||||
}
|
||||
await environment.login(user.token, user, constante)
|
||||
toast.success(`Bienvenido ${user.nombre_usuario}`, presets.toaster)
|
||||
await global.setUserObj(user)
|
||||
await global.setConstanteObj(constante)
|
||||
await global.setToken(resultado[0].token)
|
||||
await global.setTheme(user.theme)
|
||||
await i18n.locale(user.i18n)
|
||||
router.push(homePath)
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(i18n.t('common.errorApi') + error, presets.toaster)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getEnv = async () => {
|
||||
const env = await environment.getEnvUser()
|
||||
if (env && env.token) {
|
||||
router.push(presets.locations.welcome)
|
||||
}
|
||||
}
|
||||
|
||||
// when page is mounted
|
||||
useEffect(() => {
|
||||
if (hasMounted) {
|
||||
getEnv()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [hasMounted])
|
||||
|
||||
return (
|
||||
<div className={'via-login-page'}>
|
||||
<div className={'via-login-layout'}>
|
||||
{/* <!-- Tarjeta de Login --> */}
|
||||
<div className={'via-card'}>
|
||||
<div className={'via-login-header'}>
|
||||
<div className={'h-64 w-64 shrink-0'}>
|
||||
<Image src={presets.images.logo} alt="logo" className={'via-login-logo'} width={100} height={100} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="align-center flex w-full p-4 ">
|
||||
<div className={'via-login-form'}>
|
||||
{/* <!-- Formulario --> */}
|
||||
<FormLogin onLogin={loginUsuario} />
|
||||
{/* <!-- Fin Formulario --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={'via-login-background'}
|
||||
style={{ backgroundImage: `url(${presets.images.loginFondo})`, minHeight: '75vh', backgroundSize: 'cover' }}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginPage
|
@ -1,118 +0,0 @@
|
||||
import Image from 'next/image'
|
||||
import { Inter } from 'next/font/google'
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] })
|
||||
|
||||
export default function Home () {
|
||||
return (
|
||||
<main
|
||||
className={`flex min-h-screen flex-col items-center justify-between p-24 ${inter.className}`}
|
||||
>
|
||||
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
|
||||
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:dark:bg-zinc-800/30">
|
||||
Get started by editing
|
||||
<code className="font-mono font-bold">src/pages/index.tsx</code>
|
||||
</p>
|
||||
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white lg:static lg:h-auto lg:w-auto lg:bg-none dark:from-black dark:via-black">
|
||||
<a
|
||||
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
By{' '}
|
||||
<Image
|
||||
src="/vercel.svg"
|
||||
alt="Vercel Logo"
|
||||
className="dark:invert"
|
||||
width={100}
|
||||
height={24}
|
||||
priority
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:lg:h-[360px] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700/10 after:dark:from-sky-900 after:dark:via-[#0141ff]/40">
|
||||
<Image
|
||||
className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js Logo"
|
||||
width={180}
|
||||
height={37}
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-32 grid text-center lg:mb-0 lg:w-full lg:max-w-5xl lg:grid-cols-4 lg:text-left">
|
||||
<a
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
|
||||
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2 className={'mb-3 text-2xl font-semibold'}>
|
||||
Docs{' '}
|
||||
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
|
||||
->
|
||||
</span>
|
||||
</h2>
|
||||
<p className={'m-0 max-w-[30ch] text-sm opacity-50'}>
|
||||
Find in-depth information about Next.js features and API.
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
|
||||
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2 className={'mb-3 text-2xl font-semibold'}>
|
||||
Learn{' '}
|
||||
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
|
||||
->
|
||||
</span>
|
||||
</h2>
|
||||
<p className={'m-0 max-w-[30ch] text-sm opacity-50'}>
|
||||
Learn about Next.js in an interactive course with quizzes!
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
|
||||
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2 className={'mb-3 text-2xl font-semibold'}>
|
||||
Templates{' '}
|
||||
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
|
||||
->
|
||||
</span>
|
||||
</h2>
|
||||
<p className={'m-0 max-w-[30ch] text-sm opacity-50'}>
|
||||
Discover and deploy boilerplate example Next.js projects.
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
|
||||
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<h2 className={'mb-3 text-2xl font-semibold'}>
|
||||
Deploy{' '}
|
||||
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
|
||||
->
|
||||
</span>
|
||||
</h2>
|
||||
<p className={'m-0 max-w-[30ch] text-sm opacity-50'}>
|
||||
Instantly deploy your Next.js site to a shareable URL with Vercel.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { createContext, useContext, useState } from 'react'
|
||||
import { createContext, useState } from 'react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import presets from '@/utils/globalPresets'
|
||||
|
||||
|
@ -1,19 +1,14 @@
|
||||
import { createContext, useState, useRef, useEffect } from 'react'
|
||||
import rosetta from 'rosetta'
|
||||
// import rosetta from 'rosetta/debug'
|
||||
import { execute } from '@/helper/clientApi'
|
||||
import useHasMounted from '@/hooks/useHasMounted'
|
||||
import environment from '@/utils/environment'
|
||||
// import { sprCatalogosS } from '@/js/spr'
|
||||
// import { getEnv } from '@/js/funciones'
|
||||
// import environment from '@/utils/environment'
|
||||
|
||||
const i18n = rosetta()
|
||||
|
||||
export const defaultLanguage = 'es'
|
||||
export const languages = ['es', 'en']
|
||||
export const contentLanguageMap = { es: 'es-GT', en: 'en-US' }
|
||||
|
||||
export const I18nContext = createContext()
|
||||
const defaultLanguage = 'es'
|
||||
const languages = ['es', 'en']
|
||||
const contentLanguageMap = { es: 'es-GT', en: 'en-US' }
|
||||
const I18nContext = createContext()
|
||||
|
||||
// default language
|
||||
i18n.locale(defaultLanguage)
|
||||
@ -42,12 +37,10 @@ const I18nProvider = ({ children, locale, dict }) => {
|
||||
|
||||
const setLanguage = async () => {
|
||||
let msgs = {}
|
||||
const env = await environment.getEnvUser()
|
||||
const response2 = await execute('SPR_PROY_SESION_S', [env.token])
|
||||
// TODO: implementar idioma del usuario
|
||||
// if (response2[0].status !== 'ERROR') {
|
||||
// // const options = await execute(sprCatalogosS, ['datosUsuario', await getEnv(i18n)])
|
||||
// const options = await execute(sprCatalogosS, ['datosUsuario', env.token])
|
||||
// const env = await environment.getEnvUser()
|
||||
// const response = await execute('SPR_PROY_SESION_S', [env.token])
|
||||
// if (response[0].status !== 'ERROR') {
|
||||
// const options = await execute('SPR_CATALOGOS_S', ['idioma', env.token])
|
||||
// locale = options[0].idioma
|
||||
// } else {
|
||||
// locale = defaultLanguage
|
||||
@ -71,11 +64,6 @@ const I18nProvider = ({ children, locale, dict }) => {
|
||||
setLanguage()
|
||||
}
|
||||
|
||||
// // when locale is updated
|
||||
// useEffect(() => {
|
||||
// setLanguage()
|
||||
// }, [activeLocaleRef.current])
|
||||
|
||||
// when page is mounted
|
||||
useEffect(() => {
|
||||
if (hasMounted) {
|
||||
@ -88,4 +76,6 @@ const I18nProvider = ({ children, locale, dict }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export { defaultLanguage, languages, contentLanguageMap, I18nContext }
|
||||
|
||||
export default I18nProvider
|
||||
|
58
src/styles/additional-styles/dropzone.css
Normal file
58
src/styles/additional-styles/dropzone.css
Normal file
@ -0,0 +1,58 @@
|
||||
@import "react-dropzone-component/styles/filepicker.css";
|
||||
|
||||
.dropzone.dz-clickable {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
height: 80px !important;
|
||||
min-height: 80px !important;
|
||||
margin: 0px !important;
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-image {
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
width: 120px;
|
||||
height: 80px !important;
|
||||
position: relative;
|
||||
display: block;
|
||||
z-index: 10;
|
||||
margin: 0px !important;
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-image img {
|
||||
display: block;
|
||||
max-height: 80px !important;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-details {
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
top: 8px !important;
|
||||
left: 0;
|
||||
margin: 0px !important;
|
||||
padding: 0px !important;
|
||||
opacity: 0;
|
||||
font-size: 13px;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
height: 80px !important;
|
||||
padding: 2em 1em;
|
||||
text-align: center;
|
||||
color: rgba(0,0,0,.9);
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
.filepicker-file-icon {
|
||||
margin: 5px !important;
|
||||
padding: 1px !important;
|
||||
}
|
7
src/styles/additional-styles/toastify.css
Normal file
7
src/styles/additional-styles/toastify.css
Normal file
@ -0,0 +1,7 @@
|
||||
@import 'react-toastify/dist/ReactToastify.css';
|
||||
|
||||
.Toastify__toast-container--top-center {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
15
src/styles/component-styles/datatable.css
Normal file
15
src/styles/component-styles/datatable.css
Normal file
@ -0,0 +1,15 @@
|
||||
.via-states-datatable {
|
||||
@apply text-xs font-semibold mr-2 px-2.5 py-0.5 rounded;
|
||||
}
|
||||
.via-icon-active {
|
||||
@apply text-green-800 dark:text-green-300;
|
||||
}
|
||||
.via-icon-inactive {
|
||||
@apply text-red-800 dark:text-red-300;
|
||||
}
|
||||
.via-detalle-datatable {
|
||||
@apply text-white bg-blue-700 hover:bg-blue-800 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800;
|
||||
}
|
||||
.via-badge-datatable {
|
||||
@apply text-white bg-red-500 border-white dark:border-gray-900;
|
||||
}
|
112
src/styles/component-styles/loading.css
Normal file
112
src/styles/component-styles/loading.css
Normal file
@ -0,0 +1,112 @@
|
||||
.backgroundLoader {
|
||||
@apply bg-white backdrop-blur-md;
|
||||
}
|
||||
|
||||
.colorLoader {
|
||||
@apply bg-sky-500;
|
||||
}
|
||||
|
||||
.div_loading {
|
||||
@apply rounded-lg border border-gray-200 shadow-md sm:p-6 md:p-8 dark:border-gray-700 z-50;
|
||||
position: absolute;
|
||||
height: 35%;
|
||||
width: 30%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
margin: 0 auto;
|
||||
width: 200px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.spinner > div {
|
||||
height: 100%;
|
||||
width: 8px;
|
||||
display: inline-block;
|
||||
margin-left: 3px;
|
||||
-webkit-animation: sk-stretchdelay 1.8s infinite ease-in-out;
|
||||
animation: sk-stretchdelay 1.8s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.spinner div:nth-child(1) {
|
||||
-webkit-animation-delay: -1.6s;
|
||||
animation-delay: -1.6s;
|
||||
}
|
||||
|
||||
.spinner div:nth-child(2) {
|
||||
-webkit-animation-delay: -1.4s;
|
||||
animation-delay: -1.4s;
|
||||
}
|
||||
|
||||
.spinner div:nth-child(3) {
|
||||
-webkit-animation-delay: -1.2s;
|
||||
animation-delay: -1.2s;
|
||||
}
|
||||
|
||||
.spinner div:nth-child(4) {
|
||||
-webkit-animation-delay: -1.0s;
|
||||
animation-delay: -1.0s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-stretchdelay {
|
||||
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
|
||||
20% { -webkit-transform: scaleY(1.0) }
|
||||
}
|
||||
|
||||
@keyframes sk-stretchdelay {
|
||||
0%, 40%, 100% {
|
||||
transform: scaleY(0.4);
|
||||
-webkit-transform: scaleY(0.4);
|
||||
} 20% {
|
||||
transform: scaleY(1.0);
|
||||
-webkit-transform: scaleY(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
.lds-facebook {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.lds-facebook div {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
width: 16px;
|
||||
background: #fff;
|
||||
animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
|
||||
}
|
||||
|
||||
.lds-facebook div:nth-child(1) {
|
||||
left: 8px;
|
||||
animation-delay: -0.24s;
|
||||
}
|
||||
|
||||
.lds-facebook div:nth-child(2) {
|
||||
left: 32px;
|
||||
animation-delay: -0.12s;
|
||||
}
|
||||
|
||||
.lds-facebook div:nth-child(3) {
|
||||
left: 56px;
|
||||
animation-delay: 0;
|
||||
}
|
||||
|
||||
@keyframes lds-facebook {
|
||||
0% {
|
||||
top: 8px;
|
||||
height: 64px;
|
||||
}
|
||||
50%, 100% {
|
||||
top: 24px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
19
src/styles/component-styles/navbar.css
Normal file
19
src/styles/component-styles/navbar.css
Normal file
@ -0,0 +1,19 @@
|
||||
.via-navbar {
|
||||
@apply bg-white dark:bg-[#222222] border-slate-200 text-theme-app-500 dark:text-theme-app-50 font-semibold !important;
|
||||
}
|
||||
|
||||
.via-menu-btn-navbar {
|
||||
@apply text-slate-600 hover:text-slate-900 !important;
|
||||
}
|
||||
|
||||
.via-user-menu-btn-navbar {
|
||||
@apply bg-slate-700 text-white transition-colors duration-[350ms] ease-in-out !important;
|
||||
}
|
||||
|
||||
.via-user-options-navbar {
|
||||
@apply text-gray-900 bg-transparent transition-colors duration-[350ms] ease-in-out !important;
|
||||
}
|
||||
|
||||
.via-user-options-selected-navbar {
|
||||
@apply bg-slate-700 dark:bg-slate-800 text-white transition-colors duration-[350ms] ease-in-out !important;
|
||||
}
|
31
src/styles/component-styles/sidebar.css
Normal file
31
src/styles/component-styles/sidebar.css
Normal file
@ -0,0 +1,31 @@
|
||||
.via-bg-sidebar {
|
||||
@apply bg-theme-app-500 border border-theme-app-300 rounded-t-lg md:rounded-t-none md:rounded-b-lg md:rounded-none dark:border-theme-app-800 dark:from-theme-app-700 dark:to-theme-app-800 !important;
|
||||
}
|
||||
|
||||
.via-options-sidebar {
|
||||
@apply text-theme-app-50 bg-transparent transition-colors duration-150 font-semibold hover:bg-theme-app-50 hover:text-gray-800 dark:text-theme-app-50 dark:hover:bg-theme-app-700 first-letter:uppercase !important;
|
||||
}
|
||||
|
||||
.via-sub-options-sidebar {
|
||||
@apply text-white hover:bg-theme-app-100 transition-colors duration-150 font-semibold gap-x-1 hover:text-gray-800 dark:text-theme-app-50 dark:hover:bg-theme-app-800 !important;
|
||||
}
|
||||
|
||||
.via-drawer-count {
|
||||
@apply inline-flex items-center w-8 justify-center mr-1 px-2 py-2 text-sm font-semibold leading-none bg-teal-800 text-white rounded-full
|
||||
}
|
||||
|
||||
.via-app-title-sidebar {
|
||||
@apply !text-theme-app-50 dark:text-theme-app-50 hover:bg-theme-app-800 dark:hover:bg-theme-app-950 !rounded-lg px-1 cursor-default !important;
|
||||
}
|
||||
|
||||
.via-user-info-sidebar {
|
||||
@apply !text-white bg-theme-app-700 dark:bg-theme-app-900 hover:bg-theme-app-800 dark:hover:bg-theme-app-950 !rounded-t-lg py-1 cursor-default;
|
||||
}
|
||||
|
||||
.via-icons-sidebar {
|
||||
@apply !text-theme-app-950 bg-blue-100 rounded-md border p-[1px] drop-shadow-md !important;
|
||||
}
|
||||
|
||||
.via-icons-sub-sidebar {
|
||||
@apply !text-theme-app-950 bg-cyan-50 rounded-md h-6 w-6 p-[1px] drop-shadow-md !important;
|
||||
}
|
@ -1,27 +1,39 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=fallback');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Material+Icons+Round');
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--foreground-rgb: 0, 0, 0;
|
||||
--background-start-rgb: 214, 219, 220;
|
||||
--background-end-rgb: 255, 255, 255;
|
||||
}
|
||||
/* ===== Scrollbar CSS ===== */
|
||||
@layer utilities {
|
||||
/* Firefox */
|
||||
* {
|
||||
scrollbar-width: auto;
|
||||
scrollbar-color: #1F92BF #e1e1e1;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--foreground-rgb: 255, 255, 255;
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
/* Chrome, Edge, and Safari */
|
||||
*::-webkit-scrollbar {
|
||||
@apply w-2 h-2 bg-gray-200 dark:bg-gray-800 rounded-lg;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
@apply bg-theme-app-600 rounded-lg border-theme-app-400 dark:bg-theme-app-600 dark:border-theme-app-600;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
@apply bg-theme-app-700 border-theme-app-700 dark:bg-theme-app-900 dark:border-theme-app-900;
|
||||
transition: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
/* Additional Styles */
|
||||
@import 'additional-styles/toastify.css';
|
||||
@import 'component-styles/loading.css';
|
||||
@import 'component-styles/sidebar.css';
|
||||
@import 'component-styles/navbar.css';
|
||||
@import 'component-styles/datatable.css';
|
||||
@import 'page-styles/common.css';
|
||||
@import 'page-styles/login.css';
|
||||
@import 'ui-styles/via-ui.css';
|
150
src/styles/page-styles/common.css
Normal file
150
src/styles/page-styles/common.css
Normal file
@ -0,0 +1,150 @@
|
||||
.via-card {
|
||||
@apply block rounded-md shadow-md w-full border-gray-300 border drop-shadow-lg bg-white dark:bg-[#4E4E4E] shadow-[#D1D1D1] hover:shadow-[#00000033];
|
||||
}
|
||||
|
||||
.via-label {
|
||||
@apply block text-gray-500 dark:text-gray-300 text-[14px] xl:text-[15px] font-medium mb-1 pl-0;
|
||||
}
|
||||
|
||||
.via-input {
|
||||
@apply w-full text-sm text-gray-900 dark:text-neutral-900 rounded-lg border border-gray-300 focus:ring-stone-500 focus:border-stone-500 dark:border-stone-600 dark:placeholder-gray-400 dark:focus:border-stone-500 !important;
|
||||
}
|
||||
|
||||
.via-input-prepend {
|
||||
@apply w-full text-sm text-gray-900 dark:text-neutral-900 rounded-l-lg border-l-gray-100 border border-gray-300 focus:ring-stone-500 focus:border-stone-500 dark:border-stone-600 dark:placeholder-gray-400 dark:focus:border-stone-500 !important;
|
||||
}
|
||||
|
||||
.via-append-input {
|
||||
@apply absolute top-0 -right-1 h-full p-1 text-sm font-medium text-white bg-theme-app-500 dark:bg-theme-app-900 rounded-r-lg border border-theme-app-900 hover:bg-theme-app-600 focus:ring-4 focus:outline-none focus:ring-theme-app-300 dark:hover:bg-theme-app-900 dark:focus:ring-theme-app-800;
|
||||
}
|
||||
|
||||
.via-append-input-extra {
|
||||
@apply absolute top-0 right-0 h-full p-1 mr-6 text-sm font-medium text-white bg-theme-app-500 dark:bg-theme-app-900 border border-theme-app-900 hover:bg-theme-app-800 focus:ring-4 focus:outline-none focus:ring-theme-app-300 dark:hover:bg-theme-app-900 dark:focus:ring-theme-app-800;
|
||||
}
|
||||
|
||||
.via-button {
|
||||
@apply cursor-pointer inline-flex items-center h-8 px-2 m-1 text-white ease-linear transition-colors duration-150 rounded-md border border-gray-300 dark:border-gray-700;
|
||||
}
|
||||
.via-div-actions {
|
||||
@apply flex w-full justify-center flex-wrap;
|
||||
}
|
||||
|
||||
.via-no {
|
||||
@apply text-red-700 dark:text-red-600;
|
||||
}
|
||||
|
||||
.via-yes {
|
||||
@apply text-green-700 dark:text-green-600;
|
||||
}
|
||||
|
||||
.via-default {
|
||||
@apply text-theme-app-700 dark:text-theme-app-300;
|
||||
}
|
||||
|
||||
.via-default-bg {
|
||||
@apply bg-theme-app-700 dark:bg-theme-app-300;
|
||||
}
|
||||
|
||||
.via-default-active {
|
||||
@apply text-theme-app-500 dark:text-theme-app-500;
|
||||
}
|
||||
|
||||
.via-yellow {
|
||||
@apply text-amber-400 dark:text-amber-300 ;
|
||||
}
|
||||
|
||||
.via-yellow-bg {
|
||||
@apply bg-amber-500 dark:bg-amber-600 ;
|
||||
}
|
||||
|
||||
.via-yellow-active {
|
||||
@apply text-amber-500 dark:text-amber-600 ;
|
||||
}
|
||||
|
||||
.via-green {
|
||||
@apply text-green-400 dark:text-green-300;
|
||||
}
|
||||
|
||||
.via-green-bg {
|
||||
@apply bg-green-500 dark:bg-green-600;
|
||||
}
|
||||
|
||||
.via-green-active {
|
||||
@apply text-green-600 dark:text-green-600;
|
||||
}
|
||||
|
||||
.via-red {
|
||||
@apply text-red-400 dark:text-red-300;
|
||||
}
|
||||
|
||||
.via-red-bg {
|
||||
@apply bg-red-500 dark:bg-red-600;
|
||||
}
|
||||
|
||||
.via-red-active {
|
||||
@apply text-red-600 dark:text-red-600;
|
||||
}
|
||||
|
||||
.via-blue {
|
||||
@apply text-blue-400 dark:text-blue-300;
|
||||
}
|
||||
|
||||
.via-blue-bg {
|
||||
@apply bg-blue-500 dark:bg-blue-600;
|
||||
}
|
||||
|
||||
.via-blue-active {
|
||||
@apply text-blue-600 dark:text-blue-600;
|
||||
}
|
||||
|
||||
.via-translate {
|
||||
@apply -translate-x-1/2;
|
||||
}
|
||||
|
||||
.via-opacity {
|
||||
@apply bg-opacity-25;
|
||||
}
|
||||
|
||||
.via-img-preview {
|
||||
@apply h-16 max-h-16 !important;
|
||||
}
|
||||
|
||||
.responsive-container {
|
||||
@apply w-full h-auto min-h-[calc(100vh-60px)] mx-auto bg-[#ECEFF8] dark:bg-[#0f0f0f] items-center pb-10 p-2;
|
||||
}
|
||||
|
||||
.via-title {
|
||||
@apply font-semibold text-[#0F0F0F] dark:text-[#F1F1F1]
|
||||
}
|
||||
|
||||
.via-subtitle {
|
||||
@apply text-[#606060] dark:text-[#AAAAAA]
|
||||
}
|
||||
|
||||
.via-text {
|
||||
@apply text-[#131313] dark:text-[#FFFFFF]
|
||||
}
|
||||
|
||||
/* Clase para el color warning (azul) */
|
||||
.via-warning {
|
||||
@apply bg-blue-500 hover:bg-blue-600 dark:bg-warning-dark dark:hover:bg-warning-hover-dark text-white !important;
|
||||
}
|
||||
|
||||
/* Clase para el color danger (rojo) */
|
||||
.via-danger {
|
||||
@apply bg-danger hover:bg-danger-hover dark:bg-danger-dark dark:hover:bg-danger-hover-dark text-white !important;
|
||||
}
|
||||
|
||||
/* Clase para el color success (verde) */
|
||||
.via-success {
|
||||
@apply bg-success hover:bg-success-hover dark:bg-success-dark dark:hover:bg-success-hover-dark text-white !important;
|
||||
}
|
||||
|
||||
|
||||
.via-background {
|
||||
@apply bg-[#F6F6F6] dark:bg-[#272727] !important;
|
||||
}
|
||||
|
||||
/* .test {
|
||||
@apply bg-theme-app-
|
||||
} */
|
23
src/styles/page-styles/login.css
Normal file
23
src/styles/page-styles/login.css
Normal file
@ -0,0 +1,23 @@
|
||||
.via-login-page {
|
||||
@apply flex flex-wrap w-screen h-screen bg-gray-200;
|
||||
}
|
||||
|
||||
.via-login-layout {
|
||||
@apply flex flex-shrink w-full h-full md:w-1/2 lg:w-1/3 bg-white;
|
||||
}
|
||||
|
||||
.via-login-header {
|
||||
@apply flex w-full p-4 justify-center overflow-hidden;
|
||||
}
|
||||
|
||||
.via-login-logo {
|
||||
@apply w-64 h-64 bg-center bg-auto bg-no-repeat object-cover;
|
||||
}
|
||||
|
||||
.via-login-background {
|
||||
@apply hidden flex-shrink h-full md:w-1/2 lg:w-2/3 md:flex bg-center bg-contain;
|
||||
}
|
||||
|
||||
.via-login-form {
|
||||
@apply flex w-full flex-col space-y-4;
|
||||
}
|
214
src/styles/ui-styles/via-ui.css
Normal file
214
src/styles/ui-styles/via-ui.css
Normal file
@ -0,0 +1,214 @@
|
||||
.main-container {
|
||||
@apply grid gap-x-5 gap-y-3 2xl:gap-y-8 my-2 2xl:my-4 text-slate-700 justify-center content-around;
|
||||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply flex flex-col w-full rounded-lg border duration-300 items-center bg-white dark:bg-[#272727] shadow-[#D1D1D1] hover:shadow-[#00000033];
|
||||
}
|
||||
|
||||
.card-header {
|
||||
@apply flex flex-col w-full rounded-t-lg border-b duration-300 items-center bg-white dark:bg-[#272727] shadow-[#D1D1D1] hover:shadow-[#00000033];
|
||||
}
|
||||
|
||||
.header-card {
|
||||
@apply bg-gradient-to-br dark:bg-gradient-to-br from-theme-app-600 to-theme-app-400 dark:from-theme-app-800 dark:to-theme-app-600 flex h-12 w-full items-center justify-center rounded-t-lg;
|
||||
}
|
||||
|
||||
.header-items {
|
||||
@apply grid grid-cols-2 justify-start text-white font-medium gap-2 items-center w-full py-2 ;
|
||||
grid-template-columns: auto auto;
|
||||
}
|
||||
|
||||
.text-header {
|
||||
@apply font-semibold md:ml-2 ml-1 text-white justify-start left-0 ;
|
||||
overflow:hidden;
|
||||
height: auto;
|
||||
-webkit-box-orient: vertical;
|
||||
display: block;
|
||||
display: -webkit-box;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
|
||||
@keyframes loading {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-loading {
|
||||
animation: loading 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
|
||||
/* tooltip styles */
|
||||
|
||||
.tooltip-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tooltip-box {
|
||||
@apply !absolute;
|
||||
background-color: #555;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.tooltip-top {
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.tooltip-bottom {
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.tooltip-left {
|
||||
right: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.tooltip-right {
|
||||
left: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* tabs styles */
|
||||
.tabs {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.tabsContentWrapper {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tabsContent {
|
||||
/* position: absolute; */
|
||||
transition: transform 0.6s ease-in-out;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tabsContent {
|
||||
@apply w-full;
|
||||
transition: transform 0.6s ease-in-out, opacity 0.6s ease-in-out;
|
||||
}
|
||||
|
||||
.tabsContent[data-active="false"] {
|
||||
transform: translateX(-100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tabsContent[data-active="true"] {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.tabsList {
|
||||
@apply flex w-full rounded-t-lg border-b duration-300 items-center bg-white dark:bg-[#272727] shadow-[#D1D1D1] hover:shadow-[#00000033] p-1;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.tabsTrigger {
|
||||
@apply bg-white dark:bg-[#3D3D3D] text-gray-500 dark:text-gray-200 hover:text-gray-700 dark:hover:text-gray-300 active:!bg-gray-100 dark:active:!bg-[#3D3D3D] font-medium transition-colors duration-500 delay-1000 ease-in-out;
|
||||
flex-grow: 1;
|
||||
text-align: center;
|
||||
transition: background-color 0.75s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tabsTrigger[data-active="true"] {
|
||||
@apply bg-white text-theme-app-500 dark:text-theme-app-900 font-bold hover:font-extrabold;
|
||||
}
|
||||
|
||||
.tabsIndicator {
|
||||
@apply bg-theme-app-500 dark:bg-theme-app-900;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 4px;
|
||||
transition: left 0.75s ease, right 0.75s ease;
|
||||
}
|
||||
|
||||
.slide-left-in {
|
||||
animation: slide-left-in 0.75s forwards;
|
||||
}
|
||||
|
||||
.slide-right-in {
|
||||
animation: slide-right-in 0.75s forwards;
|
||||
}
|
||||
|
||||
.slide-left-out {
|
||||
animation: slide-left-out 0.75s forwards;
|
||||
}
|
||||
|
||||
.slide-right-out {
|
||||
animation: slide-right-out 0.75s forwards;
|
||||
}
|
||||
|
||||
@keyframes slide-left-in {
|
||||
from { transform: translateX(100%); }
|
||||
to { transform: translateX(0); }
|
||||
}
|
||||
|
||||
@keyframes slide-right-in {
|
||||
from { transform: translateX(-100%); }
|
||||
to { transform: translateX(0); }
|
||||
}
|
||||
|
||||
@keyframes slide-left-out {
|
||||
from { transform: translateX(0); }
|
||||
to { transform: translateX(-100%); }
|
||||
}
|
||||
|
||||
@keyframes slide-right-out {
|
||||
from { transform: translateX(0); }
|
||||
to { transform: translateX(100%); }
|
||||
}
|
||||
|
||||
/* checkbox styles */
|
||||
|
||||
|
||||
.filter-button{
|
||||
@apply items-center hover:bg-theme-app-400 dark:hover:bg-theme-app-700 rounded-lg grid grid-cols-2 h-10 px-4 gap-2 text-slate-700 hover:text-white dark:text-white font-medium duration-300 dark:hover:text-white;
|
||||
grid-template-columns: auto auto;
|
||||
}
|
||||
|
||||
|
||||
.Accordion > .AccordionTrigger:first-child > div:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.Accordion > .AccordionTrigger:last-child > div:last-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.tooltip-indicator {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 8px solid gray;
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 50;
|
||||
}
|
@ -1,36 +1,33 @@
|
||||
import Cookie from 'js-cookie'
|
||||
import functions from 'v-functions'
|
||||
import { execute } from '../helper/clientApi'
|
||||
import presets from './globalPresets'
|
||||
import { findWhere } from 'underscore'
|
||||
import { execute } from '@/helper/clientApi'
|
||||
|
||||
/**
|
||||
* @brief Objeto con funciones comunes de ambiente
|
||||
* @typedef {Object} Environment
|
||||
* @property {function} getResultParameters - Funcion para obtener los parametros de un resultado
|
||||
* @property {function} buildFunctiontsHeaders - Funcion para construir las funciones de los headers
|
||||
* @property {function} setEnvUser - Funcion para guardar el usuario en el localstorage
|
||||
* @property {function} getEnvUser - Funcion para obtener el usuario del localstorage
|
||||
* @property {function} logout - Funcion para cerrar sesion
|
||||
* @property {function} login - Funcion para iniciar sesion
|
||||
* @property {function} getTime - Funcion para obtener la hora actual
|
||||
* @property {function} validaResultadoDB - Funcion para validar el resultado de una peticion a la base de datos
|
||||
* @property {function} getFileParams - Funcion para obtener los parametros de un archivo
|
||||
* @property {function} validaPermisos - Funcion para validar los permisos de un usuario
|
||||
* @property {function} i18nHeaders - Funcion para traducir los headers
|
||||
*
|
||||
* @type {Environment}
|
||||
* @exports environment
|
||||
* @description Este archivo contiene las funciones globales de la aplicacion
|
||||
* @example
|
||||
* import environment from '@/utils/environment'
|
||||
*
|
||||
* environment.getResultParameters(confParameters, item, mainParameters)
|
||||
*
|
||||
*/
|
||||
const environment = {
|
||||
/**
|
||||
* @brief Obtiene el token de los Cookies y el usuario del LocalStorage
|
||||
* @param {*} callback funcion a ejecutar cuando se obtuvieron los datos
|
||||
* @returns
|
||||
*/
|
||||
getFormatRandomNumber: () => {
|
||||
const getRandomId = () => {
|
||||
return String(Math.floor(Math.random() * 10000))
|
||||
}
|
||||
|
||||
const currentDate = new Date()
|
||||
|
||||
let fixName = `${currentDate.getFullYear()}`
|
||||
fixName += `${(currentDate.getMonth() + 1).toString().padStart(2, '0')}`
|
||||
fixName += `${currentDate.getDate().toString().padStart(2, '0')}`
|
||||
fixName += `${currentDate.getHours().toString().padStart(2, '0')}`
|
||||
fixName += `${currentDate.getMinutes().toString().padStart(2, '0')}`
|
||||
fixName += `${currentDate.getMilliseconds().toString()}`
|
||||
fixName += `_${getRandomId()}`
|
||||
|
||||
return fixName
|
||||
},
|
||||
|
||||
getResultParameters: (confParameters, item, mainParameters) => {
|
||||
const resultParameters = []
|
||||
if (confParameters != null && confParameters.length) {
|
||||
@ -236,7 +233,6 @@ const environment = {
|
||||
// return (new Date()).getTime()
|
||||
return 1668220842700
|
||||
},
|
||||
|
||||
validaResultadoDB: (resultado, i18n, toast, showOKMessage = false) => {
|
||||
const showToast = (i18n, toast, message, type, i18nCode = null) => {
|
||||
const displayMessage = message
|
||||
@ -279,7 +275,6 @@ const environment = {
|
||||
|
||||
return true
|
||||
},
|
||||
|
||||
getFileParams (model, headers, value, prefix) {
|
||||
const head = findWhere(headers, { value })
|
||||
const { filename, extension } = functions.getFilePattern(model[value])
|
||||
@ -307,7 +302,6 @@ const environment = {
|
||||
}
|
||||
return params
|
||||
},
|
||||
|
||||
validaPermisos: async (token, administra, configura, graba_modifica, consulta) => {
|
||||
let permisos = await execute('FUN_INFO_SESION_ENTIDAD', [token])
|
||||
if (permisos === undefined || permisos.length <= 0) {
|
||||
|
@ -7,7 +7,7 @@ const presets = {
|
||||
images: {
|
||||
loginFondo: 'https://www.via-asesores.com/backgrounds/smartoperation/SmartOperation_background.png',
|
||||
welcomeFondo: 'https://www.via-asesores.com/backgrounds/smartoperation/SmartOperation_background.png',
|
||||
icon: 'https://www.via-asesores.com/icons/smartoperation/SmartOperation_icon_light.png',
|
||||
icon: 'https://www.via-asesores.com/logos/logo_icons/smarterp_icon.svg',
|
||||
logo: 'https://www.via-asesores.com/logos/smartOperations.png',
|
||||
imageLoader: 'https://www.via-asesores.com/logos/logo_via.png',
|
||||
noImageFound: 'https://www.via-asesores.com/smartsalesnprofit/images/LogoViasaClaroTransparente_600x.png',
|
||||
@ -17,8 +17,7 @@ const presets = {
|
||||
locations: {
|
||||
login: '/',
|
||||
welcome: '/dashboard',
|
||||
welcomeTemp: '/welcome',
|
||||
profile: '/seguridad/profile'
|
||||
welcomeTemp: '/welcome'
|
||||
},
|
||||
toaster: {
|
||||
position: 'top-center',
|
||||
|
@ -1,20 +1,96 @@
|
||||
import type { Config } from 'tailwindcss'
|
||||
|
||||
const defaultTheme = require('tailwindcss/defaultTheme')
|
||||
|
||||
const config: Config = {
|
||||
mode: 'jit',
|
||||
content: [
|
||||
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/app/**/*.{js,ts,jsx,tsx,mdx}'
|
||||
],
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {
|
||||
backgroundImage: {
|
||||
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
||||
'gradient-conic':
|
||||
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
|
||||
fontFamily: {
|
||||
sans: ['Inter', ...defaultTheme.fontFamily.sans],
|
||||
inter: ['Inter', 'sans-serif', ...defaultTheme.fontFamily.sans]
|
||||
},
|
||||
fontSize: {
|
||||
xs: ['0.75rem', { lineHeight: '1.25' }],
|
||||
sm: ['0.875rem', { lineHeight: '1.25' }],
|
||||
base: ['1rem', { lineHeight: '1.25', letterSpacing: '-0.01em' }],
|
||||
lg: ['1.125rem', { lineHeight: '1.25', letterSpacing: '-0.01em' }],
|
||||
xl: ['1.25rem', { lineHeight: '1.25', letterSpacing: '-0.01em' }],
|
||||
'2xl': ['1.5rem', { lineHeight: '1.33', letterSpacing: '-0.01em' }],
|
||||
'3xl': ['1.88rem', { lineHeight: '1.33', letterSpacing: '-0.01em' }],
|
||||
'4xl': ['2.25rem', { lineHeight: '1.25', letterSpacing: '-0.02em' }],
|
||||
'5xl': ['3rem', { lineHeight: '1.25', letterSpacing: '-0.02em' }],
|
||||
'6xl': ['3.75rem', { lineHeight: '1.2', letterSpacing: '-0.02em' }]
|
||||
},
|
||||
screens: {
|
||||
xs: '480px'
|
||||
},
|
||||
plugins: [],
|
||||
borderWidth: {
|
||||
3: '3px'
|
||||
},
|
||||
minWidth: {
|
||||
36: '9rem',
|
||||
44: '11rem',
|
||||
56: '14rem',
|
||||
60: '15rem',
|
||||
72: '18rem',
|
||||
80: '20rem'
|
||||
},
|
||||
maxWidth: {
|
||||
'8xl': '88rem',
|
||||
'9xl': '96rem'
|
||||
},
|
||||
zIndex: {
|
||||
60: '60'
|
||||
},
|
||||
boxShadow: {
|
||||
DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.08), 0 1px 2px 0 rgba(0, 0, 0, 0.02)',
|
||||
md: '0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -1px rgba(0, 0, 0, 0.02)',
|
||||
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.01)',
|
||||
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 10px 10px -5px rgba(0, 0, 0, 0.01)'
|
||||
},
|
||||
outline: {
|
||||
blue: '2px solid rgba(0, 112, 244, 0.5)'
|
||||
},
|
||||
colors: {
|
||||
'theme-text': {
|
||||
principal: '#323338',
|
||||
disabled: '#cbd5e1'
|
||||
},
|
||||
'theme-app': {
|
||||
50: '#DDE3EB',
|
||||
100: '#B0C4D6',
|
||||
200: '#83A5C1',
|
||||
300: '#5686AC',
|
||||
400: '#296897',
|
||||
500: '#1E507B',
|
||||
600: '#1B4870',
|
||||
700: '#183F64',
|
||||
800: '#153758',
|
||||
900: '#112F4D',
|
||||
950: '#0E2741'
|
||||
},
|
||||
warning: '#3B82F6',
|
||||
'warning-dark': '#1E40AF',
|
||||
'warning-hover': '#60A5FA',
|
||||
'warning-hover-dark': '#2563EB',
|
||||
danger: '#EF4444',
|
||||
'danger-dark': '#991B1B',
|
||||
'danger-hover': '#F87171',
|
||||
'danger-hover-dark': '#DC2626',
|
||||
success: '#22C55E',
|
||||
'success-dark': '#15803D',
|
||||
'success-hover': '#34D399',
|
||||
'success-hover-dark': '#22C55E'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: []
|
||||
}
|
||||
export default config
|
||||
|
@ -14,9 +14,10 @@
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
"@/*": ["./src/*"],
|
||||
"vComponents/*": ["./node_modules/vComponents/dist/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user