Created
September 6, 2023 11:40
-
-
Save 7iomka/ae496d62d17e52c5016aaaa79f2facf4 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import clsx from 'clsx'; | |
import { Anchor, Button, Loader, LoadingOverlay } from '@mantine/core'; | |
import type { PropsWithChildren } from 'react'; | |
import { useUnit } from 'effector-react'; | |
import { $$viewer } from '@/entities/viewer'; | |
import { Form, FormField, useForm } from '@/shared/form'; | |
import { createView } from '@/shared/lib/view'; | |
import { CustomLink } from '@/shared/ui'; | |
import { createModelProvider2 } from '@/shared/lib/factory'; | |
import { factory } from '../../register.model'; | |
const { ModelProvider: CreateRegisterFormProvider, useModel } = | |
createModelProvider2('RegisterFormProvider'); | |
const FormPhone = createView() | |
.map(() => { | |
const model = useModel(factory); | |
const [isLoading, isPhoneEditable, handleEditPhone, confirmationModes] = useUnit([ | |
model.$formPhonePending, | |
model.$isPhoneEditable, | |
model.editPhoneClicked, | |
model.$confirmationModes, | |
]); | |
const { fields, onSubmit: handleSubmit } = useForm(model.$$formPhone); | |
return { | |
fields, | |
handleSubmit, | |
isLoading, | |
isPhoneEditable, | |
handleEditPhone, | |
confirmationModes, | |
}; | |
}) | |
.view( | |
({ fields, handleSubmit, isLoading, isPhoneEditable, handleEditPhone, confirmationModes }) => ( | |
<Form onSubmit={handleSubmit}> | |
<FormField.PhoneInput | |
field={fields.phone} | |
label="Номер телефона" | |
disabled={!isPhoneEditable} | |
/> | |
{!isPhoneEditable && ( | |
<Anchor | |
component="button" | |
type="button" | |
color="dark" | |
underline | |
className="opacity-70 hover:opacity-100 mt-5" | |
onClick={handleEditPhone} | |
> | |
Изменить номер телефона | |
</Anchor> | |
)} | |
{isPhoneEditable && ( | |
<> | |
<FormField.SegmentedControl | |
className="mt-15" | |
field={fields.confirmationMode} | |
data={confirmationModes.map((mode) => ({ | |
value: mode.value, | |
label: mode.label, | |
}))} | |
fullWidth | |
color="primary" | |
/> | |
<Button | |
radius="xl" | |
color="gray.3" | |
fullWidth | |
className="mt-15" | |
disabled={isLoading} | |
type="submit" | |
> | |
{isLoading ? <Loader variant="dots" color="dark" /> : 'Получить код'} | |
</Button> | |
</> | |
)} | |
</Form> | |
), | |
); | |
const FormPhoneConfirm = createView< | |
PropsWithChildren<{ className?: string; submitLabel?: string }> | |
>() | |
.map(() => { | |
const model = useModel(factory); | |
const [ | |
isLoading, | |
isConfirmationCountdownRunning, | |
confirmationCodeRequestCount, | |
confirmationCountdown, | |
resendCode, | |
confirmationModeInfo, | |
] = useUnit([ | |
model.$registerPending, | |
model.$isPhoneConfirmationCountdownRunning, | |
model.$confirmationCodeRequestCount, | |
model.$phoneConfirmationCountdownString, | |
model.confirmationCodeResended, | |
model.$confirmationModeInfo, | |
]); | |
const { fields, onSubmit: handleSubmit } = useForm(model.$$formPhoneConfirm); | |
return { | |
fields, | |
handleSubmit, | |
isLoading, | |
isConfirmationCountdownRunning, | |
confirmationCountdown, | |
confirmationCodeRequestCount, | |
resendCode, | |
confirmationModeInfo, | |
}; | |
}) | |
.view( | |
({ | |
className, | |
fields, | |
handleSubmit, | |
isLoading, | |
isConfirmationCountdownRunning, | |
confirmationCountdown, | |
confirmationCodeRequestCount, | |
resendCode, | |
confirmationModeInfo, | |
submitLabel = 'Зарегистрироваться', | |
children, | |
}) => ( | |
<div className={className}> | |
<Form className={className} onSubmit={handleSubmit}> | |
<div className="text-sm text-center font-bold"> | |
Минутку, код подтверждения отправлен на указанный номер через{' '} | |
{confirmationModeInfo.label}. | |
</div> | |
<FormField.TextInput | |
className="mt-20" | |
field={fields.code} | |
label="Код из сообщения" | |
autoComplete="off" | |
/> | |
{!!children && <div className="mt-15">{children}</div>} | |
<FormField.Checkbox | |
className="mt-20" | |
field={fields.agreement} | |
label={ | |
<> | |
Согласен с{' '} | |
<CustomLink | |
className="inline" | |
component="a" | |
href="/static/documents/privacy-policy.pdf" | |
target="_blank" | |
> | |
правилами обработки персональных данных | |
</CustomLink> | |
</> | |
} | |
/> | |
<Button radius="xl" className="mt-15" fullWidth type="submit"> | |
{isLoading ? <Loader variant="dots" color="dark" /> : submitLabel} | |
</Button> | |
{confirmationCodeRequestCount > 0 && | |
(isConfirmationCountdownRunning ? ( | |
<div className="text-sm text-center font-bold mt-10"> | |
Получить код повторно через {confirmationCountdown} | |
</div> | |
) : ( | |
<Button radius="xl" className="mt-15" color="gray.3" fullWidth onClick={resendCode}> | |
Получить новый код | |
</Button> | |
))} | |
</Form> | |
</div> | |
), | |
); | |
const RegisterForm = createView< | |
PropsWithChildren<{ | |
className?: string; | |
formSubmitLabel?: string; | |
}> | |
>() | |
.displayName('RegisterForm') | |
.units({ | |
isAuthorized: $$viewer.$isAuthorized, | |
}) | |
.map(() => { | |
const model = useModel(factory); | |
const isConfirmationCodeEnabled = useUnit(model.$isConfirmationCodeEnabled); | |
return { isConfirmationCodeEnabled }; | |
}) | |
.memo() | |
.view(({ className, isConfirmationCodeEnabled, children, formSubmitLabel, isAuthorized }) => ( | |
<section className={clsx(className, 'relative')}> | |
<FormPhone /> | |
{isConfirmationCodeEnabled && ( | |
<FormPhoneConfirm className="mt-15" submitLabel={formSubmitLabel}> | |
{children} | |
</FormPhoneConfirm> | |
)} | |
<LoadingOverlay | |
visible={isAuthorized} | |
loader={ | |
<div className="flex-col items-center text-center"> | |
<Loader width={40} variant="dots" /> | |
</div> | |
} | |
/> | |
</section> | |
)).Memo; | |
const CreateRegisterForm = ({ model, ...rest }) => ( | |
<CreateRegisterFormProvider model={model}> | |
<RegisterForm {...rest} /> | |
</CreateRegisterFormProvider> | |
); | |
export { CreateRegisterForm }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment