Profile Admin
This commit is contained in:
@@ -18,8 +18,8 @@ class AuthController extends Controller
|
||||
]);
|
||||
|
||||
$user = User::query()
|
||||
->where('email', $request->email)
|
||||
->first();
|
||||
->where('email', $request->email)
|
||||
->first();
|
||||
|
||||
if (!$user) {
|
||||
return response(['message' => 'User Tidak Ditemukan'], 404);
|
||||
@@ -43,4 +43,76 @@ class AuthController extends Controller
|
||||
|
||||
return response(['message' => 'Berhasil Logout.']);
|
||||
}
|
||||
|
||||
public function resetPassword(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
$request->validate([
|
||||
'old_password' => 'required',
|
||||
'new_password' => 'required',
|
||||
'confirm_new_password' => 'required'
|
||||
]);
|
||||
|
||||
if (!Hash::check($request['old_password'], $user->password)) {
|
||||
return response(['message' => 'Password Salah'], 403);
|
||||
}
|
||||
|
||||
if ($request["new_password"] != $request["confirm_new_password"]) {
|
||||
return response([
|
||||
'message' => "Password Tidak Sama"
|
||||
]);
|
||||
}
|
||||
|
||||
$user->update([
|
||||
'password' => Hash::make($request->confirm_new_password),
|
||||
]);
|
||||
return response()->json($user);
|
||||
}
|
||||
|
||||
public function verifyEmail(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required|email',
|
||||
]);
|
||||
|
||||
$user = User::query()
|
||||
->where('email', $request->email)
|
||||
->first();
|
||||
|
||||
if (!$user) {
|
||||
return response(['message' => 'User Tidak Ditemukan'], 404);
|
||||
}
|
||||
|
||||
return response()->json($user);
|
||||
}
|
||||
|
||||
public function forgetPassword(Request $request)
|
||||
{
|
||||
return $request->all();
|
||||
$request->validate([
|
||||
'email' => 'required|email',
|
||||
'new_password' => 'required',
|
||||
'confirm_new_password' => 'required'
|
||||
]);
|
||||
|
||||
$user = User::query()
|
||||
->where('email', $request->email)
|
||||
->first();
|
||||
|
||||
if (!$user) {
|
||||
return response(['message' => 'User Tidak Ditemukan'], 404);
|
||||
}
|
||||
|
||||
if ($request["new_password"] != $request["confirm_new_password"]) {
|
||||
return response([
|
||||
'message' => "Password Tidak Sama"
|
||||
]);
|
||||
}
|
||||
|
||||
$user->update([
|
||||
'password' => Hash::make($request->confirm_new_password),
|
||||
]);
|
||||
return response()->json($user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ Route::prefix('internal')->group(function () {
|
||||
Route::get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
});
|
||||
Route::put('reset-password', [AuthController::class, 'resetPassword'])->name('resetPassword');
|
||||
|
||||
|
||||
Route::resource('corporates', CorporateController::class);
|
||||
Route::put('corporates/{corporate_id}/activation', [CorporateController::class, 'activation']);
|
||||
|
||||
BIN
frontend/dashboard/public/image/overlay.png
Normal file
BIN
frontend/dashboard/public/image/overlay.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 473 KiB |
@@ -5,7 +5,7 @@ import { Box, Divider, Typography, Stack, MenuItem, Avatar } from '@mui/material
|
||||
// components
|
||||
import MenuPopover from '../../../components/MenuPopover';
|
||||
import { IconButtonAnimate } from '../../../components/animate';
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import useAuth from '../../../hooks/useAuth';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -17,7 +17,7 @@ const MENU_OPTIONS = [
|
||||
},
|
||||
{
|
||||
label: 'Profile',
|
||||
linkTo: '/',
|
||||
linkTo: '/profile',
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
@@ -43,7 +43,7 @@ export default function AccountPopover() {
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
navigate('/auth/login');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -97,7 +97,13 @@ export default function AccountPopover() {
|
||||
|
||||
<Stack sx={{ p: 1 }}>
|
||||
{MENU_OPTIONS.map((option) => (
|
||||
<MenuItem key={option.label} onClick={handleClose}>
|
||||
<MenuItem
|
||||
key={option.label}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
navigate(option.linkTo);
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
@@ -105,7 +111,9 @@ export default function AccountPopover() {
|
||||
|
||||
<Divider sx={{ borderStyle: 'dashed' }} />
|
||||
|
||||
<MenuItem sx={{ m: 1 }} onClick={handleLogout}>Logout</MenuItem>
|
||||
<MenuItem sx={{ m: 1 }} onClick={handleLogout}>
|
||||
Logout
|
||||
</MenuItem>
|
||||
</MenuPopover>
|
||||
</>
|
||||
);
|
||||
|
||||
347
frontend/dashboard/src/pages/Profile/FormPassword.tsx
Normal file
347
frontend/dashboard/src/pages/Profile/FormPassword.tsx
Normal file
@@ -0,0 +1,347 @@
|
||||
import * as Yup from 'yup';
|
||||
import { enqueueSnackbar, useSnackbar } from 'notistack';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
// @mui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Grid,
|
||||
Stack,
|
||||
Typography,
|
||||
Chip,
|
||||
Autocomplete,
|
||||
InputAdornment,
|
||||
IconButton,
|
||||
} from '@mui/material';
|
||||
|
||||
// components
|
||||
import { FormProvider, RHFTextField, RHFSwitch } from '../../components/hook-form';
|
||||
import axios from '../../utils/axios';
|
||||
import { JWTContextType } from '../../@types/auth';
|
||||
|
||||
// @mui
|
||||
import { LinearProgress, linearProgressClasses, FormControlLabel } from '@mui/material';
|
||||
import Checkbox from '@mui/material/Checkbox';
|
||||
// components
|
||||
import MuiDialog from '../../components/MuiDialog';
|
||||
// React
|
||||
import { ReactElement } from 'react';
|
||||
import { Users } from '../../@types/user';
|
||||
import Iconify from '../../components/Iconify';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const HeaderStyle = styled('header')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: theme.spacing(2),
|
||||
justifyContent: 'space-between',
|
||||
}));
|
||||
|
||||
const LabelStyle = styled(Typography)(({ theme }) => ({
|
||||
...theme.typography.h6,
|
||||
marginBottom: theme.spacing(2),
|
||||
marginTop: theme.spacing(2),
|
||||
}));
|
||||
type DataContent = {
|
||||
info: string;
|
||||
date: string;
|
||||
time: string;
|
||||
};
|
||||
|
||||
type MuiDialogProps = {
|
||||
title?: {
|
||||
name?: string;
|
||||
icon?: string;
|
||||
};
|
||||
openDialog: boolean;
|
||||
setOpenDialog: Function;
|
||||
content?: ReactElement;
|
||||
data?: DataContent[];
|
||||
};
|
||||
|
||||
type FormValuesProps = {
|
||||
value: string;
|
||||
active: boolean;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const DialogFormPassword = ({ title, openDialog, setOpenDialog, data }: MuiDialogProps) => {
|
||||
const [isDisabledCheckbox, setIsDisabledCheckbox] = useState(false);
|
||||
const [isDisabledButton, setIsDisabledButton] = useState(true);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const id = data;
|
||||
|
||||
const isEdit = id ? true : false;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||
// const [currentUsers, setCurrentUsers] = useState<JWTContextType>();
|
||||
const [currentUsers, setCurrentUsers] = useState<Users>();
|
||||
console.log('usernya masuk', currentUsers);
|
||||
useEffect(() => {
|
||||
if (isEdit) {
|
||||
axios.get('/user/' + id).then((res) => {
|
||||
setCurrentUsers(res.data);
|
||||
});
|
||||
}
|
||||
}, [id]);
|
||||
|
||||
const Title = styled(Typography)(({ theme }) => ({
|
||||
...theme.typography.h4,
|
||||
boxShadow: 'none',
|
||||
fontWeight: 700,
|
||||
color: '#005B7F',
|
||||
}));
|
||||
|
||||
console.log('currentUsers', currentUsers);
|
||||
|
||||
console.log('data Id masuk', data);
|
||||
|
||||
// const NewCorporateSchema = Yup.object().shape({
|
||||
// active: Yup.boolean().required('Corporate Status is required'),
|
||||
// // file: Yup.boolean().required('Corporate Status is required'),
|
||||
// });
|
||||
|
||||
// const defaultValues = useMemo(
|
||||
// () => ({
|
||||
// id: currentUsers?.id || '',
|
||||
// name: currentUsers?.name || '',
|
||||
// value: currentUsers?.value || '',
|
||||
// active: currentUsers?.active === 1 ? true : false,
|
||||
// }),
|
||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// [currentUsers]
|
||||
// );
|
||||
|
||||
interface FormValuesProps extends Partial<Banner> {
|
||||
taxes: boolean;
|
||||
inStock: boolean;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
isEdit: boolean;
|
||||
currentBanners?: Banner;
|
||||
};
|
||||
|
||||
// const profileSchema = Yup.object().shape({
|
||||
// // password: Yup.string().required('katasandilama is required'),
|
||||
// // katasandibaru: Yup.string().required('katasandibaru is required'),
|
||||
// // konfirmasikatasandi: Yup.string().required('konfirmasikatasandi is required'),
|
||||
// });
|
||||
|
||||
// const defaultValues = useMemo(
|
||||
// () => ({
|
||||
// new_password: currentUsers?.new_password,
|
||||
// password2: currentUsers?.password2,
|
||||
// }),
|
||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// [currentUsers]
|
||||
// );
|
||||
|
||||
const methods = useForm<FormValuesProps>({
|
||||
// resolver: yupResolver(profileSchema),
|
||||
// defaultValues,
|
||||
});
|
||||
|
||||
// console.log('defaultValues', defaultValues);
|
||||
const {
|
||||
reset,
|
||||
watch,
|
||||
control,
|
||||
setValue,
|
||||
setError,
|
||||
getValues,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting },
|
||||
} = methods;
|
||||
|
||||
const values = watch();
|
||||
|
||||
// useEffect(() => {
|
||||
// if (isEdit && currentUsers) {
|
||||
// reset(defaultValues);
|
||||
// }
|
||||
// if (!isEdit) {
|
||||
// reset(defaultValues);
|
||||
// }
|
||||
|
||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// }, [isEdit, currentUsers]);
|
||||
|
||||
useEffect(() => {
|
||||
if (openDialog === false) {
|
||||
reset();
|
||||
}
|
||||
}, [openDialog, reset]);
|
||||
|
||||
const onSubmit = async (data: FormValuesProps) => {
|
||||
console.log('data', data);
|
||||
// const formData = new FormData();
|
||||
// formData.append('password', password);
|
||||
// formData.append('passworrd')
|
||||
|
||||
try {
|
||||
if (!isEdit) {
|
||||
const response = await axios.post('/reset-password', data);
|
||||
} else {
|
||||
const response = await axios.put('/reset-password/', data);
|
||||
}
|
||||
|
||||
reset();
|
||||
enqueueSnackbar(
|
||||
!isEdit ? 'Password Created Successfully!' : 'Password Updated Successfully!',
|
||||
{
|
||||
variant: 'success',
|
||||
}
|
||||
);
|
||||
|
||||
setOpenDialog(false);
|
||||
// navigate(0);
|
||||
|
||||
// window.location.reload();
|
||||
// navigate('/general/bantuan/contact', { replace: true });
|
||||
} catch (error: any) {
|
||||
if (error && error.response.status === 422) {
|
||||
for (const [key, value] of Object.entries(error.response.data.errors)) {
|
||||
setError(key, { message: value[0] });
|
||||
enqueueSnackbar(value[0] ?? 'Failed Processing Request', { variant: 'error' });
|
||||
}
|
||||
} else {
|
||||
enqueueSnackbar(error.message ?? 'Failed Processing Request', { variant: 'error' });
|
||||
}
|
||||
}
|
||||
|
||||
const ascent = document?.querySelector('ascent');
|
||||
if (ascent != null) {
|
||||
ascent.innerHTML = '';
|
||||
}
|
||||
};
|
||||
|
||||
const [showPasswordOld, setShowPasswordOld] = useState(false);
|
||||
const [showPasswordNew, setShowPasswordNew] = useState(false);
|
||||
const [showPasswordConfirmNew, setShowPasswordConfirmNew] = useState(false);
|
||||
|
||||
const getContent = () => (
|
||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||
<HeaderStyle>
|
||||
<Title>Ubah Kata Sandi</Title>
|
||||
</HeaderStyle>
|
||||
<Stack spacing={3}>
|
||||
<Box sx={{ width: '100%', typography: 'body1', p: 2 }}>
|
||||
<Grid item xs={12}>
|
||||
<LabelStyle>Kata Sandi Lama </LabelStyle>
|
||||
<RHFTextField
|
||||
name="old_password"
|
||||
label="Kata Sandi Lama"
|
||||
type={showPasswordOld ? 'text' : 'password'}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton onClick={() => setShowPasswordOld(!showPasswordOld)} edge="end">
|
||||
<Iconify icon={showPasswordOld ? 'eva:eye-fill' : 'eva:eye-off-fill'} />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<LabelStyle>Kata Sandi Baru </LabelStyle>
|
||||
<RHFTextField
|
||||
name="new_password"
|
||||
label="Kata Sandi Baru"
|
||||
type={showPasswordNew ? 'text' : 'password'}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton onClick={() => setShowPasswordNew(!showPasswordNew)} edge="end">
|
||||
<Iconify icon={showPasswordNew ? 'eva:eye-fill' : 'eva:eye-off-fill'} />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<LabelStyle>Konfirmasi Kata Sandi </LabelStyle>
|
||||
<RHFTextField
|
||||
name="confirm_new_password"
|
||||
label="Konfirmasi Kata Sandi"
|
||||
type={showPasswordConfirmNew ? 'text' : 'password'}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
onClick={() => setShowPasswordConfirmNew(!showPasswordConfirmNew)}
|
||||
edge="end"
|
||||
>
|
||||
<Iconify
|
||||
icon={showPasswordConfirmNew ? 'eva:eye-fill' : 'eva:eye-off-fill'}
|
||||
/>
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Box sx={{ width: '100%', pt: 5 }}>
|
||||
<Stack
|
||||
alignItems="center"
|
||||
justifyContent="end"
|
||||
direction={{ xs: 'column', md: 'row' }}
|
||||
// sx={{ textAlign: { xs: 'center', md: 'left' } }}
|
||||
>
|
||||
<Stack direction="row" spacing={1}>
|
||||
<Button
|
||||
sx={{
|
||||
boxShadow: 'none',
|
||||
}}
|
||||
variant="outlined"
|
||||
size="medium"
|
||||
fullWidth={true}
|
||||
onClick={() => setOpenDialog(false)}
|
||||
>
|
||||
Batal
|
||||
</Button>
|
||||
<LoadingButton
|
||||
sx={{ boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)' }}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
size="medium"
|
||||
fullWidth={true}
|
||||
loading={isSubmitting}
|
||||
>
|
||||
{!isEdit ? 'Simpan' : 'Simpan'}
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</FormProvider>
|
||||
);
|
||||
|
||||
return (
|
||||
<MuiDialog
|
||||
title={title}
|
||||
openDialog={openDialog}
|
||||
setOpenDialog={setOpenDialog}
|
||||
content={getContent()}
|
||||
maxWidth="sm"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DialogFormPassword;
|
||||
379
frontend/dashboard/src/pages/Profile/Index.tsx
Normal file
379
frontend/dashboard/src/pages/Profile/Index.tsx
Normal file
@@ -0,0 +1,379 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Collapse,
|
||||
IconButton,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
OutlinedInput,
|
||||
Paper,
|
||||
Select,
|
||||
SelectChangeEvent,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TextField,
|
||||
Typography,
|
||||
Badge,
|
||||
Tab,
|
||||
Tabs,
|
||||
CardHeader,
|
||||
Stack,
|
||||
Menu,
|
||||
ButtonGroup,
|
||||
Pagination,
|
||||
Grid,
|
||||
Chip,
|
||||
styled,
|
||||
DialogTitle,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogActions,
|
||||
Switch,
|
||||
Avatar,
|
||||
MenuItemClasses,
|
||||
} from '@mui/material';
|
||||
import * as Yup from 'yup';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
|
||||
import {
|
||||
Link,
|
||||
NavLink as RouterLink,
|
||||
useSearchParams,
|
||||
useNavigate,
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
// hooks
|
||||
import React, { ChangeEvent, Component, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
// components
|
||||
import axios from '../../utils/axios';
|
||||
import { LaravelPaginatedData } from '../../@types/paginated-data';
|
||||
import { Icd } from '../../@types/diagnosis';
|
||||
import BasePagination from '../../components/BasePagination';
|
||||
import { Users } from '../../@types/user';
|
||||
import CreateIcon from '@mui/icons-material/Create';
|
||||
import { Props } from '../../components/editor/index';
|
||||
import { red } from '@mui/material/colors';
|
||||
import { borderRadius, margin, padding } from '@mui/system';
|
||||
|
||||
import FormPassword from './FormPassword';
|
||||
import OrganizationsForm from './FormPassword';
|
||||
import DialogTopUpLimit from './DialogTopUpLimit';
|
||||
import { number } from 'yup/lib/locale';
|
||||
import AccountBoxIcon from '@mui/icons-material/AccountBox';
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
import BadgeIcon from '@mui/icons-material/Badge';
|
||||
import CallIcon from '@mui/icons-material/Call';
|
||||
import MailIcon from '@mui/icons-material/Mail';
|
||||
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import KeyIcon from '@mui/icons-material/Key';
|
||||
import useAuth from '../../hooks/useAuth';
|
||||
import LogoutTwoToneIcon from '@mui/icons-material/LogoutTwoTone';
|
||||
|
||||
export default function List() {
|
||||
// Generate the every row of the table
|
||||
const HeaderStyle = styled('header')(({ theme }) => ({
|
||||
padding: theme.spacing(5),
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}));
|
||||
|
||||
const Name = styled(Typography)(({ theme }) => ({
|
||||
...theme.typography.h3,
|
||||
marginBottom: theme.spacing(1),
|
||||
marginTop: theme.spacing(2),
|
||||
color: '#005B7F',
|
||||
}));
|
||||
|
||||
const LabelStyle = styled(Typography)(({ theme }) => ({
|
||||
...theme.typography.h6,
|
||||
marginBottom: theme.spacing(2),
|
||||
marginTop: theme.spacing(2),
|
||||
color: '#005B7F',
|
||||
}));
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { organization_id } = useParams();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [importResult, setImportResult] = useState(null);
|
||||
|
||||
const { id } = useParams();
|
||||
const isEdit = id ? true : false;
|
||||
|
||||
const Item = styled(Paper)(({ theme }) => ({
|
||||
textAlign: 'left',
|
||||
}));
|
||||
|
||||
const ButtonStyle = {
|
||||
color: '#005B7F',
|
||||
backgroundColor: '#FFFFFF',
|
||||
boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)',
|
||||
borderRadius: '8px',
|
||||
flex: 1,
|
||||
marginRight: 3,
|
||||
padding: '13px',
|
||||
border: '2px solid #005B7F',
|
||||
fontSize: '15px',
|
||||
lineHeight: '16px',
|
||||
textTransform: 'none',
|
||||
'&:hover': {
|
||||
backgroundColor: '#005B7F',
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
};
|
||||
|
||||
const ButtonStyle2 = {
|
||||
color: '#CB3A31',
|
||||
flex: 1,
|
||||
marginRight: 3,
|
||||
padding: '13px',
|
||||
fontSize: '15px',
|
||||
lineHeight: '16px',
|
||||
textTransform: 'none',
|
||||
'&:hover': {
|
||||
backgroundColor: '#DFE2E1',
|
||||
},
|
||||
};
|
||||
|
||||
function createData(Users: Users): Users {
|
||||
return {
|
||||
...Users,
|
||||
};
|
||||
}
|
||||
|
||||
const headStyle = {
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
|
||||
function DataUsers() {
|
||||
const [user, setUser] = useState([]);
|
||||
useEffect(() => {
|
||||
axios.get('/user').then((response) => {
|
||||
setUser(response.data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const defaultValues = useMemo(
|
||||
() => ({
|
||||
id: user?.id,
|
||||
email: user?.email,
|
||||
}),
|
||||
[user]
|
||||
);
|
||||
|
||||
console.log('user', user);
|
||||
return (
|
||||
<div>
|
||||
<Typography variant="h3" sx={{ mb: 5 }}>
|
||||
Profile
|
||||
</Typography>
|
||||
<Box position="relative" mb={5}>
|
||||
<Box
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
position="relative"
|
||||
minHeight="18.75rem"
|
||||
borderRadius="xl"
|
||||
sx={{
|
||||
borderRadius: '20px',
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src="/image/overlay.png"
|
||||
alt="overlay"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{ borderTopLeftRadius: '20px', borderTopRightRadius: '20px' }}
|
||||
/>
|
||||
</Box>
|
||||
<Card
|
||||
sx={{
|
||||
position: 'relative',
|
||||
mt: -8,
|
||||
mx: 3,
|
||||
py: 2,
|
||||
px: 2,
|
||||
}}
|
||||
>
|
||||
<Grid container spacing={3} alignItems="center" sx={{ p: 3 }}>
|
||||
<Grid item>
|
||||
<Avatar
|
||||
src="https://minimal-assets-api.vercel.app/assets/images/avatars/avatar_5.jpg"
|
||||
alt="Rayan Moran"
|
||||
sx={{ width: 100, height: 100, ml: '4%' }}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Box height="100%" mt={0.5} lineHeight={1} sx={{ ml: 5 }}>
|
||||
<Typography variant="h4" fontWeight="700">
|
||||
Rayan Moran
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color="text.secondary">
|
||||
Super Admin
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6} lg={4} sx={{ ml: 'auto' }}></Grid>
|
||||
</Grid>
|
||||
</Card>
|
||||
</Box>
|
||||
<Stack spacing={3}>
|
||||
<Card sx={{ p: 3 }}>
|
||||
<Grid sx={{ mt: 5, ml: 5, mb: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
pb: 2,
|
||||
borderBottom: '5px solid',
|
||||
}}
|
||||
>
|
||||
<Stack spacing={2} justifyContent="center" alignItems="center" direction="row">
|
||||
<AccountBoxIcon />
|
||||
<Typography variant="h4" sx={{ ml: 1 }}>
|
||||
Profil
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Box sx={{ p: 5 }}>
|
||||
<Grid>
|
||||
<Grid item xs={12} md={12}>
|
||||
<LabelStyle>
|
||||
<PersonIcon /> ID
|
||||
</LabelStyle>
|
||||
<Title>{user?.id ? user?.id : '-'}</Title>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={12}>
|
||||
<LabelStyle>
|
||||
<BadgeIcon /> Nama
|
||||
</LabelStyle>
|
||||
<Title>Perdi</Title>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={12}>
|
||||
<LabelStyle>
|
||||
<CallIcon /> Telepon
|
||||
</LabelStyle>
|
||||
<Title>2131231231</Title>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={12}>
|
||||
<LabelStyle>
|
||||
<MailIcon /> Email
|
||||
</LabelStyle>
|
||||
<Title>{user?.email ? user?.email : '-'}</Title>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Card>
|
||||
|
||||
<Card sx={{ p: 3 }}>
|
||||
<Grid sx={{ mt: 5, ml: 5, mb: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
pb: 2,
|
||||
borderBottom: '5px solid',
|
||||
}}
|
||||
>
|
||||
<Stack spacing={2} justifyContent="center" alignItems="center" direction="row">
|
||||
<LockIcon />
|
||||
<Typography variant="h4" sx={{ ml: 1 }}>
|
||||
Keamanan
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Box sx={{ p: 5 }}>
|
||||
<Grid item xs={12} md={12}>
|
||||
<div style={{ display: 'flex', justifyContent: 'Center' }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={ButtonStyle}
|
||||
startIcon={<KeyIcon />}
|
||||
onClick={() => {
|
||||
clickHandler('edit');
|
||||
setEdit(user.id);
|
||||
}}
|
||||
>
|
||||
Ubah Kata Sandi
|
||||
</Button>
|
||||
</div>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Card>
|
||||
<div style={{ display: 'flex', justifyContent: 'Center', color: '#CB3A31' }}>
|
||||
<MenuItem sx={{ m: 5 }} onClick={handleLogout}>
|
||||
<LogoutTwoToneIcon /> Logout
|
||||
</MenuItem>
|
||||
</div>
|
||||
{/* </Box>
|
||||
</React.Fragment> */}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Title = styled(Typography)(({ theme }) => ({
|
||||
boxShadow: 'none',
|
||||
// paddingBottom: theme.spacing(3),
|
||||
fontWeight: 700,
|
||||
color: '#000000',
|
||||
}));
|
||||
|
||||
const TitleRole = styled(Typography)(({ theme }) => ({
|
||||
...theme.typography.h5,
|
||||
boxShadow: 'none',
|
||||
fontWeight: 500,
|
||||
color: '#000000',
|
||||
}));
|
||||
|
||||
const [openDialog, setOpenDialog] = useState(false);
|
||||
const [dialogTitle, setDialogTitle] = useState('');
|
||||
const [isDialog, setIsDialog] = useState('');
|
||||
const [edit, setEdit] = useState(number);
|
||||
const clickHandler = (isDialog: string) => {
|
||||
switch (isDialog) {
|
||||
case 'edit':
|
||||
setIsDialog(isDialog);
|
||||
setOpenDialog(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const { logout } = useAuth();
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
navigate('/auth/login');
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Card sx={{ marginTop: '30px', p: 5, boxShadow: 'none' }}>
|
||||
{/* <Row /> */}
|
||||
<DataUsers />
|
||||
{/* {dataTableData.map((row) => (
|
||||
<Row key={row.id} row={row} />
|
||||
))} */}
|
||||
</Card>
|
||||
|
||||
{isDialog === 'edit' && (
|
||||
<FormPassword
|
||||
data={edit}
|
||||
openDialog={openDialog}
|
||||
setOpenDialog={setOpenDialog}
|
||||
title={{ name: dialogTitle, icon: 'heroicons-solid:cash' }}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export default function ResetPassword() {
|
||||
size="large"
|
||||
component={RouterLink}
|
||||
to={PATH_AUTH.login}
|
||||
sx={{ mt: 1 }}
|
||||
sx={{ mt: 3 }}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
|
||||
@@ -8,7 +8,6 @@ import LoadingScreen from '../components/LoadingScreen';
|
||||
import GuestGuard from '../guards/GuestGuard';
|
||||
import { RegisterForm } from '../sections/auth/register';
|
||||
import Register from '../pages/auth/Register';
|
||||
import ResetPassword from '../pages/auth/ResetPassword';
|
||||
import VerifyCode from '../pages/auth/VerifyCode';
|
||||
import { AuthProvider } from '../contexts/LaravelAuthContext';
|
||||
import AuthGuard from '../guards/AuthGuard';
|
||||
@@ -53,7 +52,7 @@ export default function Router() {
|
||||
},
|
||||
// { path: 'login-unprotected', element: <Login /> },
|
||||
// { path: 'register-unprotected', element: <Register /> },
|
||||
// { path: 'reset-password', element: <ResetPassword /> },
|
||||
{ path: 'reset-password', element: <ResetPassword /> },
|
||||
// { path: 'verify', element: <VerifyCode /> },
|
||||
],
|
||||
},
|
||||
@@ -229,6 +228,10 @@ export default function Router() {
|
||||
path: 'claims/:id',
|
||||
element: <ClaimsCreate />,
|
||||
},
|
||||
{
|
||||
path: 'profile',
|
||||
element: <Profile />,
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
@@ -265,6 +268,7 @@ export default function Router() {
|
||||
}
|
||||
|
||||
const Login = Loadable(lazy(() => import('../pages/auth/Login')));
|
||||
const ResetPassword = Loadable(lazy(() => import('../pages/auth/ResetPassword')));
|
||||
|
||||
// Dashboard
|
||||
const Dashboard = Loadable(lazy(() => import('../pages/Dashboard')));
|
||||
@@ -329,5 +333,7 @@ const CorporateClaimHistories = Loadable(
|
||||
lazy(() => import('../pages/Corporates/ClaimHistory/Index'))
|
||||
);
|
||||
|
||||
const Profile = Loadable(lazy(() => import('../pages/Profile/Index')));
|
||||
|
||||
const Claims = Loadable(lazy(() => import('../pages/Claims/Index')));
|
||||
const ClaimsCreate = Loadable(lazy(() => import('../pages/Claims/CreateUpdate')));
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function LoginForm() {
|
||||
resolver: yupResolver(LoginSchema),
|
||||
defaultValues,
|
||||
});
|
||||
|
||||
|
||||
const {
|
||||
reset,
|
||||
setError,
|
||||
@@ -58,8 +58,8 @@ export default function LoginForm() {
|
||||
|
||||
const onSubmit = async (data: FormValuesProps) => {
|
||||
try {
|
||||
const loginResult = await login(data.email, data.password );
|
||||
|
||||
const loginResult = await login(data.email, data.password);
|
||||
|
||||
navigate('/dashboard');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -75,7 +75,7 @@ export default function LoginForm() {
|
||||
return (
|
||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Stack spacing={3}>
|
||||
<Alert severity='info'>Email : admin@linksehat.dev & Password : password</Alert>
|
||||
<Alert severity="info">Email : admin@linksehat.dev & Password : password</Alert>
|
||||
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
|
||||
|
||||
<RHFTextField name="email" label="Email address" />
|
||||
|
||||
@@ -3,17 +3,19 @@ import * as Yup from 'yup';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useForm } from 'react-hook-form';
|
||||
// @mui
|
||||
import { Stack } from '@mui/material';
|
||||
import { Alert, Stack } from '@mui/material';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
// hooks
|
||||
import useIsMountedRef from '../../../hooks/useIsMountedRef';
|
||||
// components
|
||||
import { FormProvider, RHFTextField } from '../../../components/hook-form';
|
||||
import axios from '../../../utils/axios';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type FormValuesProps = {
|
||||
email: string;
|
||||
afterSubmit?: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
@@ -35,24 +37,33 @@ export default function ResetPasswordForm({ onSent, onGetEmail }: Props) {
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
formState: { isSubmitting },
|
||||
setError,
|
||||
formState: { errors, isSubmitting },
|
||||
} = methods;
|
||||
|
||||
const onSubmit = async (data: FormValuesProps) => {
|
||||
try {
|
||||
await axios.post('/verify-email', data);
|
||||
console.log(data);
|
||||
|
||||
// await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
if (isMountedRef.current) {
|
||||
onSent();
|
||||
onGetEmail(data.email);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.log(error.response.data);
|
||||
if (isMountedRef.current) {
|
||||
setError('afterSubmit', { ...error, message: error.response.data.message });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Stack spacing={3}>
|
||||
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
|
||||
<RHFTextField name="email" label="Email address" />
|
||||
|
||||
<LoadingButton
|
||||
|
||||
Reference in New Issue
Block a user