Skip to content

Commit

Permalink
feature #25 added admin user flow
Browse files Browse the repository at this point in the history
- added admin user search page
- added admin user edit page
- added admin user create page
- added missing endpoints to UserAPI

closes #25
  • Loading branch information
sifes committed Jan 25, 2024
1 parent d6e1f8c commit 16a4f04
Show file tree
Hide file tree
Showing 29 changed files with 915 additions and 15 deletions.
3 changes: 2 additions & 1 deletion fictadvisor-web/src/app/admin/users/create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';

import AdminPanelLayout from '@/components/common/layout/admin-panel-layout/AdminPanelLayout';
import CreateUserPage from '@/components/pages/admin/admin-user/create-user-page';

const Create = () => {
return (
<AdminPanelLayout>
<div></div>
<CreateUserPage />
</AdminPanelLayout>
);
};
Expand Down
21 changes: 17 additions & 4 deletions fictadvisor-web/src/app/admin/users/edit/[userId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import React from 'react';
'use client';
import React, { FC } from 'react';
import { useQuery } from 'react-query';

import AdminPanelLayout from '@/components/common/layout/admin-panel-layout/AdminPanelLayout';
import EditUserPage from '@/components/pages/admin/admin-user/edit-user-page';
import UserAPI from '@/lib/api/user/UserAPI';

const UserId = () => {
interface AdminUserEditProps {
params: {
userId: string;
};
}

const AdminUserEdit: FC<AdminUserEditProps> = ({ params }) => {
const { data: user, isSuccess } = useQuery('getUser', () =>
UserAPI.getUser(params.userId),
);
return (
<AdminPanelLayout>
<div></div>
{isSuccess && <EditUserPage user={user}></EditUserPage>}
</AdminPanelLayout>
);
};

export default UserId;
export default AdminUserEdit;
3 changes: 2 additions & 1 deletion fictadvisor-web/src/app/admin/users/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';

import AdminPanelLayout from '@/components/common/layout/admin-panel-layout/AdminPanelLayout';
import SearchUserPage from '@/components/pages/admin/admin-user/search-user-page';

const Page = () => {
return (
<AdminPanelLayout>
<div></div>
<SearchUserPage></SearchUserPage>
</AdminPanelLayout>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DropDownOption } from '@/components/common/ui/form/dropdown/types';
import { UserGroupState } from '@/types/user';

export const UserStateOptions: DropDownOption[] = [
{ id: UserGroupState.APPROVED, label: 'Верифікований' },
{ id: UserGroupState.DECLINED, label: 'Не верифікований' },
{ id: UserGroupState.PENDING, label: 'В очікуванні' },
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { SxProps, Theme } from '@mui/material/styles';

export const header: SxProps<Theme> = {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '16px',
};

export const button: SxProps<Theme> = {
borderRadius: '8px',
};

export const title: SxProps<Theme> = {
borderBottom: '1px solid',
borderColor: 'backgroundDark.400',
padding: '16px',
width: '50%',
};

export const input: SxProps<Theme> = {
width: '40%',
borderRadius: '8px',
padding: '0px 16px',
};

export const body: SxProps<Theme> = {
display: 'flex',
gap: '36px',
padding: '24px 16px',
};

export const inputsWrapper: SxProps<Theme> = {
width: '100%',
maxWidth: '308px',
display: 'flex',
flexDirection: 'column',
gap: '18px',
};

export const avatar: SxProps<Theme> = {
width: '160px',
height: '160px',
borderRadius: '100%',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
'use client';
import React, { FC, useState } from 'react';
import { Avatar, Box, CardHeader, Stack } from '@mui/material';
import { isAxiosError } from 'axios';
import { useRouter } from 'next/navigation';

import Button from '@/components/common/ui/button-mui';
import {
ButtonColor,
ButtonSize,
} from '@/components/common/ui/button-mui/types';
import { Dropdown, InputSize, InputType } from '@/components/common/ui/form';
import { FieldSize } from '@/components/common/ui/form/common/types';
import Input from '@/components/common/ui/form/input-mui';
import useToast from '@/hooks/use-toast';
import { useToastError } from '@/hooks/use-toast-error/useToastError';
import UserAPI from '@/lib/api/user/UserAPI';
import { UserGroupState } from '@/types/user';

import { UserStateOptions } from '../constants/UserStateOptions';

import * as styles from './CreateUserPage.styles';

const CreateUserPage: FC = () => {
const [username, setUsername] = useState<string>('');
const [email, setEmail] = useState<string>('');
const [userState, setUserState] = useState<UserGroupState>(
'' as UserGroupState,
);
const toast = useToast();
const toastError = useToastError();
const router = useRouter();

const handleUserCreation = async () => {
try {
await UserAPI.create({ username, email, state: userState });
toast.success('Користувач успішно створений!', '', 4000);
router.replace('/admin/users');
} catch (e) {
if (isAxiosError(e)) {
toastError.displayError(e.response?.data.message);
}
}
};

return (
<>
<Box sx={styles.header}>
<CardHeader title="Створення користувача" sx={styles.title} />
<Stack flexDirection="row" gap="8px">
<Button
size={ButtonSize.MEDIUM}
text="Скасувати"
color={ButtonColor.SECONDARY}
href="/admin/users"
sx={styles.button}
/>
<Button
size={ButtonSize.MEDIUM}
text="Зберегти"
onClick={() => handleUserCreation()}
sx={styles.button}
/>
</Stack>
</Box>
<Box sx={styles.body}>
<Box sx={styles.inputsWrapper}>
<Input
value={username}
onChange={setUsername}
size={InputSize.MEDIUM}
type={InputType.DEFAULT}
showRemark={false}
label="Username"
/>
<Input
value={email}
onChange={setEmail}
size={InputSize.MEDIUM}
type={InputType.DEFAULT}
showRemark={false}
label="Пошта"
/>
<Dropdown
disableClearable
placeholder="Стан користувача"
size={FieldSize.MEDIUM}
options={UserStateOptions}
showRemark={false}
onChange={(value: string) => setUserState(value as UserGroupState)}
value={userState}
label="Стан користувача"
/>
</Box>
<Box>
<Avatar
src={'/frog-avatar.png'}
alt="картинка користувача"
sx={styles.avatar}
/>
</Box>
</Box>
</>
);
};

export default CreateUserPage;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './CreateUserPage';
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { SxProps, Theme } from '@mui/material/styles';

export const header: SxProps<Theme> = {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '16px',
};

export const title: SxProps<Theme> = {
borderBottom: '1px solid',
borderColor: 'backgroundDark.400',
padding: '16px',
width: '50%',
'& .MuiCardHeader-subheader': {
typography: 'body1',
color: 'grey.500',
},
};

export const button: SxProps<Theme> = {
borderRadius: '8px',
};

export const body: SxProps<Theme> = {
display: 'flex',
gap: '36px',
padding: '24px 16px',
};

export const inputsWrapper: SxProps<Theme> = {
width: '100%',
maxWidth: '308px',
display: 'flex',
flexDirection: 'column',
gap: '18px',
};

export const avatar: SxProps<Theme> = {
width: '160px',
height: '160px',
borderRadius: '100%',
};
Loading

0 comments on commit 16a4f04

Please sign in to comment.