generated from 8iq/nodejs-hackathon-boilerplate-starter-kit
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
circle create page with validators and select features
- Loading branch information
1 parent
389e8c8
commit e89add4
Showing
27 changed files
with
526 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
apps/schools/domains/circle/components/createCircleForm/constants.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const CIRCLE_NAME = 'circle_name' | ||
export const CIRCLE_ADDRESS = 'circle_address' | ||
export const ADDRESS_ROOM = 'address_room' |
30 changes: 30 additions & 0 deletions
30
apps/schools/domains/circle/components/createCircleForm/hooks.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { useMemo } from 'react' | ||
import { PleaseInputAddressMsg, PleaseInputCircleNameMsg } from '@domains/user/components/auth/constants/message' | ||
import { ValidatorsMap } from '@domains/common/redux/interfaces' | ||
import { getGreaterValidator } from '@domains/common/utils/validators' | ||
|
||
export const useCreateCircleFormValidators = () => { | ||
return useMemo<ValidatorsMap>(() => { | ||
return { | ||
name: [ | ||
{ | ||
required: true, | ||
message: PleaseInputCircleNameMsg, | ||
whitespace: true, | ||
type: 'string', | ||
}, | ||
getGreaterValidator(200), | ||
], | ||
address: [ | ||
{ | ||
required: true, | ||
message: PleaseInputAddressMsg, | ||
whitespace: true, | ||
type: 'string', | ||
}, | ||
getGreaterValidator(200), | ||
], | ||
room: [getGreaterValidator(55)], | ||
} | ||
}, [this]) | ||
} |
145 changes: 145 additions & 0 deletions
145
apps/schools/domains/circle/components/createCircleForm/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import { Form, Typography, Input as AntdInput, Row, Spin } from 'antd' | ||
import React, { useState } from 'react' | ||
import { Input } from '@domains/common/components/input' | ||
import styles from './styles/styles.module.scss' | ||
import { Button } from '@domains/common/components/button' | ||
import { useCreateCircleFormValidators } from './hooks' | ||
import { useGetAllCirclesQuery } from '@domains/organization/redux/organizationApi' | ||
import { useOrganization } from '@domains/organization/providers/organizationProvider' | ||
import { WithTooltip } from '@domains/common/components/tooltip/withTooltip' | ||
import { TOOLTIP_MARGIN } from './styles/styles' | ||
import { isValidFormCheck } from '@domains/common/utils/form' | ||
import { CIRCLE_NAME, CIRCLE_ADDRESS, ADDRESS_ROOM } from './constants' | ||
import classnames from 'classnames' | ||
import { AimOutlined } from '@ant-design/icons' | ||
import { Select } from '@domains/common/components/select' | ||
import { handleSubmitForm } from '../../handlers/circle' | ||
import { useCreateCircleMutation } from '../../redux/circleApi' | ||
import { getVarsForAddressColumn } from '@domains/common/utils/geo' | ||
|
||
export const CreateCircleForm = () => { | ||
const validators = useCreateCircleFormValidators() | ||
const { organization, organizationId } = useOrganization() | ||
const [form] = Form.useForm() | ||
const [isFormValid, setIsFormValid] = useState(false) | ||
const [mutation] = useCreateCircleMutation() | ||
const circlesData = useGetAllCirclesQuery({ | ||
organization_id: organization.id, | ||
}) | ||
const circlesAddresses = Array.from( | ||
new Set(circlesData?.data?.results.map((x) => getVarsForAddressColumn(x.address)[0])), | ||
) | ||
|
||
const validationCheck = () => { | ||
setIsFormValid(isValidFormCheck(form, [CIRCLE_NAME])) | ||
} | ||
|
||
return ( | ||
<Row className={styles.mainRow}> | ||
<div className={styles.formContainer}> | ||
<Form | ||
form={form} | ||
className={styles.table} | ||
colon={false} | ||
requiredMark={false} | ||
onValuesChange={validationCheck} | ||
onFinish={() => { | ||
handleSubmitForm(organizationId, form, mutation).then((isSucceed) => { | ||
if (isSucceed) window.location.href = '/circle' | ||
}) | ||
}} | ||
layout='vertical' | ||
> | ||
<Typography.Title level={1}>Добавление кружка</Typography.Title> | ||
<WithTooltip tooltipText={'Здесь будет текст тултипа'} margin={TOOLTIP_MARGIN}> | ||
<Form.Item | ||
required={true} | ||
label={ | ||
<span> | ||
<span className={styles.requiredMark}>*</span> Название | ||
</span> | ||
} | ||
name={CIRCLE_NAME} | ||
className={styles.label} | ||
rules={validators.name} | ||
> | ||
<Input required={true} placeholder='Введите название кружка' /> | ||
</Form.Item> | ||
</WithTooltip> | ||
|
||
<Row className={styles.complexInputContainer}> | ||
{!circlesData.isLoading ? ( | ||
<> | ||
<AntdInput.Group compact className={styles.complexInput}> | ||
<Form.Item | ||
required={true} | ||
label={ | ||
<span> | ||
<span className={styles.requiredMark}>*</span> Адрес | ||
</span> | ||
} | ||
name={CIRCLE_ADDRESS} | ||
initialValue={circlesAddresses[0]} | ||
className={classnames(styles.label, styles.address)} | ||
rules={validators.address} | ||
> | ||
<Select | ||
placeholder='Выберите адрес кружка' | ||
customType={'selectInput'} | ||
className={styles.select} | ||
loading={circlesData.isLoading} | ||
options={circlesAddresses?.map((x: string | undefined) => { | ||
return { | ||
value: x, | ||
label: x, | ||
} | ||
})} | ||
/> | ||
</Form.Item> | ||
|
||
<Form.Item | ||
label={'Помещение'} | ||
name={ADDRESS_ROOM} | ||
className={classnames(styles.label, styles.room)} | ||
initialValue={''} | ||
rules={validators.room} | ||
> | ||
<Input className={styles.input} placeholder='Помещение и номер' /> | ||
</Form.Item> | ||
</AntdInput.Group> | ||
|
||
<Button className={styles.mapButton} antdType={'text'} icon={<AimOutlined />}> | ||
Выбрать на карте | ||
</Button> | ||
</> | ||
) : ( | ||
<Spin></Spin> | ||
)} | ||
</Row> | ||
|
||
<Form.Item name='button'> | ||
<Button | ||
disabled={!isFormValid} | ||
key='submit' | ||
type='schoolDefault' | ||
htmlType='submit' | ||
block | ||
data-cy='resetcomplete-button' | ||
style={{ width: '30%' }} | ||
className={styles.button} | ||
> | ||
Добавить кружок | ||
</Button> | ||
</Form.Item> | ||
</Form> | ||
</div> | ||
<div className={styles.mobileApp}> | ||
<Typography.Title level={3}>Приложение родителей</Typography.Title> | ||
<Typography.Title level={3} className={styles.text}> | ||
Родители смогут увидеть ваш кружок с помощью карты и узнать информацию о нём! | ||
</Typography.Title> | ||
{/*<Image src={mobileApp} alt={"Мобильное приложения на странице создания кружка"}/>*/} | ||
</div> | ||
</Row> | ||
) | ||
} |
88 changes: 88 additions & 0 deletions
88
apps/schools/domains/circle/components/createCircleForm/styles/styles.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
@import '../../../../common/components/styles/abstracts/colors'; | ||
|
||
.mainRow { | ||
height: 100px; | ||
justify-content: space-between; | ||
|
||
.formContainer { | ||
width: 700px; | ||
|
||
.table { | ||
max-width: 550px; | ||
|
||
.requiredMark { | ||
color: $color-required-mark; | ||
} | ||
|
||
.label { | ||
font-family: 'Roboto', sans-serif; | ||
font-size: 14px; | ||
font-style: normal; | ||
font-weight: 400; | ||
line-height: 22px; | ||
} | ||
|
||
.complexInputContainer { | ||
width: 125%; | ||
|
||
.complexInput { | ||
width: 76%; | ||
|
||
.address { | ||
width: 65%; | ||
border-radius: 0; | ||
|
||
.input { | ||
border-top-right-radius: 0; | ||
border-bottom-right-radius: 0; | ||
} | ||
} | ||
|
||
.room { | ||
width: 35%; | ||
|
||
.input { | ||
border-top-left-radius: 0; | ||
border-bottom-left-radius: 0; | ||
} | ||
} | ||
} | ||
|
||
.mapButton { | ||
width: 24%; | ||
margin-top: 38px; | ||
color: #2698FF; | ||
padding-left: 1%; | ||
} | ||
} | ||
|
||
|
||
.button { | ||
text-align: center; | ||
font-family: 'Roboto', sans-serif; | ||
font-size: 16px; | ||
font-style: normal; | ||
font-weight: 400; | ||
line-height: 24px; | ||
} | ||
} | ||
} | ||
|
||
.mobileApp { | ||
padding-left: 60px; | ||
padding-right: 60px; | ||
padding-top: 30px; | ||
margin-top: 20px; | ||
height: 814px; | ||
width: 505px; | ||
border-radius: 12px; | ||
background: linear-gradient(180deg, rgba(24, 144, 255, 0.3) 0%, rgba(245, 245, 245, 0.00) 100%); | ||
|
||
.text{ | ||
font-size: 24px; | ||
font-style: normal; | ||
font-weight: 600; | ||
line-height: 130%; | ||
} | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
apps/schools/domains/circle/components/createCircleForm/styles/styles.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const TOOLTIP_MARGIN = '47px' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { FormInstance, message } from 'antd' | ||
import { SuccessCreateCircleMsg } from '@domains/user/components/auth/constants/message' | ||
import { removeEmpty } from '@domains/common/utils/form' | ||
import { CIRCLE_NAME, CIRCLE_ADDRESS, ADDRESS_ROOM } from '../components/createCircleForm/constants' | ||
import { withLoadingMessage } from '@domains/common/utils/loading' | ||
import { ADDRESS_SEPARATOR } from '@domains/common/utils/geo' | ||
|
||
export async function handleSubmitForm(organizationId: string, formComponent: FormInstance, mutation: any) { | ||
console.log(formComponent.getFieldValue(CIRCLE_ADDRESS)) | ||
|
||
const response = await withLoadingMessage( | ||
'Выполняется запрос...', | ||
mutation, | ||
removeEmpty({ | ||
organization: organizationId, | ||
name: formComponent.getFieldValue(CIRCLE_NAME), | ||
address: `${formComponent.getFieldValue(CIRCLE_ADDRESS)}${ADDRESS_SEPARATOR}${formComponent.getFieldValue( | ||
ADDRESS_ROOM, | ||
)}`, | ||
}), | ||
) | ||
|
||
if ('data' in response) { | ||
message.success(SuccessCreateCircleMsg) | ||
return true | ||
} | ||
|
||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { Select as BaseSelect } from 'antd' | ||
import React, { useState } from 'react' | ||
import defaultStyles from './styles/default.module.scss' | ||
import { CustomInputProps, selectStyleDictionary } from './interfaces' | ||
import classNames from 'classnames' | ||
import { typeSelect } from '@domains/common/constants/Select' | ||
|
||
export const Select: React.FC<CustomInputProps> = (props) => { | ||
const { | ||
disabled = false, | ||
customType = 'selectDefault', | ||
placeholder, | ||
label, | ||
className, | ||
children, | ||
options, | ||
...restProps | ||
} = props | ||
|
||
if (!typeSelect.includes(customType)) { | ||
return ( | ||
<div className={defaultStyles.selectContainer}> | ||
<label>{label}</label> | ||
<BaseSelect | ||
className={classNames(defaultStyles.select, className)} | ||
placeholder={placeholder} | ||
data-testid='select' | ||
{...restProps} | ||
> | ||
{children} | ||
</BaseSelect> | ||
</div> | ||
) | ||
} else if (customType === 'selectInput') { | ||
const [addressText, setAddressText] = useState('') | ||
|
||
const handleSearch = (value: string) => { | ||
setAddressText(value) | ||
} | ||
|
||
let additionalOption = | ||
addressText != '' | ||
? [ | ||
{ | ||
value: addressText, | ||
label: addressText, | ||
}, | ||
] | ||
: [] | ||
|
||
if (options && options.filter((x) => x.value === addressText).length > 0) additionalOption = [] | ||
|
||
return ( | ||
<div className={selectStyleDictionary['selectDefault']?.selectContainer}> | ||
<label>{label}</label> | ||
<BaseSelect | ||
className={classNames(selectStyleDictionary['selectDefault']?.select, className)} | ||
{...restProps} | ||
showSearch={true} | ||
onSearch={handleSearch} | ||
onSelect={() => setAddressText('')} | ||
placeholder={placeholder} | ||
options={options?.concat(additionalOption)} | ||
data-testid='select' | ||
> | ||
{children} | ||
</BaseSelect> | ||
</div> | ||
) | ||
} else { | ||
return ( | ||
<div className={selectStyleDictionary[customType]?.selectContainer}> | ||
<label>{label}</label> | ||
<BaseSelect | ||
className={classNames(selectStyleDictionary[customType]?.select, className)} | ||
{...restProps} | ||
placeholder={placeholder} | ||
data-testid='select' | ||
> | ||
{children} | ||
</BaseSelect> | ||
</div> | ||
) | ||
} | ||
} |
Oops, something went wrong.