Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] #8

Merged
merged 6 commits into from
Jul 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions src/app/auth/login/components/form.component.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,56 @@
'use client';
import { Formik } from 'formik';
import { Box, Grid } from '@mui/material';
import { Box, Grid, InputAdornment } from '@mui/material';
import { LOGIN_FORM } from '@/app/auth/login/constant/login.constant';
import Input from '@/shared/component/input/input.component';
import Button from '@/shared/component/button/button.component';
import Typography from '@/shared/component/typography/typography';
import Checkbox from '@/shared/component/checkbox/checkbox.component';
import { LOGIN_SCHEMA } from '@/app/auth/services/schema/schema.service';
import { useState } from 'react';
import Icon from '@/shared/component/icon/icon';
import { useLoginUserMutation } from '@/app/auth/services/api-service/api-service';

export default function LoginForm () {
const [ passwordView, setPasswordView ] = useState<boolean>( true );
const [ login ] = useLoginUserMutation();
return (
<Formik
onSubmit={ () => alert( 'hello' ) }
initialValues={ {} }
render={ ( { handleChange, handleSubmit } ) => (
onSubmit={ ({ email, password }) => {
const data = {
user: {
email,
password
}
};
login(data);
} }
initialValues={ { email: '', password: '' } }
validationSchema={LOGIN_SCHEMA}
render={ ( { handleChange, values, handleBlur, handleSubmit, errors, touched } ) => (
<Grid item container>
{
LOGIN_FORM.map( ( { label, name } ) => (
LOGIN_FORM.map( ( { label, name, type } ) => (
<Grid item container my='8px' key={ `${ label }+${ name }` }>
<Input
<Input
name={ name }
label={ label }
helperText={'type'}
onBlur={handleBlur}
value={values[name]}
variant='outlined'
type={( type === 'password' && passwordView ? 'password' : 'text' ) || type}
helperText={(touched[name as keyof unknown] &&
errors[name as keyof unknown] &&
errors[name as keyof unknown]) as string }
onChange={ handleChange }
InputProps={ {
endAdornment: (
type === 'password' && <InputAdornment position="start" className='cursor--pointer' onClick={(): void =>
setPasswordView( !passwordView )}>
<Icon iconName={ passwordView ? 'visibility' : 'visibility_off' } />
</InputAdornment>
),
} }
/>
</Grid>
) )
Expand All @@ -40,7 +69,7 @@ export default function LoginForm () {
</Grid>
</Grid>
<Grid item container my='32px' >
<Button click={ handleSubmit } variant='contained' label='Login' className='width--full'/>
<Button click={ handleSubmit } variant='contained' label='Login' className='width--full' />
</Grid>
</Grid>
) }
Expand Down
8 changes: 5 additions & 3 deletions src/app/auth/login/constant/login.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import gmail from '../../../../../public/icons/Gmail.svg';
export const LOGIN_FORM: LoginForm[] = [
{
name: 'email',
label: 'Email'
label: 'Email',
type: 'email'
},
{
name: 'password',
label: 'Password'
}
label: 'Password',
type: 'password'
},
];

export const LOGIN_ICONS: LoginIcons[] = [
Expand Down
3 changes: 2 additions & 1 deletion src/app/auth/login/model/login.model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface LoginForm {
name: string;
label: string
label: string;
type: string
}

export interface LoginIcons {
Expand Down
25 changes: 25 additions & 0 deletions src/app/auth/services/api-service/api-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/dist/query/react';
import { FetchBaseQueryArgs } from '@reduxjs/toolkit/dist/query/fetchBaseQuery';
import { EndpointBuilder } from '@reduxjs/toolkit/dist/query/endpointDefinitions';

export const authAPI = createApi({
reducerPath: 'auth',
baseQuery: fetchBaseQuery({
baseUrl: process.env.NEXT_PUBLIC_BASE_URL
}as FetchBaseQueryArgs),
endpoints: (builder: EndpointBuilder<any, any, any>) => ({
loginUser: builder.mutation<any, string>({
query (body) {
return {
url: 'users/sign_in',
method: 'POST',
body
};
}
}),
}),
});

export const { useLoginUserMutation } = authAPI;


16 changes: 16 additions & 0 deletions src/app/auth/services/schema/schema.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as Yup from 'yup';
import {
EMAIL_FIELD,
PASSWORD_LENGTH, PASSWORD_REQUIRED_LOWERCASE,
PASSWORD_REQUIRED_NUMBER, PASSWORD_REQUIRED_UPPERCASE,
REQUIRED_FIELD
} from '@/shared/constant/shared.constant';

export const LOGIN_SCHEMA = Yup.object().shape( {
email: Yup.string()
.required( REQUIRED_FIELD ).email( EMAIL_FIELD ),
password: Yup.string().required( REQUIRED_FIELD ).min( 6, PASSWORD_LENGTH )
.matches( /[0-9]/, PASSWORD_REQUIRED_NUMBER )
.matches( /[a-z]/, PASSWORD_REQUIRED_LOWERCASE )
.matches( /[A-Z]/, PASSWORD_REQUIRED_UPPERCASE ),
} );
46 changes: 27 additions & 19 deletions src/shared/component/input/input.component.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { Grid, TextField } from '@mui/material';
import { TextField } from '@mui/material';
import { InputProps } from '@/shared/component/input/model/input.model';
import { styled } from '@mui/system';

const CustomInput = styled( TextField )(
( { theme } ) => `
& .MuiFormHelperText-root {
color: ${theme.palette.error.main};
}

`
);

function Input (props: InputProps) {
const { placeholder,
Expand All @@ -17,24 +27,22 @@ function Input (props: InputProps) {
type
} = props;
return(
<Grid>
<TextField fullWidth
className={className as string}
name={name}
onBlur={onBlur}
variant={variant as any}
placeholder={placeholder as string}
label={label}
InputProps={InputProps as any}
type={type}
value={value}
onChange={onChange}
helperText={helperText}
error={error as boolean}
sx={sx as any}
required={required as boolean}
/>
</Grid>
<CustomInput fullWidth
className={className as string}
name={name}
onBlur={onBlur}
variant={variant as any}
placeholder={placeholder as string}
label={label}
InputProps={InputProps as any}
type={type}
value={value}
onChange={onChange}
helperText={helperText}
error={error as boolean}
sx={sx as any}
required={required as boolean}
/>
);
}

Expand Down
6 changes: 6 additions & 0 deletions src/shared/constant/shared.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const REQUIRED_FIELD = 'The field is required';
export const EMAIL_FIELD = 'Email must be a valid email';
export const PASSWORD_LENGTH = 'Password must be 6 characters long';
export const PASSWORD_REQUIRED_NUMBER = 'Password requires a number';
export const PASSWORD_REQUIRED_LOWERCASE = 'Password requires a lowercase letter';
export const PASSWORD_REQUIRED_UPPERCASE = 'Password requires an uppercase letter';
2 changes: 2 additions & 0 deletions src/shared/model/common.model.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export type MatColors = 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning';
export type MatVariants = 'text' | 'outlined' | 'contained';
export type MatInputVariants = 'filled' | 'outlined' | 'standard';


Loading