fix and update
This commit is contained in:
@@ -134,6 +134,8 @@ export default function LoginPage() {
|
||||
|
||||
const [otpChannels, setOtpChannels] = useState<OtpChannel[]>([]);
|
||||
|
||||
const [otpBackupChannels, setOtpBackupChannels] = useState<OtpChannel[]>([]);
|
||||
|
||||
const [showMethods, setShowMethods] = useState(false);
|
||||
|
||||
const [step, setStep] = useState<Step>('identify');
|
||||
@@ -397,6 +399,8 @@ export default function LoginPage() {
|
||||
|
||||
setOtpChannels(result.otpChannels ?? []);
|
||||
|
||||
setOtpBackupChannels(result.otpBackupChannels ?? []);
|
||||
|
||||
|
||||
|
||||
if (result.isTotpEnabled) {
|
||||
@@ -413,6 +417,8 @@ export default function LoginPage() {
|
||||
|
||||
const channels = result.otpChannels ?? [];
|
||||
|
||||
const backupChannels = result.otpBackupChannels ?? [];
|
||||
|
||||
if (channels.length > 1) {
|
||||
|
||||
setStep('otpChannel');
|
||||
@@ -429,6 +435,24 @@ export default function LoginPage() {
|
||||
|
||||
}
|
||||
|
||||
// Нет основных каналов, но есть резервные — даём выбрать резервную доставку.
|
||||
|
||||
if (backupChannels.length > 1) {
|
||||
|
||||
setStep('otpChannel');
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (backupChannels.length === 1) {
|
||||
|
||||
await requestLoginOtp(backupChannels[0].channel, identifier);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (result.hasPassword) {
|
||||
|
||||
setStep('password');
|
||||
@@ -658,7 +682,7 @@ export default function LoginPage() {
|
||||
|
||||
function renderAlternativeMethods(includeOtpRequest: boolean) {
|
||||
|
||||
const hasAlternatives = includeOtpRequest || methods.length > 0;
|
||||
const hasAlternatives = includeOtpRequest || methods.length > 0 || otpBackupChannels.length > 0;
|
||||
|
||||
if (!hasAlternatives) return null;
|
||||
|
||||
@@ -736,6 +760,50 @@ export default function LoginPage() {
|
||||
|
||||
})}
|
||||
|
||||
{otpBackupChannels.length ? (
|
||||
|
||||
<>
|
||||
|
||||
<p className="px-1 pt-1 text-xs uppercase tracking-wide text-[#7d818d]">Резервные контакты</p>
|
||||
|
||||
{otpBackupChannels.map((channel) => {
|
||||
|
||||
const Icon = channelIcon[channel.channel] ?? Mail;
|
||||
|
||||
return (
|
||||
|
||||
<button
|
||||
|
||||
key={channel.channel}
|
||||
|
||||
type="button"
|
||||
|
||||
onClick={() => void requestLoginOtp(channel.channel)}
|
||||
|
||||
disabled={isSubmitting}
|
||||
|
||||
className="flex w-full items-center gap-3 rounded-[16px] bg-[#2a2c36] p-3 text-left hover:bg-[#33353f] disabled:opacity-50"
|
||||
|
||||
>
|
||||
|
||||
<Icon className="h-5 w-5 text-[#b9bdc9]" />
|
||||
|
||||
<span className="text-sm">
|
||||
|
||||
{channelLabel[channel.channel] ?? 'Резервный код'} — {channel.masked}
|
||||
|
||||
</span>
|
||||
|
||||
</button>
|
||||
|
||||
);
|
||||
|
||||
})}
|
||||
|
||||
</>
|
||||
|
||||
) : null}
|
||||
|
||||
</div>
|
||||
|
||||
) : null}
|
||||
@@ -1012,6 +1080,50 @@ export default function LoginPage() {
|
||||
|
||||
})}
|
||||
|
||||
{otpBackupChannels.length ? (
|
||||
|
||||
<>
|
||||
|
||||
<p className="px-1 pt-2 text-xs uppercase tracking-wide text-[#7d818d]">Резервные контакты</p>
|
||||
|
||||
{otpBackupChannels.map((channel) => {
|
||||
|
||||
const Icon = channelIcon[channel.channel] ?? Mail;
|
||||
|
||||
return (
|
||||
|
||||
<button
|
||||
|
||||
key={channel.channel}
|
||||
|
||||
type="button"
|
||||
|
||||
disabled={isSubmitting}
|
||||
|
||||
onClick={() => void requestLoginOtp(channel.channel)}
|
||||
|
||||
className="flex w-full items-center gap-3 rounded-[16px] bg-[#2a2c36] p-3 text-left hover:bg-[#33353f] disabled:opacity-50"
|
||||
|
||||
>
|
||||
|
||||
<Icon className="h-5 w-5 text-[#b9bdc9]" />
|
||||
|
||||
<span className="text-sm">
|
||||
|
||||
{channelLabel[channel.channel] ?? 'Резервный код'} — {channel.masked}
|
||||
|
||||
</span>
|
||||
|
||||
</button>
|
||||
|
||||
);
|
||||
|
||||
})}
|
||||
|
||||
</>
|
||||
|
||||
) : null}
|
||||
|
||||
</div>
|
||||
|
||||
{totpChallengeToken ? (
|
||||
|
||||
Reference in New Issue
Block a user