Skip to content

Commit

Permalink
added change and delete buttons to student page +
Browse files Browse the repository at this point in the history
page for changing student name +
fixes in common components
  • Loading branch information
zavarin-michael committed Mar 9, 2024
1 parent f93689d commit 9563762
Show file tree
Hide file tree
Showing 15 changed files with 271 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
}

.deleteButton {
width: 160px;
width: auto;
padding: 7px;
}
}
1 change: 1 addition & 0 deletions apps/schools/domains/organization/redux/organizationApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const organizationApi = commonApi.injectEndpoints({
url: `/organization-management/organizations/students/${data.student_id}`,
method: 'GET',
}),
providesTags: (result, error, arg) => [{ type: 'Student', id: arg.student_id }],
}),
getTeacher: build.query<{ teacher: GetTeacher }, TeacherData>({
query: (data) => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const STUDENT_NAME = 'student_name'
21 changes: 21 additions & 0 deletions apps/schools/domains/student/components/changeStudentForm/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useMemo } from 'react'
import { ValidatorsMap } from '@domains/common/redux/interfaces'
import { PleaseInputStudentNameMsg } from '@domains/user/components/auth/constants/message'
import { getGreaterValidator } from '@domains/common/utils/validators'
import { STUDENT_NAME } from '@domains/student/components/changeStudentForm/constants'

export const useChangeStudentFormValidators = () => {
return useMemo<ValidatorsMap>(() => {
return {
[STUDENT_NAME]: [
{
required: false,
message: PleaseInputStudentNameMsg,
whitespace: true,
type: 'string',
},
getGreaterValidator(200),
],
}
}, [this])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { useEffect, useState } from 'react'
import router from 'next/router'
import { Col, Form, Row, Spin, Typography } from 'antd'
import { Button } from '@domains/common/components/button'
import styles from './styles/styles.module.scss'
import Image from 'next/image'
import duckEmptyPage from '@public/image/duckEmptyPage.svg'

import { isValidFormCheck } from '@domains/common/utils/form'
import { Input } from '@domains/common/components/input'

import { useGetStudentQuery } from '@domains/organization/redux/organizationApi'
import { STUDENT_NAME } from '../createStudentForm/constants'
import { getUuidFromUrl } from '@domains/common/utils/getUuidFromUrl'
import { handleSubmitForm } from '@domains/student/handlers/studentPatch'
import { useUpdateStudentByIdMutation } from '@domains/student/redux/studentApi'
import { useChangeStudentFormValidators } from '@domains/student/components/changeStudentForm/hooks'
import { ErrorType } from '@store/commonApi'

export function ChangeStudentForm() {
const uuid = getUuidFromUrl()
const { data: student, error: studentError, isFetching } = useGetStudentQuery({ student_id: uuid[0] })
const [form] = Form.useForm()
const [isFormValid, setIsFormValid] = useState(false)
const validators = useChangeStudentFormValidators()
const [mutation] = useUpdateStudentByIdMutation()

const initialValues = {
[STUDENT_NAME]: student?.student.name ?? '',
}

useEffect(() => {
if (studentError && (studentError as ErrorType).status == 404) {
router.push('/student')
}
}, [studentError])

if (uuid.length === 0) router.push('/404')

const validationCheck = () => {
setIsFormValid(isValidFormCheck(form, [], initialValues))
}

return (
<Row className={styles.baseRowContainer}>
<Image src={duckEmptyPage} alt={'Duck with a magnifying glass'} width={190} />
<Col className={styles.infoContainer}>
<Typography.Title className={styles.title} level={1}>
Редактирование обучающегося
</Typography.Title>

{!isFetching ? (
<Form
form={form}
className={styles.table}
colon={false}
requiredMark={false}
onValuesChange={validationCheck}
onFinish={() => {
handleSubmitForm(uuid[0], form, mutation).then((isSuccess) => {
if (isSuccess) router.push(`/student/${uuid[0]}`)
})
}}
layout='vertical'
>
<Form.Item
required={true}
label={'Ф. И. О.'}
name={STUDENT_NAME}
rules={validators[STUDENT_NAME]}
className={styles.label}
initialValue={initialValues[STUDENT_NAME]}
>
<Input required={true} placeholder='Введите имя' />
</Form.Item>

<Row className={styles.buttonsContainer}>
<Button type='schoolDefaultAuto' htmlType='submit' disabled={!isFormValid} block>
Сохранить изменения
</Button>

<Button
type='schoolDefaultAuto'
antdType={'default'}
block
onClick={() => router.push(`/student/${uuid[0]}`)}
>
Отменить
</Button>
</Row>
</Form>
) : (
<Spin />
)}
</Col>
</Row>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.baseRowContainer {
padding-bottom: 50px;

.infoContainer {
margin-left: 70px;
max-width: 600px;

.title {
margin-bottom: 50px;
}

.itemContainer {
margin-bottom: 30px;
}

.buttonsContainer {
gap: 20px;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
STUDENT_NAME,
STUDENT_PHONE,
} from '@domains/student/components/createStudentForm/constants'
import { handleSubmitForm } from '@domains/student/handlers/student'
import { handleSubmitForm } from '@domains/student/handlers/studentCreate'
import { WithTooltip } from '@domains/common/components/tooltip/withTooltip'
import { TOOLTIP_MARGIN_TOP } from '@domains/student/components/createStudentForm/styles/constants'
import { Select } from '@domains/common/components/select'
Expand Down
44 changes: 35 additions & 9 deletions apps/schools/domains/student/components/currentStudent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import router from 'next/router'
import duckEmptyPage from '@public/image/duckEmptyPage.svg'
import { Button } from '@domains/common/components/button'
import { Field } from '@domains/common/components/field'
import { useDeleteStudentMutation } from '@domains/student/redux/studentApi'
import { ActionBar } from '@domains/common/components/stickyBlock/actionBar'
import DeleteModal from '@domains/common/components/deleteModal'

const CurrentStudent = () => {
const [isModalVisible, setIsModalVisible] = useState(false)
// const [mutation, isDeleteFinished] = useDeleteCircleMutation()
const [mutation, isDeleteFinished] = useDeleteStudentMutation()
const uuid = getUuidFromUrl()

console.log(uuid)

const { data: student, error: studentError, isLoading } = useGetStudentQuery({ student_id: uuid[0] })

useEffect(() => {
Expand All @@ -28,7 +29,7 @@ const CurrentStudent = () => {
}
}, [studentError])

// if (isDeleteFinished.isSuccess) return null
if (isDeleteFinished.isSuccess) return null
if (uuid.length === 0) router.push('/404')

return (
Expand All @@ -44,7 +45,7 @@ const CurrentStudent = () => {
searchTrigger={false}
>
<Row className={styles.headersBlock}>
<Col lg={14} md={24} xs={24} sm={24} className={styles.queriesBlock}>
<Col lg={14} md={24} xs={24} sm={24} className={styles.infoBlock}>
<Row className={styles.baseRowContainer}>
<Col lg={4} className={styles.image}>
<Image src={duckEmptyPage} alt={'Duck with a magnifying glass'} width={190} />
Expand All @@ -58,10 +59,6 @@ const CurrentStudent = () => {
fieldValue={student?.student.student_profile?.phone}
/>
<Field fieldName={'Кружок:'} fieldValue={student?.student.circle?.name} />

<Button type='schoolDefaultAuto' block onClick={() => router.push('/student/edit')}>
Редактировать профиль
</Button>
</Col>
</Row>
</Col>
Expand All @@ -82,6 +79,35 @@ const CurrentStudent = () => {
</div>
</Col>
</Row>
<ActionBar
actions={[
<Button
key={'edit'}
className={styles.changeButton}
onClick={() => router.push(`/student/${uuid[0]}/change`)}
>
Редактировать профиль
</Button>,
<Button
antdType={'ghost'}
className={styles.deleteButton}
key='submit'
danger
onClick={() => setIsModalVisible(true)}
>
Удалить
</Button>,
]}
/>
<DeleteModal
isModalVisible={isModalVisible}
mutation={mutation}
setIsModalVisible={setIsModalVisible}
titleText={'Удалить обучающегося?'}
buttonText={'Удалить обучающегося'}
urlAfterDelete={'/student'}
dataField={'student_id'}
/>
</EmptyWrapper>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
height: initial;
margin-bottom: 42px;

.queriesBlock {
.infoBlock {
padding-right: 30px;

@media (max-width: 992px) {
Expand Down Expand Up @@ -88,7 +88,7 @@
display: flex;
flex-direction: column;
gap: 15px;
margin: 30px 23px 0px 30px;
margin: 30px 23px 0 30px;
position: relative;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FormInstance, message } from 'antd'
import { LoadingRequestMsg, SuccessInviteEmployeeMsg } from '@domains/user/components/auth/constants/message'
import { LoadingRequestMsg, SuccessCreateStudentMsg } from '@domains/user/components/auth/constants/message'
import {
CIRCLES,
PARENT_EMAIL,
Expand Down Expand Up @@ -40,7 +40,7 @@ export async function handleSubmitForm(form: FormInstance, mutation: any) {
)

if (isSuccess) {
message.success(SuccessInviteEmployeeMsg)
message.success(SuccessCreateStudentMsg)
}

return isSuccess
Expand Down
27 changes: 27 additions & 0 deletions apps/schools/domains/student/handlers/studentPatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { FormInstance, message } from 'antd'
import { LoadingRequestMsg, SuccessUpdateStudentMsg } from '@domains/user/components/auth/constants/message'
import { removeEmpty } from '@domains/common/utils/form'
import { withLoadingMessage } from '@domains/common/utils/loading'
import { STUDENT_NAME } from '@domains/student/components/changeStudentForm/constants'

export async function handleSubmitForm(studentId: string, form: FormInstance, mutation: any) {
const isSuccess = await withLoadingMessage(
LoadingRequestMsg,
async () => {
let response = await mutation(
removeEmpty({
student_id: studentId,
name: form.getFieldValue(STUDENT_NAME),
}),
)
return 'data' in response
},
[],
)

if (isSuccess) {
message.success(SuccessUpdateStudentMsg)
}

return isSuccess
}
8 changes: 8 additions & 0 deletions apps/schools/domains/student/redux/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface DeleteStudentData {
student_id: string
}

export interface UpdateStudentData {
student_id?: string
name?: string
}
28 changes: 28 additions & 0 deletions apps/schools/domains/student/redux/studentApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { commonApi } from '@store/commonApi'
import { DeleteStudentData, UpdateStudentData } from './interfaces'
import { GetStudent } from '@domains/common/redux/serializers'

const organizationApi = commonApi.injectEndpoints({
endpoints: (build) => ({
deleteStudent: build.mutation<{}, DeleteStudentData>({
query: (data) => ({
url: `/students-management/students/${data.student_id}`,
method: 'DELETE',
}),
invalidatesTags: [{ type: 'Student', id: 'LIST' }],
}),
updateStudentById: build.mutation<{ student: GetStudent }, UpdateStudentData>({
query: (data) => ({
url: `/students-management/students/${data.student_id}`,
method: 'PATCH',
body: data,
}),
invalidatesTags: (result, error, arg) => [
{ type: 'Student', id: 'LIST' },
{ type: 'Student', id: arg.student_id },
],
}),
}),
})

export const { useDeleteStudentMutation, useUpdateStudentByIdMutation } = organizationApi
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const SuccessSignInMsg = 'Вы успешно вошли в аккаун
export const SuccessResetPasswordMsg = 'Вы успешно сменили пароль'
export const SuccessRegistrationMsg = 'Вы успешно зарегистрировались'
export const PleaseInputYourNameMsg = 'Пожалуйста, введите ваше Ф. И. О.'
export const PleaseInputStudentNameMsg = 'Пожалуйста, введите ваше Ф. И. О. обучающегося'
export const PersonNameMustContainMsg = 'Введен недопустимый символ'
export const PersonNameMustNotStartOrAndMsg = 'ФИО не может начинаться с этого символа'
export const PleaseInputCircleNameMsg = 'Пожалуйста, введите название кружка'
Expand All @@ -30,4 +31,6 @@ export const PleaseSelectOneOfOptionsMsg = 'Пожалуйста, выберит
export const SuccessInviteEmployeeMsg = 'Приглашение отправлено'
export const SuccessCreateCircleMsg = 'Кружок успешно создан'
export const SuccessUpdateCircleMsg = 'Кружок успешно изменён'
export const SuccessCreateStudentMsg = 'Обучающийся успешно создан'
export const SuccessUpdateStudentMsg = 'Обучающийся успешно изменён'
export const SuccessUpdateUserProfileMsg = 'Ваш профиль успешно изменён'
22 changes: 22 additions & 0 deletions apps/schools/pages/student/[id]/change/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react'
import Head from 'next/head'
import { PageContent } from '@domains/common/components/containers/PageContent'
import { OrganizationRequired } from '@domains/common/components/containers/OrganizationRequired'
import { ChangeStudentForm } from '@domains/student/components/changeStudentForm'

export const Change = () => {
return (
<>
<Head>
<title>Редактирование обучающегося</title>
</Head>
<PageContent>
<OrganizationRequired>
<ChangeStudentForm />
</OrganizationRequired>
</PageContent>
</>
)
}

export default Change

0 comments on commit 9563762

Please sign in to comment.