-
Notifications
You must be signed in to change notification settings - Fork 818
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(flat-pages): add password login & register (#1984)
* feat(flat-components): add login with password feat(flat-components): add reset password page feat(flat-pages): add sign up page refactor(flat-pages): refactor login logic to useLogin refactor(flat-pages): refactor QRCode & BindingPhone components refactor(flat-pages): replace type with enum refactor(flat-pages): merge register to login page & optimize login logic refactor(storybook): add storybook for components refactor(storybook): add storybook for components refactor(library): remove useless types * update lockfile --------- Co-authored-by: hyrious <hyrious@outlook.com>
- Loading branch information
Showing
50 changed files
with
2,079 additions
and
997 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
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
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
29 changes: 29 additions & 0 deletions
29
.../flat-components/src/components/LoginPage/BindingPhonePanel/BindingPhonePanel.stories.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,29 @@ | ||
import { Meta, Story } from "@storybook/react"; | ||
import { message } from "antd"; | ||
import React from "react"; | ||
import { BindingPhonePanelProps, BindingPhonePanel } from "."; | ||
|
||
const storyMeta: Meta = { | ||
title: "LoginPage/BindingPhonePanel", | ||
component: BindingPhonePanel, | ||
}; | ||
|
||
export default storyMeta; | ||
|
||
export const Overview: Story<BindingPhonePanelProps> = props => { | ||
return <BindingPhonePanel {...props} />; | ||
}; | ||
|
||
Overview.args = { | ||
cancelBindingPhone: () => { | ||
message.info("back to previous step"); | ||
}, | ||
bindingPhone: (countryCode: string, phone: string, code: string) => { | ||
message.info("bind phone with " + countryCode + " " + phone + " " + code); | ||
return new Promise(resolve => setTimeout(() => resolve(false), 1000)); | ||
}, | ||
sendBindingPhoneCode: (countryCode: string, phone: string) => { | ||
message.info("send verification code with " + countryCode + " " + phone); | ||
return new Promise(resolve => setTimeout(() => resolve(false), 1000)); | ||
}, | ||
}; |
134 changes: 134 additions & 0 deletions
134
packages/flat-components/src/components/LoginPage/BindingPhonePanel/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,134 @@ | ||
import { useTranslate } from "@netless/flat-i18n"; | ||
import { Input, Select, Button, message } from "antd"; | ||
|
||
import { validatePhone, validateCode } from "../LoginWithCode"; | ||
import { COUNTRY_CODES } from "../LoginWithCode/data"; | ||
import { useIsUnMounted, useSafePromise } from "../../../utils/hooks"; | ||
import React, { useCallback, useState } from "react"; | ||
import { LoginTitle } from "../LoginTitle"; | ||
|
||
import checkedSVG from "../icons/checked.svg"; | ||
|
||
export interface BindingPhonePanelProps { | ||
cancelBindingPhone: () => void; | ||
bindingPhone?: (countryCode: string, phone: string, code: string) => Promise<boolean>; | ||
sendBindingPhoneCode?: (countryCode: string, phone: string) => Promise<boolean>; | ||
} | ||
|
||
export const BindingPhonePanel: React.FC<BindingPhonePanelProps> = ({ | ||
sendBindingPhoneCode, | ||
cancelBindingPhone, | ||
bindingPhone, | ||
}) => { | ||
const sp = useSafePromise(); | ||
const t = useTranslate(); | ||
|
||
const isUnMountRef = useIsUnMounted(); | ||
const [phone, setPhone] = useState(""); | ||
const [code, setCode] = useState(false); | ||
const [countdown, setCountdown] = useState(0); | ||
const [countryCode, setCountryCode] = useState("+86"); | ||
const [clickedBinding, setClickedBinding] = useState(false); | ||
const [bindingPhoneCode, setBindingPhoneCode] = useState(""); | ||
|
||
const canBinding = !clickedBinding && validatePhone(phone) && validateCode(bindingPhoneCode); | ||
|
||
const sendBindingCode = useCallback(async () => { | ||
if (validatePhone(phone) && sendBindingPhoneCode) { | ||
setCode(true); | ||
const sent = await sp(sendBindingPhoneCode(countryCode, phone)); | ||
setCode(false); | ||
if (sent) { | ||
void message.info(t("sent-verify-code-to-phone")); | ||
let count = 60; | ||
setCountdown(count); | ||
const timer = setInterval(() => { | ||
if (isUnMountRef.current) { | ||
clearInterval(timer); | ||
return; | ||
} | ||
setCountdown(--count); | ||
if (count === 0) { | ||
clearInterval(timer); | ||
} | ||
}, 1000); | ||
} | ||
} | ||
}, [countryCode, isUnMountRef, phone, sendBindingPhoneCode, sp, t]); | ||
|
||
const bindPhone = useCallback(async () => { | ||
if (canBinding && bindingPhone) { | ||
setClickedBinding(true); | ||
const success = await sp(bindingPhone(countryCode, phone, bindingPhoneCode)); | ||
if (success) { | ||
await sp(new Promise(resolve => setTimeout(resolve, 60000))); | ||
} else { | ||
message.error(t("bind-phone-failed")); | ||
} | ||
setClickedBinding(false); | ||
} | ||
}, [bindingPhone, bindingPhoneCode, canBinding, countryCode, phone, sp, t]); | ||
|
||
return ( | ||
<div className="login-with-phone binding"> | ||
<div className="login-width-limiter"> | ||
<LoginTitle subtitle={t("need-bind-phone")} title={t("bind-phone")} /> | ||
<Input | ||
placeholder={t("enter-phone")} | ||
prefix={ | ||
<Select bordered={false} defaultValue="+86" onChange={setCountryCode}> | ||
{COUNTRY_CODES.map(code => ( | ||
<Select.Option | ||
key={code} | ||
value={`+${code}`} | ||
>{`+${code}`}</Select.Option> | ||
))} | ||
</Select> | ||
} | ||
size="small" | ||
status={!phone || validatePhone(phone) ? undefined : "error"} | ||
value={phone} | ||
onChange={ev => setPhone(ev.currentTarget.value)} | ||
/> | ||
<Input | ||
placeholder={t("enter-code")} | ||
prefix={<img alt="checked" draggable={false} src={checkedSVG} />} | ||
status={ | ||
!bindingPhoneCode || validateCode(bindingPhoneCode) ? undefined : "error" | ||
} | ||
suffix={ | ||
countdown > 0 ? ( | ||
<span className="login-countdown"> | ||
{t("seconds-to-resend", { seconds: countdown })} | ||
</span> | ||
) : ( | ||
<Button | ||
disabled={code || !validatePhone(phone)} | ||
loading={code} | ||
size="small" | ||
type="link" | ||
onClick={sendBindingCode} | ||
> | ||
{t("send-verify-code")} | ||
</Button> | ||
) | ||
} | ||
value={bindingPhoneCode} | ||
onChange={ev => setBindingPhoneCode(ev.currentTarget.value)} | ||
/> | ||
<Button | ||
className="login-big-button" | ||
disabled={!canBinding} | ||
loading={clickedBinding} | ||
type="primary" | ||
onClick={bindPhone} | ||
> | ||
{t("confirm")} | ||
</Button> | ||
<Button className="login-btn-back" type="link" onClick={cancelBindingPhone}> | ||
{t("back")} | ||
</Button> | ||
</div> | ||
</div> | ||
); | ||
}; |
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
32 changes: 32 additions & 0 deletions
32
packages/flat-components/src/components/LoginPage/LoginWithCode/LoginWithCode.stories.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,32 @@ | ||
import { Meta, Story } from "@storybook/react"; | ||
import { message } from "antd"; | ||
import React from "react"; | ||
import { LoginWithCode, LoginWithCodeProps } from "."; | ||
|
||
const storyMeta: Meta = { | ||
title: "LoginPage/LoginWithCode", | ||
component: LoginWithCode, | ||
}; | ||
|
||
export default storyMeta; | ||
|
||
export const Overview: Story<LoginWithCodeProps> = props => { | ||
return <LoginWithCode {...props} />; | ||
}; | ||
|
||
Overview.args = { | ||
onClickButton: provider => { | ||
message.info("login with " + provider); | ||
}, | ||
sendVerificationCode: (country, phone) => { | ||
message.info("send verification code with " + country + " " + phone); | ||
return new Promise(resolve => setTimeout(() => resolve(phone === "123456"), 1000)); | ||
}, | ||
loginOrRegister: (country, phone, code) => { | ||
message.info("login with " + country + " " + phone + " " + code); | ||
return new Promise(resolve => setTimeout(() => resolve(false), 1000)); | ||
}, | ||
loginWithPassword: () => { | ||
message.info("login with password"); | ||
}, | ||
}; |
File renamed without changes.
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
Oops, something went wrong.