#1 feature/1161_login_page_UI

Fusionado
merisahm fusionados 2 commits de feature/1161_login_page_UI en FE_dev hace 3 años

+ 26021
- 88
package-lock.json
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


BIN
public/hrcenter.png Ver fichero


+ 7
- 1
public/index.html Ver fichero

@@ -2,8 +2,14 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="hrcenter.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap"
rel="stylesheet"
/>
<meta name="theme-color" content="#000000" />
<meta
name="description"

BIN
src/assets/images/Vector.png Ver fichero


BIN
src/assets/images/google1.png Ver fichero


BIN
src/assets/images/hrcenter.png Ver fichero


BIN
src/assets/images/logo_horizontal_black.png Ver fichero


+ 4
- 0
src/assets/styles/_base.scss Ver fichero

@@ -26,6 +26,10 @@ html {
}
}

body{
background-color: $grayFD !important;
overflow-x: hidden;
}
html,
body,
#root {

+ 2
- 2
src/assets/styles/_functions.scss Ver fichero

@@ -1,7 +1,7 @@
@function pxToRem($target, $context: $base-font-size) {
@return ($target / $context) * 1rem;
@return calc($target / $context) * 1rem;
}

@function pxToRemMd($target, $context: $base-font-size-md) {
@return ($target / $context) * 1rem;
@return calc($target / $context) * 1rem;
}

+ 2
- 2
src/assets/styles/_layout.scss Ver fichero

@@ -1,10 +1,10 @@
.l-page {
@include flex-column;
flex: 1 1 auto;
padding-bottom: 7rem;
// padding-bottom: 7rem;
position:relative;
@include media-below($bp-xl) {
padding-bottom: 4rem;
// padding-bottom: 4rem;
}
}


+ 22
- 1
src/assets/styles/_typography.scss Ver fichero

@@ -1,3 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap");
body,
div,
dl,
@@ -53,5 +54,25 @@ h3,
h4,
h5,
h6 {
font-weight: 500;
font-weight: 600 !important;
}

.text-end {
width: 100%;
text-align: end;
}

h5 {
// imported from figma
//styleName: Heading;
font-family: Source Sans Pro !important;
font-size: 24px !important;
font-weight: 600 !important;
line-height: 32px !important;
letter-spacing: 0.02em !important;
text-align: center !important;
}

.text-black{
color: $mainBlack;
}

+ 14
- 3
src/assets/styles/_variables.scss Ver fichero

@@ -1,7 +1,18 @@
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap');
$base-font-size: 16px;
$base-font-size-md: 14px;

$font-family: 'Avenir Next';
$font-family: "Source Sans Pro";
// $font-family: "Open Sans";

// Colors from Figma
$diligPurple: #90278f;
$mainBlue: #226cb0;
$googleGray: #f1f1f1; // color of the google auth btn
$googleGray-light: #f5f5f5;
$googleGray-dark: #e9e9e9;
$mainBlack: #272727;
$grayFD: #FDFDFD;

// Colors
$color-primary: #024f86;
@@ -50,8 +61,8 @@ $box-shadow: 0 3px 8px 0 rgba(112, 120, 135, 0.24);
$account-dropdown-shadow: 0 6px 38px 0 rgba(112, 120, 135, 0.56);

// Border Radius
$border-radius: 4px;
$border-radius-md: 8px;
$border-radius: 9px;
$border-radius-md: 16px;

// Breakpoints
$bp-xxs: 325px;

+ 2
- 2
src/assets/styles/components/_auth-card.scss Ver fichero

@@ -1,6 +1,6 @@
.c-auth-card {
max-width: pxToRem(624px);
width: 100%;
max-width: pxToRem(289px);
width: 100%;
box-shadow: $box-shadow;
border-radius: $border-radius;
border: 1px solid $color-primary-light;

+ 1
- 1
src/assets/styles/components/_auth.scss Ver fichero

@@ -20,4 +20,4 @@
line-height: 1.22;
color: $dark-blue;
font-weight: bold;
}
}

+ 28
- 6
src/assets/styles/components/_button.scss Ver fichero

@@ -2,13 +2,13 @@
@include outline-none;
@include button-clear;
@include flex-center;
font-size: pxToRem(18px);
font-size: pxToRem(12px) !important;
line-height: 1.35;
padding: pxToRem(8px) pxToRem(8px);
border-radius: $border-radius;
padding: pxToRem(13px) pxToRem(8px) !important;
border-radius: $border-radius !important;
box-shadow: $button-shadow-pressed;
color: inherit;
font-weight: 600;
font-weight: 600 !important;
letter-spacing: 0;
text-align: center;
text-transform: uppercase;
@@ -25,9 +25,8 @@
}

&.c-btn--primary {
background-color: $color-primary;
background-color: $mainBlue;
color: $white;
border: 1px solid $color-primary;

&:disabled {
&:hover {
@@ -47,6 +46,29 @@
box-shadow: $button-shadow-pressed;
}
}
&.c-btn--gray {
background-color: $googleGray;
color: $black-5;

&:disabled {
&:hover {
background-color: $googleGray;
box-shadow: none;
}
}

&:hover {
background-color: $googleGray-light;
box-shadow: $button-shadow-hover;
}

&:focus,
&:active {
background-color: $googleGray-dark;
box-shadow: $button-shadow-pressed;
}
}

&.c-btn--primary-outlined {
background-color: transparent;

+ 46
- 0
src/assets/styles/components/_login.scss Ver fichero

@@ -1,3 +1,49 @@
.c-login-container {
position: relative;
min-height: 100vh;
display: flex !important;
justify-content: center;
align-items: center;
padding: 0;
overflow-x: hidden;

// input[type="text"], input[type='password'] {
// width: 100%;
// border-radius: $border-radius;
// }
.rounded-input{
border-radius: $border-radius-md !important;
}
}

.login-logo {
width: pxToRem(150px);
height: pxToRem(150px);
border-radius: 12px;
}

.l-t-rectangle,
.r-b-rectangle {
position: absolute;
width: 180px;
height: 180px;
filter: blur(155px);
border-radius: 18px;
// transform: rotate(-15deg);
}

.l-t-rectangle {
left: -60px;
top: 0px;
background: $diligPurple;
}

.r-b-rectangle {
right: -60px;
bottom: 0px;
background: $mainBlue;
}

.c-login {
&.c-login--user {
.c-login__form {

+ 20
- 0
src/assets/styles/components/_nav.scss Ver fichero

@@ -0,0 +1,20 @@
.full-rounded{
height: 40px;
width: 40px;
font-size: 16px;
@include flex-center;
border-radius: 50%;
background-color: $mainBlue;
color: white;
margin-right: 50px;
}

// smooth transition from app-bg color to navbar bg-color
.navLinks-cont{
background: linear-gradient(90deg, rgba(255,255,255,0.25) 15%, white);
}

.search-Icon{
margin-right: 50px;
cursor: pointer;
}

+ 9
- 0
src/assets/styles/components/_rules.scss Ver fichero

@@ -0,0 +1,9 @@
.hr{
height: 2px;
background-color: $grey-12;
width: 115px;
margin: 5px 10px;
}
.hr-mid{
padding: 2.5px 7.5px;
}

+ 1
- 1
src/components/Auth/Auth.js Ver fichero

@@ -7,7 +7,7 @@ const Auth = ({ children }) => {

return (
<div className="c-auth">
<h1 className="c-auth__title">{t(`login.welcome`)}</h1>
<h1 className="c-auth__title">{t(`app.title`)}</h1>
{children}
</div>
);

+ 189
- 151
src/components/MUI/NavbarComponent.js Ver fichero

@@ -1,160 +1,198 @@
import React, { useState, useMemo, useContext } from 'react';
import React, { useState, useMemo, useContext } from "react";
import {
AppBar,
Badge,
Box,
IconButton,
Toolbar,
Typography,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
useMediaQuery,
} from '@mui/material';
import { useTheme } from '@mui/system';
import MenuOutlinedIcon from '@mui/icons-material/MenuOutlined';
import ShoppingBasketIcon from '@mui/icons-material/ShoppingBasket';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
import MenuList from './MenuListComponent';
import Drawer from './DrawerComponent';
import { ColorModeContext } from '../../context/ColorModeContext';
AppBar,
// Badge,
Box,
IconButton,
Toolbar,
Typography,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
useMediaQuery,
} from "@mui/material";
import HrLogo from "../../assets/images/hrcenter.png";
import searchIcon from "../../assets/images/Vector.png";
import { useTheme } from "@mui/system";
import MenuOutlinedIcon from "@mui/icons-material/MenuOutlined";
// import ShoppingBasketIcon from "@mui/icons-material/ShoppingBasket";
import Brightness4Icon from "@mui/icons-material/Brightness4";
import Brightness7Icon from "@mui/icons-material/Brightness7";
// import MenuList from "./MenuListComponent";
import Drawer from "./DrawerComponent";
import { ColorModeContext } from "../../context/ColorModeContext";
import { useTranslation } from "react-i18next";

const NavbarComponent = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.down('sm'));
const toggleColorMode = useContext(ColorModeContext);
const navItems = [
"ads",
"selectionFlow",
"candidates",
"planer",
"patterns",
"stats",
"users",
];
const [openDrawer, setOpenDrawer] = useState(false);
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.down("sm"));
const toggleColorMode = useContext(ColorModeContext);

const handleToggleDrawer = () => {
setOpenDrawer(!openDrawer);
};
const { t } = useTranslation();

const drawerContent = useMemo(
() => (
<List>
<ListItemButton divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 1</ListItemText>
</ListItemIcon>
</ListItemButton>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 2</ListItemText>
</ListItemIcon>
</ListItem>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemText>Link 3</ListItemText>
</ListItem>
<ListItem divider>
<IconButton onClick={toggleColorMode}>
<ListItemText>Toggle {theme.palette.mode} mode</ListItemText>
{theme.palette.mode === 'dark' ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</ListItem>
</List>
),
[handleToggleDrawer]
);
const handleToggleDrawer = () => {
setOpenDrawer(!openDrawer);
};

return (
<AppBar
elevation={2}
sx={{ backgroundColor: 'background.default', position: 'relative' }}
>
<Toolbar>
<Box
component="div"
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
}}
>
{matches ? (
<Drawer
open={openDrawer}
toggleOpen={handleToggleDrawer}
content={drawerContent}
/>
) : (
<Box sx={{ display: 'flex' }}>
<Typography
variant="h6"
sx={{
marginRight: 3,
cursor: 'pointer',
color: 'text.primary',
}}
>
Link 1
</Typography>
<Typography
variant="body1"
sx={{
marginRight: 3,
cursor: 'pointer',
color: 'text.primary',
}}
>
Link 2
</Typography>
<Typography
variant="subtitle1"
sx={{
marginRight: 3,
cursor: 'pointer',
color: 'text.primary',
}}
>
Link 3
</Typography>
</Box>
)}
<Box>
<MenuList />
</Box>
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
{matches ? (
<Box>
<IconButton onClick={handleToggleDrawer}>
<MenuOutlinedIcon />
</IconButton>
</Box>
) : (
<Box>
<IconButton>
<Badge badgeContent={3} color="primary">
<ShoppingBasketIcon color="action" />
</Badge>
</IconButton>
<IconButton sx={{ ml: 1 }} onClick={toggleColorMode}>
{theme.palette.mode === 'dark' ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</Box>
)}
</Box>
</Box>
</Toolbar>
</AppBar>
);
const drawerContent = useMemo(
() => (
<List>
{navItems.map((n) => (
<ListItemButton key={n} divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText
variant="body1"
sx={{
marginRight: "50px",
cursor: "pointer",
textAlign: "right",
lineHeight: "20.11px",
fontWeight: "400",
color: "text.primary",
marginY: "0",
padding: "0",
}}
className="text-black"
>
{t("nav." + n)}
</ListItemText>
</ListItemIcon>
</ListItemButton>
))}
<ListItem divider>
<IconButton onClick={toggleColorMode}>
<ListItemText>Toggle {theme.palette.mode} mode</ListItemText>
{theme.palette.mode === "dark" ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</ListItem>
</List>
),
[handleToggleDrawer]
);

return (
<AppBar
elevation={0}
sx={{
backgroundColor: "transparent",
position: "relative",
width: "100%",
padding: "0",
}}
>
<Toolbar
sx={{
padding: "0px",
margin: "0px",
width: "100%",
}}
>
<Box
component="div"
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
width: "100%",
padding: "0px",
margin: "0px",
// md: {paddingX: "72px"}
// paddingX: "72px"
}}
>
<Box
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
{matches ? (
<Box>
<IconButton onClick={handleToggleDrawer}>
<MenuOutlinedIcon />
</IconButton>
</Box>
) : (
<Box>
{/* <IconButton onClick={handleToggleDrawer}>
<MenuOutlinedIcon />
</IconButton> */}
<img
style={{ height: "37px", width: "37px", marginLeft: "72px" }}
src={HrLogo}
/>
</Box>
)}
</Box>
{matches ? (
<Drawer
open={openDrawer}
toggleOpen={handleToggleDrawer}
content={drawerContent}
/>
) : (
<Box
sx={{
display: "flex",
alignItems: "center",
paddingRight: "20px",
justifyContent: "flex-end",
height: "81px",
width: "1076px",
borderBottom: "1px solid #F4F4F4",
boxSizing: "border-box",
}}
className="navLinks-cont"
>
{navItems.map((n) => (
<Typography
variant="body1"
key={n}
sx={{
marginRight: "50px",
cursor: "pointer",
textAlign: "right",
lineHeight: "20.11px",
fontWeight: "400",
// color: "text.primary",
marginY: "0",
padding: "0",
}}
className="text-black"
>
{t("nav." + n)}
</Typography>
))}
<div className="search-Icon">
<img src={searchIcon} />
</div>
<div className="full-rounded">DR</div>
</Box>
)}
{/* <Box>
<MenuList />
</Box> */}
</Box>
</Toolbar>
</AppBar>
);
};

export default NavbarComponent;

+ 6
- 2
src/i18n/index.js Ver fichero

@@ -3,16 +3,20 @@ import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

import enTranslations from './resources/en';
import rsTranslations from './resources/rs';

i18n.use(initReactI18next).init({
lng: 'en',
lng: 'rs',
fallbackLng: 'en',
debug: false,
supportedLngs: ['en'],
supportedLngs: ['en','rs'],
resources: {
en: {
translation: enTranslations,
},
rs:{
translation: rsTranslations,
},
},
interpolation: {
format: (value, format) => {

+ 13
- 2
src/i18n/resources/en.js Ver fichero

@@ -1,6 +1,6 @@
export default {
app: {
title: 'React template'
title: 'HR Center'
},
refresh: {
title: 'Are you active?',
@@ -15,6 +15,7 @@ export default {
continue: 'Continue',
labelUsername: 'Username',
labelPassword: 'Password',
or: 'or',
next: 'Next',
nextPage: 'Next page',
previousPage: 'Previous page',
@@ -40,7 +41,7 @@ export default {
},
},
login: {
welcome: 'React template',
welcome: 'Welcome!',
dontHaveAccount: "Don't have an account? ",
emailFormat: 'Invalid email address format.',
emailRequired: 'An email or username is required.',
@@ -57,6 +58,7 @@ export default {
forgotYourPassword: 'Forgot your password?',
forgotPasswordEmail:'Email',
useDifferentEmail: 'Use different email address or username',
signInWithGoogle: 'Continue with google'
},
password: {
weak: 'weak',
@@ -89,5 +91,14 @@ export default {
apiErrors:{
ClientIpAddressIsNullOrEmpty:"Client Ip address is null or empty",
UsernameDoesNotExist: "Username does not exist"
},
nav:{
ads: 'Ads',
selectionFlow: 'Selection flow',
candidates: 'Candidates',
planer: 'Planer',
patterns: 'Patterns',
stats: 'Stats',
users: 'Users'
}
};

+ 110
- 0
src/i18n/resources/rs.js Ver fichero

@@ -0,0 +1,110 @@
export default {
app: {
title: 'HR Centar'
},
refresh: {
// title: 'Are you active?',
// cta:
// "You were registered as not active, please confirm that you are active in the next minute, if you don't you will be logged out.",
},
common: {
// close: 'Close',
// trademark: 'TM',
// search: 'Search',
// error: 'Error',
// continue: 'Continue',
labelUsername: 'Korisničko ime',
labelPassword: 'Šifra',
or: 'ili',
// next: 'Next',
// nextPage: 'Next page',
// previousPage: 'Previous page',
// back: 'Back',
// goBack: 'Go Back',
// ok: 'Ok',
// done: 'Done',
// confirm: 'Confirm',
// printDownload: 'Print/Download',
// cancel: 'Cancel',
// remove: 'Remove',
// invite: 'Invite',
// save: 'Save',
// complete: 'Complete',
// download: 'Download',
// yes: 'Yes',
// no: 'No',
// to: 'to',
// select: 'Select...',
// none: 'None',
// date: {
// range: '{{start}} to {{end}}',
// },
},
login: {
welcome: 'Dobrodošli!',
// dontHaveAccount: "Don't have an account? ",
// emailFormat: 'Invalid email address format.',
// emailRequired: 'An email or username is required.',
// noUsers: 'There are no users with that email.',
// passwordStrength: 'Your password is {{strength}}.',
// passwordLength: 'Your password contain between 8 and 50 characters.',
// signUpRecommendation: 'Sign up',
// email: 'Please enter your email address or username to log in:',
logInTitle: 'Prijavi se',
logIn: 'Prijavi se',
// signUp: 'Sign Up',
usernameRequired: 'Potrebno je uneti korisničko ime.',
passwordRequired: 'Potrebno je uneti šifru.',
forgotYourPassword: 'Zaboravio/la si šifru?',
// _useDifferentEmail: 'Use different email address or username',
// get useDifferentEmail() {
// return this._useDifferentEmail;
// },
// set useDifferentEmail(value) {
// this._useDifferentEmail = value;
// },
signInWithGoogle: 'Prijava putem Google-a'
},
// password: {
// weak: 'weak',
// average: 'average',
// good: 'good',
// strong: 'strong',
// },
// forgotPassword: {
// title: 'Forgot Password',
// label: 'Send email',
// emailRequired: 'An email is required.',
// emailFormat: 'Invalid email address format.',
// forgotPassword: {
// title: 'Forgot Password',
// subtitle:
// 'Please answer the security question to gain access to your account:',
// label: 'Reset Password',
// },
// },
// notFound: {
// text: "We're sorry but we couldn't find the page you were looking for.",
// goBack: 'Go back to homepage',
// },
// errorPage: {
// text:
// "We're sorry, an internal server error came up. Please be patient or try again later.",
// goBack: 'Go back to homepage',
// logout: 'Logout',
// },
// apiErrors:{
// ClientIpAddressIsNullOrEmpty:"Client Ip address is null or empty",
// UsernameDoesNotExist: "Username does not exist"
// },
nav:{
ads: 'Oglasi',
selectionFlow: 'Tok Selekcije',
candidates: 'Kandidati',
planer: 'Planer',
patterns: 'Šabloni',
stats: 'Statistika',
users: 'Korisnici'
}
};

+ 2
- 2
src/index.css Ver fichero

@@ -1,4 +1,4 @@
body {
/* body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
@@ -10,4 +10,4 @@ body {
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
} */

+ 11
- 0
src/main.scss Ver fichero

@@ -17,6 +17,17 @@
@import './assets/styles/components/forgot-password';
@import './assets/styles/components/input';
@import './assets/styles/components/error-page';
@import './assets/styles/components/rules';
@import './assets/styles/components/nav';
@import './assets/styles/layout';
@import './assets/styles/overwrite';
@import './assets/styles/utility';

.flex-center{
@include flex-center;
}

// ================= mui overrides
.css-122f4x8-MuiToolbar-root {
padding: 0 !important;
}

+ 20
- 18
src/pages/HomePage/HomePageMUI.js Ver fichero

@@ -1,17 +1,19 @@
import React from 'react';
import { Box, Grid } from '@mui/material';
import Navbar from '../../components/MUI/NavbarComponent';
import Modals from '../../components/MUI/Examples/ModalsExample';
import DataGrid from '../../components/MUI/Examples/DataGridExample';
import PagingSortingFiltering from '../../components/MUI/Examples/PagingSortingFilteringExample';
import PagingSortingFilteringServerSide from '../../components/MUI/Examples/PagingSortingFilteringExampleServerSide';
import RandomDataProvider from '../../context/RandomDataContext';
import React from "react";
// import { Box, Grid } from '@mui/material';
import Navbar from "../../components/MUI/NavbarComponent";
// import Modals from '../../components/MUI/Examples/ModalsExample';
// import DataGrid from '../../components/MUI/Examples/DataGridExample';
// import PagingSortingFiltering from '../../components/MUI/Examples/PagingSortingFilteringExample';
// import PagingSortingFilteringServerSide from '../../components/MUI/Examples/PagingSortingFilteringExampleServerSide';
// import RandomDataProvider from '../../context/RandomDataContext';

const HomePage = () => {
return (
<>
<Navbar />
<Box sx={{ mt: 4, mx: 4 }}>
return (
<div>
<Navbar />
<div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div>
{/* <Box sx={{ mt: 4, mx: 4 }}>
<Grid container spacing={2} justifyContent="center">
<Grid item xs={12} md={3}>
<Modals />
@@ -22,16 +24,16 @@ const HomePage = () => {
<Grid item xs={12} md={9}>
<PagingSortingFiltering />
</Grid>
<Grid item xs={12} md={9}>
{/* Move to higher components? */}
<RandomDataProvider>
<Grid item xs={12} md={9}> */}
{/* Move to higher components? */}
{/* <RandomDataProvider>
<PagingSortingFilteringServerSide />
</RandomDataProvider>
</Grid>
</Grid>
</Box>
</>
);
</Box> */}
</div>
);
};

export default HomePage;

+ 1
- 0
src/pages/LoginPage/LoginPage.js Ver fichero

@@ -11,6 +11,7 @@ import Button from '../../components/Button/Button';
import TextField from '../../components/InputFields/TextField';
import Auth from '../../components/Auth/Auth';
import AuthCard from '../../components/AuthCards/AuthCard';

import {
clearLoginErrors,
fetchUser,

+ 201
- 183
src/pages/LoginPage/LoginPageMUI.js Ver fichero

@@ -1,201 +1,219 @@
/* eslint-disable */
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { useFormik } from 'formik';
import { useDispatch, useSelector } from 'react-redux';
import { NavLink } from 'react-router-dom';
import * as Yup from 'yup';
import { useTranslation } from 'react-i18next';
import i18next from 'i18next';
import React, { useState } from "react";
import PropTypes from "prop-types";
import { useFormik } from "formik";
import { useDispatch, useSelector } from "react-redux";
import { NavLink } from "react-router-dom";
import * as Yup from "yup";
import { useTranslation } from "react-i18next";
import HrLogo from "../../assets/images/hrcenter.png";
import DiligLogo from "../../assets/images/logo_horizontal_black.png";
import googleLogo from "../../assets/images/google1.png";
import i18next from "i18next";
import {
clearLoginErrors,
fetchUser,
} from '../../store/actions/login/loginActions';
import { selectLoginError } from '../../store/selectors/loginSelectors';
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from '../../constants/pages';
clearLoginErrors,
fetchUser,
} from "../../store/actions/login/loginActions";
import { selectLoginError } from "../../store/selectors/loginSelectors";
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages";
import {
Box,
Button,
Container,
Grid,
IconButton,
InputAdornment,
Link,
TextField,
Typography,
} from '@mui/material';
import { Visibility, VisibilityOff } from '@mui/icons-material';
import Backdrop from '../../components/MUI/BackdropComponent';
import ErrorMessage from '../../components/MUI/ErrorMessageComponent';
import { selectIsLoadingByActionType } from '../../store/selectors/loadingSelectors';
import { LOGIN_USER_LOADING } from '../../store/actions/login/loginActionConstants';
Box,
Button,
Container,
Grid,
IconButton,
InputAdornment,
Link,
TextField,
Typography,
} from "@mui/material";
import { Visibility, VisibilityOff } from "@mui/icons-material";
import Backdrop from "../../components/MUI/BackdropComponent";
import ErrorMessage from "../../components/MUI/ErrorMessageComponent";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import { LOGIN_USER_LOADING } from "../../store/actions/login/loginActionConstants";
import { fontSize } from "@mui/system";

const LoginPage = ({ history }) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const error = useSelector(selectLoginError);
const dispatch = useDispatch();
const { t } = useTranslation();
const error = useSelector(selectLoginError);

const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);
const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);

// When user refreshes page
// useEffect(() => {
// function redirectClient() {
// if (!tokens.RefreshToken && !tokens.JwtToken) {
// return;
// }
// }
// When user refreshes page
// useEffect(() => {
// function redirectClient() {
// if (!tokens.RefreshToken && !tokens.JwtToken) {
// return;
// }
// }

// redirectClient();
// }, [history, tokens]);
// redirectClient();
// }, [history, tokens]);

const isLoading = useSelector(
selectIsLoadingByActionType(LOGIN_USER_LOADING)
);
const isLoading = useSelector(
selectIsLoadingByActionType(LOGIN_USER_LOADING)
);

const handleApiResponseSuccess = () => {
history.push({
pathname: HOME_PAGE,
state: {
from: history.location.pathname,
},
});
};
const handleApiResponseSuccess = () => {
history.push({
pathname: HOME_PAGE,
state: {
from: history.location.pathname,
},
});
};

const handleSubmit = (values) => {
const { username: Username, password: Password } = values;
dispatch(clearLoginErrors());
dispatch(
fetchUser({
Username,
Password,
handleApiResponseSuccess,
})
);
};
const handleSubmit = (values) => {
const { username: Username, password: Password } = values;
dispatch(clearLoginErrors());
dispatch(
fetchUser({
Username,
Password,
handleApiResponseSuccess,
})
);
};

const formik = useFormik({
initialValues: {
username: '',
password: '',
},
validationSchema: Yup.object().shape({
username: Yup.string().required(t('login.usernameRequired')),
password: Yup.string().required(t('login.passwordRequired')),
}),
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});
const formik = useFormik({
initialValues: {
username: "",
password: "",
},
validationSchema: Yup.object().shape({
username: Yup.string().required(t("login.usernameRequired")),
password: Yup.string().required(t("login.passwordRequired")),
}),
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});

return (
<Container component="main" maxWidth="md">
<Box
sx={{
marginTop: 32,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Typography component="h1" variant="h5">
{t('login.logInTitle')}
</Typography>
{error && <ErrorMessage error={error} />}
<Box
component="form"
onSubmit={formik.handleSubmit}
sx={{ position: 'relative', mt: 1, p: 1 }}
>
<Backdrop position="absolute" isLoading={isLoading} />
<TextField
name="username"
label={t('common.labelUsername')}
margin="normal"
value={formik.values.username}
onChange={formik.handleChange}
error={formik.touched.username && Boolean(formik.errors.username)}
helperText={formik.touched.username && formik.errors.username}
autoFocus
fullWidth
/>
<TextField
name="password"
label={t('common.labelPassword')}
margin="normal"
type={showPassword ? 'text' : 'password'}
value={formik.values.password}
onChange={formik.handleChange}
error={formik.touched.password && Boolean(formik.errors.password)}
helperText={formik.touched.password && formik.errors.password}
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
<Button
type="submit"
variant="contained"
sx={{ mt: 3, mb: 2 }}
fullWidth
>
{t('login.logIn')}
</Button>
<Grid container>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: 'center', md: 'left' } }}
>
<Link
to={FORGOT_PASSWORD_PAGE}
component={NavLink}
variant="body2"
underline="hover"
>
{t('login.forgotYourPassword')}
</Link>
</Grid>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: 'center', md: 'right' } }}
>
<Link
to="#"
component={NavLink}
variant="body2"
underline="hover"
>
{t('login.dontHaveAccount')}
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
);
return (
<Container
component="main"
maxWidth="xl"
className="c-login-container"
fullwidth="true"
>
<div className="l-t-rectangle"></div>
<div className="r-b-rectangle"></div>
<Box
sx={{
marginTop: 2,
width: 289,
height: 684,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<img src={HrLogo} className="login-logo" />
<Typography variant="h5" sx={{ m: 2, mt: 3 }}>
{t("login.welcome")}
</Typography>
{error && <ErrorMessage error={error} />}
<Box
component="form"
onSubmit={formik.handleSubmit}
sx={{ position: "relative" }}
>
<Backdrop position="absolute" isLoading={isLoading} />
{/* <label>Username:</label><br></br>
<input type='text' value={formik.values.username}
onChange={formik.handleChange}/> */}
<TextField
name="username"
label={t("common.labelUsername")}
margin="normal"
value={formik.values.username}
onChange={formik.handleChange}
error={formik.touched.username && Boolean(formik.errors.username)}
helperText={formik.touched.username && formik.errors.username}
autoFocus
fullWidth
/>
<TextField
className="rounded-input"
name="password"
label={t("common.labelPassword")}
margin="normal"
type={showPassword ? "text" : "password"}
value={formik.values.password}
onChange={formik.handleChange}
error={formik.touched.password && Boolean(formik.errors.password)}
helperText={formik.touched.password && formik.errors.password}
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
<Grid container>
<Grid item sm={12} sx={{ textAlign: "end" }}>
<Link
to={FORGOT_PASSWORD_PAGE}
component={NavLink}
variant="body2"
underline="hover"
className="text-end"
sx={{ fontSize: 12 }}
>
{t("login.forgotYourPassword")}
</Link>
</Grid>
</Grid>
<Button
type="submit"
variant="contained"
sx={{ mt: 3, mb: 2 }}
fullWidth
className="c-btn c-btn--primary"
>
{t("login.logIn")}
</Button>
<div className="flex-center">
<div className="hr hr-s"></div>
<div className="hr-mid">{t("common.or")}</div>
<div className="hr hr-e"></div>
</div>
<Button
className="c-btn c-btn--gray flex-center"
sx={{ width: "100%", mt: 2 }}
>
<img src={googleLogo} style={{ marginRight: "15px" }} />
<Typography sx={{ m: 0, p: 0 }} variant="buttonText">
{t("login.signInWithGoogle")}
</Typography>
</Button>
<div className="flex-center">
<img src={DiligLogo} style={{ margin: "70px auto 0px auto" }} />
</div>
</Box>
</Box>
</Container>
);
};

LoginPage.propTypes = {
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
};
export default LoginPage;

+ 11541
- 11251
yarn.lock
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


Cargando…
Cancelar
Guardar