nocobase/packages/core/client/src/user/SigninPage.tsx
Junyi 7e6a394f73
feat(plugin-verification): add plugin-verification and phone for users (#722)
* feat(plugin-verification): add plugin-verification and phone for users

* feat(plugin-verification): add env example

* fix(plugin-verification): fix locales

* fix(plugin-verification): remove sending comment

* fix(plugin-verification): fix i18n

* refactor(plugin-verification): move invalid error message to action

* fix(plugin-verification): add field migration

* chore(plugin-verification): update packages version

* test(plugin-verification): temp remove new package dependency

* refactor(plugin-verification): make sms authentication configurable in system settings

* fix: smsAuthEnabled

* feat: update preset-nocobase

Co-authored-by: chenos <chenlinxh@gmail.com>
2022-08-20 18:06:12 +08:00

156 lines
4.0 KiB
TypeScript

import { ISchema, useForm } from '@formily/react';
import { Tabs } from 'antd';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Link, useHistory, useLocation } from 'react-router-dom';
import { SchemaComponent, useAPIClient, useCurrentDocumentTitle, useSystemSettings } from '..';
import VerificationCode from './VerificationCode';
const passwordForm: ISchema = {
type: 'object',
name: 'passwordForm',
'x-component': 'FormV2',
properties: {
email: {
type: 'string',
required: true,
'x-component': 'Input',
'x-validator': 'email',
'x-decorator': 'FormItem',
'x-component-props': { placeholder: '{{t("Email")}}', style: {} },
},
password: {
type: 'string',
'x-component': 'Password',
required: true,
'x-decorator': 'FormItem',
'x-component-props': { placeholder: '{{t("Password")}}', style: {} },
},
actions: {
type: 'void',
'x-component': 'div',
properties: {
submit: {
title: '{{t("Sign in")}}',
type: 'void',
'x-component': 'Action',
'x-component-props': {
htmlType: 'submit',
block: true,
type: 'primary',
useAction: '{{ usePasswordSignIn }}',
style: { width: '100%' },
},
},
},
},
},
};
function useRedirect(next = '/admin') {
const location = useLocation<any>();
const history = useHistory();
const redirect = location?.['query']?.redirect;
return useCallback(() => {
history.push(redirect || '/admin');
}, [redirect]);
}
export const usePasswordSignIn = () => {
const form = useForm();
const api = useAPIClient();
const redirect = useRedirect();
return {
async run() {
await form.submit();
await api.auth.signIn(form.values);
redirect();
},
};
};
const phoneForm: ISchema = {
type: 'object',
name: 'phoneForm',
'x-component': 'Form',
properties: {
phone: {
type: 'string',
required: true,
'x-component': 'Input',
'x-validator': 'phone',
'x-decorator': 'FormItem',
'x-component-props': { placeholder: '{{t("Phone")}}', style: {} },
},
code: {
type: 'string',
required: true,
'x-component': 'VerificationCode',
'x-component-props': {
actionType: 'users:signin',
targetFieldName: 'phone',
},
'x-decorator': 'FormItem',
},
actions: {
title: '{{t("Sign in")}}',
type: 'void',
'x-component': 'Action',
'x-component-props': {
htmlType: 'submit',
block: true,
type: 'primary',
useAction: '{{ usePhoneSignIn }}',
style: { width: '100%' },
},
},
},
};
export function usePhoneSignIn() {
const form = useForm();
const api = useAPIClient();
const redirect = useRedirect();
return {
async run() {
await form.submit();
await api.auth.signIn(form.values, 'sms');
redirect();
},
};
}
export const SigninPage = () => {
const { t } = useTranslation();
useCurrentDocumentTitle('Signin');
const ctx = useSystemSettings();
const { allowSignUp, smsAuthEnabled } = ctx?.data?.data || {};
return (
<div>
{smsAuthEnabled ? (
<Tabs defaultActiveKey="password">
<Tabs.TabPane tab={t('Sign in via account')} key="password">
<SchemaComponent scope={{ usePasswordSignIn }} schema={passwordForm} />
</Tabs.TabPane>
<Tabs.TabPane tab={t('Sign in via phone')} key="phone">
<SchemaComponent
schema={phoneForm}
scope={{ usePhoneSignIn }}
components={{
VerificationCode,
}}
/>
</Tabs.TabPane>
</Tabs>
) : (
<SchemaComponent scope={{ usePasswordSignIn }} schema={passwordForm} />
)}
{allowSignUp && (
<div>
<Link to="/signup">{t('Create an account')}</Link>
</div>
)}
</div>
);
};