Skip to content
145 changes: 145 additions & 0 deletions components/ContactInfoForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import React, { memo } from "react";
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если версия React ниже 17.00.0, то в компонентах мы обязаны импортировать React from "react" так как это JSX формат.


import localStorage from '../../../utils/browser/localStorage';
import { WarningIcon, SuccessIcon } from '../../../Icons';
import { Input, SuggestionsInput, FormRow, Button, Range } from '../../../UiComponents';
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Некоторые импорты имеет смысл переделать на алиасы
../../../utils/browser/localStorage -> utils/browser/localStorage
../../../Icons -> Icons
../../../UiComponents -> UiComponents

import { MAGIC_STRINGS, LOCALES } from "./const";
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Но не все. Так файл const относится только к данному компоненту. Его лучше оставить относительным.


export const ContactInfoForm = (props) => {
const {
userInfo,
setValue,
validate,
internalErrors,
removeError,
permissions,
phoneVerification,
username,
openModal,
whatsApp,
whatsAppSetNotifications,
} = props;

const sameUser = username === userInfo.username;
const whatsAppEnabled = sameUser && whatsApp && whatsApp.bot_enabled;
const userWorkHours = sameUser && userInfo.workHours;

const phoneVerificationButton = sameUser && (
<Button
type={MAGIC_STRINGS.text}
tooltip={phoneVerification ? LOCALES.phoneConfirmed : LOCALES.phoneNotConfirmed}
mode={phoneVerification ? MAGIC_STRINGS.success : MAGIC_STRINGS.error}
onClick={
!localStorage.getSwitchUser() && !phoneVerification
? () => openModal(MAGIC_STRINGS.verificationPhoneModal)
: () => null
}
>
{phoneVerification ? <SuccessIcon /> : <WarningIcon />}
</Button>
);

const whatsAppNotifyButton = (
<Button
inline
onClick={(e) => {
e.preventDefault();
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

У некоторых компонентов Button нет вызова event.preventDefault()
Это повод проверить необходимость данного вызова и удалить его в остальных местах, если он не нужен.

whatsAppSetNotifications(!whatsApp.notify_enabled);
}}
>
{whatsApp.notify_enabled ? LOCALES.notifyWhatsappDisable : LOCALES.notifyWhatsappEnable}
</Button>
);
const whatsAppBotButton = (
<Button
inline
onClick={() =>
openModal(MAGIC_STRINGS.whatsAppAuthModal, {
link: whatsApp[MAGIC_STRINGS.redirect_url],
})
}
>
{LOCALES.whatsappBotEnable}
</Button>
);

return (
<>
<FormRow>
<Input
id={MAGIC_STRINGS.email}
label={LOCALES.email}
size='lg'
disabled={!permissions.editEmail}
value={userInfo.email}
onChange={(value) => setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.email], value)}
onBlur={(value) => {
validate(MAGIC_STRINGS.email, value);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Функции в onChange, onBlur можно вынести в отдельные хендлеры. Тогда компонент будет чище, логика и отображение будут разделены.

}}
error={internalErrors.email}
/>
<Input
id={MAGIC_STRINGS.phone}
label={LOCALES.phone}
disabled={!permissions.editPhone}
value={userInfo.phone}
onChange={(value) => setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.phone], value)}
onBlur={(value) => {
validate(MAGIC_STRINGS.phone, value);
}}
error={internalErrors.phone}
after={phoneVerificationButton}
/>
{
whatsAppEnabled
&& (whatsApp.bot_started ? whatsAppNotifyButton : whatsAppBotButton)
}
<SuggestionsInput
id={MAGIC_STRINGS.address}
label={LOCALES.address}
placeholder={LOCALES.addressDefault}
name={MAGIC_STRINGS.address}
size='xl'
value={userInfo.address}
list={userInfo.addressList}
keyName={MAGIC_STRINGS.text}
onChange={setValue}
onBlur={(address) => {
validate(MAGIC_STRINGS.addressInProfile, address);
removeError(MAGIC_STRINGS.addressInProfile);
}}
error={internalErrors.addressInProfile}
/>
</FormRow>
{permissions.editNote && (
<FormRow>
<Input
id={MAGIC_STRINGS.description}
label={LOCALES.remark}
rows='3'
size='stretch'
disabled={!permissions.editNote}
value={userInfo.notes}
onChange={(value) => setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.notes], value)}
/>
</FormRow>
)}
{userWorkHours && (
<>
{LOCALES.workHours}
<FormRow>
<Range
step={1}
min={0}
max={23}
values={userInfo.workHours}
onChange={(value) => setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.workHours], value)}
/>
</FormRow>
</>
)}
</>
);
};

export default memo(ContactInfoForm);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мемоизация поможет избежать лишних ререндеров.

146 changes: 146 additions & 0 deletions components/LegalInfoForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import React, { memo } from "react";
import moment from "moment";
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Библиотека moment.js deprecated. Можно использовать более легковесную библиотеку day.js


import {
Input,
DateInput,
RadioButtons,
FormRow,
} from "../../../UiComponents";
import { MAGIC_STRINGS, LOCALES, REGEXP, DATES_FORMAT } from "./const";

export const LegalInfoForm = (props) => {
const {
userInfo,
setValue,
validate,
internalErrors,
isJuridical,
permissions,
rejectSet,
} = props;

const setIsJuridical = (value) => {
if (permissions.editJuridical) {
setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.isJuridical], value);
} else {
rejectSet(LOCALES.juridicalError);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Смущает название. Ассоциируется с Promise.reject.
  • Необходимо разобраться, за что отвечает данная функция. Есть вероятность, что ее функциональность может быть реализована через банальный useState в данном компоненте.

}
};

return (
<FormRow>
<RadioButtons
id={MAGIC_STRINGS.isJuridical}
value={isJuridical}
list={[
{ title: LOCALES.physical, value: false },
{ title: LOCALES.juridical, value: true },
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно вынести в константы, зависит от код стиля проекта и необходимости переиспользовать такого типа объект.

]}
onChange={(value) => setIsJuridical(value)}
/>
{isJuridical ? (
<Input
id={MAGIC_STRINGS.inn}
label={LOCALES.inn}
maxLength="12"
value={userInfo.inn}
onChange={(value) => {
if (
REGEXP.inn.test(value) ||
value.length < userInfo.inn.length
)
return setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.inn], value);
}}
/>
) : (
<>
<Input
id={MAGIC_STRINGS.series}
label={LOCALES.passportSerial}
placeholder={LOCALES.passportSerialDefault}
maxLength="4"
size="xs"
value={userInfo.series}
onChange={(value) => {
if (
REGEXP.passportSerial.test(value) ||
value.length < userInfo.series.length
)
return setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.series], value);
}}
onBlur={(value) => {
validate(MAGIC_STRINGS.series, value, {
documentType: MAGIC_STRINGS.passport,
});
}}
error={internalErrors.series}
/>
<Input
id={MAGIC_STRINGS.number}
label={LOCALES.passportNumber}
placeholder={LOCALES.passportNumberDefault}
maxLength="6"
size="xs"
value={userInfo.number}
onChange={(value) => {
if (
REGEXP.passportNumber.test(value) ||
value.length < userInfo.number.length
)
return setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.number], value);
}}
onBlur={(value) => {
validate(MAGIC_STRINGS.number, value, {
documentType: MAGIC_STRINGS.passport,
});
}}
error={internalErrors.number}
/>
<DateInput
id={MAGIC_STRINGS.birthday}
label={LOCALES.birthday}
value={userInfo.birthday}
onChange={(value) => {
if (
REGEXP.birthday.test(value) ||
value.length < userInfo.birthday.length
)
return setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.birthday], value);
}}
onBlur={(value) => {
validate(MAGIC_STRINGS.birthday, value);
if (userInfo.issuedAt)
validate(MAGIC_STRINGS.issuedAt, userInfo.issuedAt, {
documentType: MAGIC_STRINGS.passport,
birth: value,
});
if (moment(value, DATES_FORMAT.DDMMYYYY).isValid()) {
setValue(
[MAGIC_STRINGS.userInfo, MAGIC_STRINGS.birthday],
moment(value, DATES_FORMAT.DDMMYYYY).format(DATES_FORMAT.DDMMYYYY)
);
}
}}
error={internalErrors.birthday}
/>
<Input
id={MAGIC_STRINGS.snils}
label={LOCALES.snils}
maxLength="11"
value={userInfo.snils}
onChange={(value) => {
if (
REGEXP.snils.test(value) ||
value.length < userInfo.snils.length
)
return setValue([MAGIC_STRINGS.userInfo, MAGIC_STRINGS.snils], value);
}}
/>
</>
)}
</FormRow>
);
};

export default memo(LegalInfoForm);
Loading