Commit 20cb9f30 authored by janithGamage's avatar janithGamage

feat : update

desc :
> user registration option UI updated
> user registration option API Connected
> user logic on frontend
parent e686976e
...@@ -3,7 +3,7 @@ GENERATE_SOURCEMAP = false ...@@ -3,7 +3,7 @@ GENERATE_SOURCEMAP = false
## Backend API URL ## Backend API URL
REACT_APP_API_URL_MOCK=https://mock-data-api-nextjs.vercel.app/ REACT_APP_API_URL_MOCK=https://mock-data-api-nextjs.vercel.app/
REACT_APP_API_URL=http://13.49.44.192/api/v1/ REACT_APP_API_URL=http://localhost:5000/
## Google Map Key ## Google Map Key
......
...@@ -12,7 +12,8 @@ import authReducer from 'store/reducers/auth'; ...@@ -12,7 +12,8 @@ import authReducer from 'store/reducers/auth';
import Loader from 'components/Loader'; import Loader from 'components/Loader';
import { AuthProps, JWTContextType } from 'types/auth'; import { AuthProps, JWTContextType } from 'types/auth';
import { KeyedObject } from 'types/root'; import { KeyedObject } from 'types/root';
import { axiosServices_Mock as axios } from 'utils/axios'; import { axiosServices_Mock as axios, axiosServices } from 'utils/axios';
const chance = new Chance(); const chance = new Chance();
...@@ -123,20 +124,49 @@ export const JWTProvider = ({ children }: { children: React.ReactElement }) => { ...@@ -123,20 +124,49 @@ export const JWTProvider = ({ children }: { children: React.ReactElement }) => {
window.localStorage.setItem('users', JSON.stringify(users)); window.localStorage.setItem('users', JSON.stringify(users));
}; };
const registerUser = async (email: string, password: string, firstName: string, lastName: string, contactNumber: string, confirmPassword: string) => {
// todo: this flow need to be recode as it not verified
const id = chance.bb_pin();
const response = await axiosServices.post('/rest_node/user/sign-up', {
firstName,
lastName,
email,
contactNumber,
password,
confirmPassword,
type: "member"
});
let users = response.data;
if (window.localStorage.getItem('users') !== undefined && window.localStorage.getItem('users') !== null) {
const localUsers = window.localStorage.getItem('users');
users = [
...JSON.parse(localUsers!),
{
id,
email,
password,
name: `${firstName} ${lastName}`
}
];
}
window.localStorage.setItem('users', JSON.stringify(users));
};
const logout = () => { const logout = () => {
setSession(null); setSession(null);
dispatch({ type: LOGOUT }); dispatch({ type: LOGOUT });
}; };
const resetPassword = async (email: string) => {}; const resetPassword = async (email: string) => { };
const updateProfile = () => {}; const updateProfile = () => { };
if (state.isInitialized !== undefined && !state.isInitialized) { if (state.isInitialized !== undefined && !state.isInitialized) {
return <Loader />; return <Loader />;
} }
return <JWTContext.Provider value={{ ...state, login, logout, register, resetPassword, updateProfile }}>{children}</JWTContext.Provider>; return <JWTContext.Provider value={{ ...state, login, logout, register, registerUser, resetPassword, updateProfile }}>{children}</JWTContext.Provider>;
}; };
export default JWTContext; export default JWTContext;
...@@ -3,6 +3,7 @@ import { FormattedMessage } from 'react-intl'; ...@@ -3,6 +3,7 @@ import { FormattedMessage } from 'react-intl';
// assets // assets
import { import {
BookOutlined,
CarryOutOutlined, CarryOutOutlined,
CreditCardOutlined, CreditCardOutlined,
FileTextOutlined, FileTextOutlined,
...@@ -25,7 +26,8 @@ const icons = { ...@@ -25,7 +26,8 @@ const icons = {
CarryOutOutlined, CarryOutOutlined,
CreditCardOutlined, CreditCardOutlined,
LoginOutlined, LoginOutlined,
RocketOutlined RocketOutlined,
BookOutlined
}; };
// ==============================|| MENU ITEMS - SUPPORT ||============================== // // ==============================|| MENU ITEMS - SUPPORT ||============================== //
...@@ -63,6 +65,44 @@ const application: NavItemType = { ...@@ -63,6 +65,44 @@ const application: NavItemType = {
} }
] ]
}, },
{
id: 'learning-management',
title: <FormattedMessage id="learning-management" />,
type: 'collapse',
icon: icons.BookOutlined,
children: [
// {
// id: 'learning-list',
// title: <FormattedMessage id="learning-list" />,
// type: 'item',
// url: '/learning-management/list',
// },
{
id: 'learning-curriculums',
title: <FormattedMessage id="learning-curriculums" />,
type: 'item',
url: '/learning-management/curriculums',
},
{
id: 'learning-curriculums-subscribed',
title: <FormattedMessage id="learning-curriculums-subscribed" />,
type: 'item',
url: '/learning-management/curriculums-subscribed',
},
{
id: 'learning-lead-board',
title: <FormattedMessage id="learning-lead-board" />,
type: 'item',
url: '/learning-management/lead-board',
},
{
id: 'learning-feedback',
title: <FormattedMessage id="learning-feedback" />,
type: 'item',
url: '/learning-management/feedback',
}
]
},
// { // {
// id: 'authentication', // id: 'authentication',
// title: <FormattedMessage id="authentication" />, // title: <FormattedMessage id="authentication" />,
......
...@@ -6,7 +6,7 @@ import { Grid, Stack, Typography } from '@mui/material'; ...@@ -6,7 +6,7 @@ import { Grid, Stack, Typography } from '@mui/material';
// project import // project import
import useAuth from 'hooks/useAuth'; import useAuth from 'hooks/useAuth';
import AuthWrapper from 'sections/auth/AuthWrapper'; import AuthWrapper from 'sections/auth/AuthWrapper';
import FirebaseRegister from 'sections/auth/auth-forms/AuthRegister'; import AuthRegister from 'sections/auth/auth-forms/AuthRegister';
// ================================|| REGISTER ||================================ // // ================================|| REGISTER ||================================ //
...@@ -31,7 +31,7 @@ const Register = () => { ...@@ -31,7 +31,7 @@ const Register = () => {
</Stack> </Stack>
</Grid> </Grid>
<Grid item xs={12}> <Grid item xs={12}>
<FirebaseRegister /> <AuthRegister />
</Grid> </Grid>
</Grid> </Grid>
</AuthWrapper> </AuthWrapper>
......
// material-ui
// project import
// ==============================|| List ||============================== //
const List = () => (
<>
</>
);
export default List;
...@@ -29,6 +29,9 @@ const Dashboard = Loadable(lazy(() => import('pages/home/dashboard'))); ...@@ -29,6 +29,9 @@ const Dashboard = Loadable(lazy(() => import('pages/home/dashboard')));
// render - user management page // render - user management page
// const UserManagementList = Loadable(lazy(() => import('pages/user-management/list/list'))); // const UserManagementList = Loadable(lazy(() => import('pages/user-management/list/list')));
// render - learning management page
// const LearningManagementList = Loadable(lazy(() => import('pages/learning-management/list/list')));
// render - parameter curriculum management page // render - parameter curriculum management page
const CurriculumManagementList = Loadable(lazy(() => import('pages/parameter/curriculum-management/list/list'))); const CurriculumManagementList = Loadable(lazy(() => import('pages/parameter/curriculum-management/list/list')));
...@@ -74,7 +77,16 @@ const MainRoutes = { ...@@ -74,7 +77,16 @@ const MainRoutes = {
element: <MaintenanceUnderConstruction /> element: <MaintenanceUnderConstruction />
} }
] ]
}, },
{
path: 'learning-management',
children: [
{
path: 'list',
element: <MaintenanceUnderConstruction />
}
]
},
], ],
}, },
{ {
...@@ -102,7 +114,7 @@ const MainRoutes = { ...@@ -102,7 +114,7 @@ const MainRoutes = {
element: <TutorialManagementList /> element: <TutorialManagementList />
} }
] ]
}, },
], ],
}, },
{ {
......
import { useEffect, useState, SyntheticEvent } from 'react'; import { SyntheticEvent, useEffect, useState } from 'react';
import { Link as RouterLink, useNavigate } from 'react-router-dom'; import { Link as RouterLink, useNavigate } from 'react-router-dom';
// material-ui // material-ui
...@@ -8,21 +8,21 @@ import { ...@@ -8,21 +8,21 @@ import {
FormControl, FormControl,
FormHelperText, FormHelperText,
Grid, Grid,
Link,
InputAdornment, InputAdornment,
InputLabel, InputLabel,
Link,
OutlinedInput, OutlinedInput,
Stack, Stack,
Typography Typography
} from '@mui/material'; } from '@mui/material';
// third party // third party
import * as Yup from 'yup';
import { Formik } from 'formik'; import { Formik } from 'formik';
import * as Yup from 'yup';
// project import // project import
import IconButton from 'components/@extended/IconButton';
import AnimateButton from 'components/@extended/AnimateButton'; import AnimateButton from 'components/@extended/AnimateButton';
import IconButton from 'components/@extended/IconButton';
import useAuth from 'hooks/useAuth'; import useAuth from 'hooks/useAuth';
import useScriptRef from 'hooks/useScriptRef'; import useScriptRef from 'hooks/useScriptRef';
...@@ -34,25 +34,35 @@ import { strengthColor, strengthIndicator } from 'utils/password-strength'; ...@@ -34,25 +34,35 @@ import { strengthColor, strengthIndicator } from 'utils/password-strength';
import { StringColorProps } from 'types/password'; import { StringColorProps } from 'types/password';
// assets // assets
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
// ============================|| JWT - REGISTER ||============================ // // ============================|| JWT - REGISTER ||============================ //
const AuthRegister = () => { const AuthRegister = () => {
const { register } = useAuth(); const { registerUser } = useAuth();
const scriptedRef = useScriptRef(); const scriptedRef = useScriptRef();
const navigate = useNavigate(); const navigate = useNavigate();
const [level, setLevel] = useState<StringColorProps>(); const [level, setLevel] = useState<StringColorProps>();
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const handleClickShowPassword = () => { const handleClickShowPassword = () => {
setShowPassword(!showPassword); setShowPassword(!showPassword);
}; };
const handleClickShowConfirmPassword = () => {
setShowConfirmPassword(!showConfirmPassword);
};
const handleMouseDownPassword = (event: SyntheticEvent) => { const handleMouseDownPassword = (event: SyntheticEvent) => {
event.preventDefault(); event.preventDefault();
}; };
const handleMouseDownConfirmPassword = (event: SyntheticEvent) => {
event.preventDefault();
};
const changePassword = (value: string) => { const changePassword = (value: string) => {
const temp = strengthIndicator(value); const temp = strengthIndicator(value);
setLevel(strengthColor(temp)); setLevel(strengthColor(temp));
...@@ -62,26 +72,36 @@ const AuthRegister = () => { ...@@ -62,26 +72,36 @@ const AuthRegister = () => {
changePassword(''); changePassword('');
}, []); }, []);
const contactNumberPattern = /^(?:\+?94|0)(?:[1-9]\d{8})$/; // Sri Lankan contact number pattern
return ( return (
<> <>
<Formik <Formik
initialValues={{ initialValues={{
firstname: '', firstName: '',
lastname: '', lastName: '',
email: '', email: '',
company: '', contactNumber: '',
password: '', password: '',
confirmPassword: '',
submit: null submit: null
}} }}
validationSchema={Yup.object().shape({ validationSchema={Yup.object().shape({
firstname: Yup.string().max(255).required('First Name is required'), firstName: Yup.string().max(255).required('First Name is required'),
lastname: Yup.string().max(255).required('Last Name is required'), lastName: Yup.string().max(255).required('Last Name is required'),
email: Yup.string().email('Must be a valid email').max(255).required('Email is required'), email: Yup.string().email('Must be a valid email').max(255).required('Email is required'),
password: Yup.string().max(255).required('Password is required') password: Yup.string().max(255).required('Password is required'),
confirmPassword: Yup.string()
.oneOf([Yup.ref('password'), undefined], 'Passwords must match')
.max(255)
.required('Confirm Password is required'),
contactNumber: Yup.string()
.matches(contactNumberPattern, 'Invalid Sri Lankan contact number')
.required('Contact Number is required')
})} })}
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => { onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
try { try {
await register(values.email, values.password, values.firstname, values.lastname); await registerUser(values.email, values.password, values.firstName, values.lastName, values.contactNumber, values.confirmPassword);
if (scriptedRef.current) { if (scriptedRef.current) {
setStatus({ success: true }); setStatus({ success: true });
setSubmitting(false); setSubmitting(false);
...@@ -116,64 +136,64 @@ const AuthRegister = () => { ...@@ -116,64 +136,64 @@ const AuthRegister = () => {
<Grid container spacing={3}> <Grid container spacing={3}>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<Stack spacing={1}> <Stack spacing={1}>
<InputLabel htmlFor="firstname-signup">First Name*</InputLabel> <InputLabel htmlFor="firstName-signup">First Name*</InputLabel>
<OutlinedInput <OutlinedInput
id="firstname-login" id="firstName-login"
type="firstname" type="firstName"
value={values.firstname} value={values.firstName}
name="firstname" name="firstName"
onBlur={handleBlur} onBlur={handleBlur}
onChange={handleChange} onChange={handleChange}
placeholder="John" placeholder="John"
fullWidth fullWidth
error={Boolean(touched.firstname && errors.firstname)} error={Boolean(touched.firstName && errors.firstName)}
/> />
{touched.firstname && errors.firstname && ( {touched.firstName && errors.firstName && (
<FormHelperText error id="helper-text-firstname-signup"> <FormHelperText error id="helper-text-firstName-signup">
{errors.firstname} {errors.firstName}
</FormHelperText> </FormHelperText>
)} )}
</Stack> </Stack>
</Grid> </Grid>
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>
<Stack spacing={1}> <Stack spacing={1}>
<InputLabel htmlFor="lastname-signup">Last Name*</InputLabel> <InputLabel htmlFor="lastName-signup">Last Name*</InputLabel>
<OutlinedInput <OutlinedInput
fullWidth fullWidth
error={Boolean(touched.lastname && errors.lastname)} error={Boolean(touched.lastName && errors.lastName)}
id="lastname-signup" id="lastName-signup"
type="lastname" type="lastName"
value={values.lastname} value={values.lastName}
name="lastname" name="lastName"
onBlur={handleBlur} onBlur={handleBlur}
onChange={handleChange} onChange={handleChange}
placeholder="Doe" placeholder="Doe"
inputProps={{}} inputProps={{}}
/> />
{touched.lastname && errors.lastname && ( {touched.lastName && errors.lastName && (
<FormHelperText error id="helper-text-lastname-signup"> <FormHelperText error id="helper-text-lastName-signup">
{errors.lastname} {errors.lastName}
</FormHelperText> </FormHelperText>
)} )}
</Stack> </Stack>
</Grid> </Grid>
<Grid item xs={12}> <Grid item xs={12}>
<Stack spacing={1}> <Stack spacing={1}>
<InputLabel htmlFor="company-signup">Company</InputLabel> <InputLabel htmlFor="contactNumber-signup">Contact Number</InputLabel>
<OutlinedInput <OutlinedInput
fullWidth fullWidth
error={Boolean(touched.company && errors.company)} error={Boolean(touched.contactNumber && errors.contactNumber)}
id="company-signup" id="contactNumber-signup"
value={values.company} value={values.contactNumber}
name="company" name="contactNumber"
onBlur={handleBlur} onBlur={handleBlur}
onChange={handleChange} onChange={handleChange}
placeholder="Demo Inc." placeholder="+94 000 000 000 / 0000000000"
inputProps={{}} inputProps={{}}
/> />
{touched.company && errors.company && ( {touched.contactNumber && errors.contactNumber && (
<FormHelperText error id="helper-text-company-signup"> <FormHelperText error id="helper-text-contactNumber-signup">
{errors.company} {errors.contactNumber}
</FormHelperText> </FormHelperText>
)} )}
</Stack> </Stack>
...@@ -250,6 +270,43 @@ const AuthRegister = () => { ...@@ -250,6 +270,43 @@ const AuthRegister = () => {
</Grid> </Grid>
</FormControl> </FormControl>
</Grid> </Grid>
<Grid item xs={12}>
<Stack spacing={1}>
<InputLabel htmlFor="confirmPassword-signup">Confirm Password</InputLabel>
<OutlinedInput
fullWidth
error={Boolean(touched.confirmPassword && errors.confirmPassword)}
id="confirmPassword-signup"
type={showConfirmPassword ? 'text' : 'password'}
value={values.confirmPassword}
name="confirmPassword"
onBlur={handleBlur}
onChange={(e) => {
handleChange(e);
}}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle confirm Password visibility"
onClick={handleClickShowConfirmPassword}
onMouseDown={handleMouseDownConfirmPassword}
edge="end"
color="secondary"
>
{showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
</IconButton>
</InputAdornment>
}
placeholder="******"
inputProps={{}}
/>
{touched.confirmPassword && errors.confirmPassword && (
<FormHelperText error id="helper-text-confirmPassword-signup">
{errors.confirmPassword}
</FormHelperText>
)}
</Stack>
</Grid>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="body2"> <Typography variant="body2">
By Signing up, you agree to our &nbsp; By Signing up, you agree to our &nbsp;
......
...@@ -75,6 +75,7 @@ export type JWTContextType = { ...@@ -75,6 +75,7 @@ export type JWTContextType = {
logout: () => void; logout: () => void;
login: (email: string, password: string) => Promise<void>; login: (email: string, password: string) => Promise<void>;
register: (email: string, password: string, firstName: string, lastName: string) => Promise<void>; register: (email: string, password: string, firstName: string, lastName: string) => Promise<void>;
registerUser: (email: string, password: string, firstName: string, lastName: string, contactNumber: string, confirmPassword: string) => Promise<void>;
resetPassword: (email: string) => Promise<void>; resetPassword: (email: string) => Promise<void>;
updateProfile: VoidFunction; updateProfile: VoidFunction;
}; };
......
...@@ -2,7 +2,7 @@ import axios from 'axios'; ...@@ -2,7 +2,7 @@ import axios from 'axios';
const axiosServices_Mock = axios.create({ baseURL: process.env.REACT_APP_API_URL_MOCK || 'http://localhost:3010/' }); const axiosServices_Mock = axios.create({ baseURL: process.env.REACT_APP_API_URL_MOCK || 'http://localhost:3010/' });
const axiosServices = axios.create({ baseURL: process.env.REACT_APP_API_URL || 'http://localhost:3010/' }); const axiosServices = axios.create({ baseURL: process.env.REACT_APP_API_URL || 'http://localhost:5000/' });
// ==============================|| AXIOS - FOR MOCK SERVICES ||============================== // // ==============================|| AXIOS - FOR MOCK SERVICES ||============================== //
......
...@@ -154,5 +154,11 @@ ...@@ -154,5 +154,11 @@
"nutrition-list": "Nutrition List", "nutrition-list": "Nutrition List",
"parameter": "Parameter", "parameter": "Parameter",
"tutorial-management": "Tutorial Management", "tutorial-management": "Tutorial Management",
"curriculum-management": "Curriculum Management" "curriculum-management": "Curriculum Management",
"learning-management": "Learning Management",
"learning-list": "Learning List",
"learning-curriculums": "Course",
"learning-curriculums-subscribed": "My Courses",
"learning-lead-board": "Lead Board",
"learning-feedback": "Feedback"
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment