mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-25 11:42:30 +01:00
update MFA screen to use updated auth layout
This commit is contained in:
parent
be4595ddce
commit
d016c5b69a
@ -102,7 +102,7 @@ export const Input = styled.input<{ error?: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
export const PasswordResetLink = styled.button`
|
||||
export const Link = styled.button`
|
||||
margin-bottom: 20px;
|
||||
margin-top: 4px;
|
||||
padding: 2px 0;
|
||||
|
@ -2,7 +2,7 @@ import { Routes } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import React from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { ReactComponent as SpacebarLogoBlue } from "../assets/images/logo/Logo-Blue.svg";
|
||||
import { useAppStore } from "../stores/AppStore";
|
||||
import {
|
||||
IAPIError,
|
||||
@ -11,154 +11,23 @@ import {
|
||||
IAPITOTPRequest,
|
||||
} from "../utils/interfaces/api";
|
||||
import { messageFromFieldError } from "../utils/messageFromFieldError";
|
||||
import Button from "./Button";
|
||||
import Container from "./Container";
|
||||
|
||||
export const Wrapper = styled(Container)`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: var(--background-secondary);
|
||||
`;
|
||||
|
||||
export const AuthBox = styled(Container)`
|
||||
background-color: var(--background-primary-alt);
|
||||
padding: 32px;
|
||||
font-size: 18px;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
width: 480px;
|
||||
border-radius: 18px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const HeaderContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const Header = styled.h1`
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
font-size: 24px;
|
||||
color: var(--text);
|
||||
`;
|
||||
|
||||
export const SubHeader = styled.h2`
|
||||
color: var(--text-muted);
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
margin-bottom: 40px;
|
||||
`;
|
||||
|
||||
export const FormContainer = styled.form`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const InputContainer = styled.h1<{ marginBottom: boolean }>`
|
||||
margin-bottom: ${(props) => (props.marginBottom ? "20px" : "0")};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
`;
|
||||
|
||||
export const LabelWrapper = styled.div<{ error?: boolean }>`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 8px;
|
||||
color: ${(props) => (props.error ? "var(--error)" : "#b1b5bc")};
|
||||
`;
|
||||
|
||||
export const InputErrorText = styled.label`
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
`;
|
||||
|
||||
export const InputLabel = styled.label`
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
`;
|
||||
|
||||
export const InputWrapper = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export const Input = styled.input<{ error?: boolean }>`
|
||||
outline: none;
|
||||
background: var(--background-secondary);
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
flex: 1;
|
||||
border-radius: 12px;
|
||||
color: var(--text);
|
||||
margin: 0;
|
||||
border: none;
|
||||
aria-invalid: ${(props) => (props.error ? "true" : "false")};
|
||||
`;
|
||||
|
||||
export const Link = styled.button`
|
||||
margin-bottom: 20px;
|
||||
margin-top: 4px;
|
||||
padding: 2px 0;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
color: var(--text-link);
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
export const LoginButton = styled(Button)`
|
||||
margin-bottom: 8px;
|
||||
width: 100%;
|
||||
min-width: 130px;
|
||||
min-height: 44px;
|
||||
`;
|
||||
|
||||
export const RegisterContainer = styled.div`
|
||||
margin-top: 4px;
|
||||
text-align: initial;
|
||||
`;
|
||||
|
||||
export const RegisterLabel = styled.label`
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
export const RegisterLink = styled.button`
|
||||
font-size: 14px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-link);
|
||||
|
||||
@media (max-width: 480px) {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Divider = styled.span`
|
||||
padding: 0 4px;
|
||||
`;
|
||||
import {
|
||||
AuthContainer,
|
||||
Divider,
|
||||
FormContainer,
|
||||
Header,
|
||||
HeaderContainer,
|
||||
Input,
|
||||
InputContainer,
|
||||
InputErrorText,
|
||||
InputLabel,
|
||||
InputWrapper,
|
||||
LabelWrapper,
|
||||
Link,
|
||||
SubHeader,
|
||||
SubmitButton,
|
||||
Wrapper,
|
||||
} from "./AuthComponents";
|
||||
|
||||
type FormValues = {
|
||||
code: string;
|
||||
@ -224,8 +93,9 @@ function MFA(props: IAPILoginResponseMFARequired) {
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<AuthBox>
|
||||
<AuthContainer>
|
||||
<HeaderContainer>
|
||||
<SpacebarLogoBlue height={48} width="auto" />
|
||||
<Header>Two-factor authentication</Header>
|
||||
<SubHeader>
|
||||
You can use a backup code or your two-factor
|
||||
@ -238,9 +108,7 @@ function MFA(props: IAPILoginResponseMFARequired) {
|
||||
style={{ marginTop: 0 }}
|
||||
>
|
||||
<LabelWrapper error={!!errors.code}>
|
||||
<InputLabel>
|
||||
Enter Spacebar Auth/Backup Code
|
||||
</InputLabel>
|
||||
<InputLabel>Enter 2FA/Backup Code</InputLabel>
|
||||
{errors.code && (
|
||||
<InputErrorText>
|
||||
<>
|
||||
@ -262,13 +130,13 @@ function MFA(props: IAPILoginResponseMFARequired) {
|
||||
</InputWrapper>
|
||||
</InputContainer>
|
||||
|
||||
<LoginButton
|
||||
<SubmitButton
|
||||
variant="primary"
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
>
|
||||
Log In
|
||||
</LoginButton>
|
||||
</SubmitButton>
|
||||
|
||||
{/* <Link
|
||||
onClick={() => {
|
||||
@ -295,7 +163,7 @@ function MFA(props: IAPILoginResponseMFARequired) {
|
||||
</Link>
|
||||
</FormContainer>
|
||||
</HeaderContainer>
|
||||
</AuthBox>
|
||||
</AuthContainer>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
81
src/components/modals/ForgotPasswordModal.tsx
Normal file
81
src/components/modals/ForgotPasswordModal.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import { useModals } from "@mattjennings/react-modal-stack";
|
||||
import styled from "styled-components";
|
||||
import Icon from "../Icon";
|
||||
import {
|
||||
ModalActionItem,
|
||||
ModalCloseWrapper,
|
||||
ModalContainer,
|
||||
ModalFooter,
|
||||
ModalHeaderText,
|
||||
ModalWrapper,
|
||||
ModelContentContainer,
|
||||
} from "./ModalComponents";
|
||||
|
||||
export const ModalHeader = styled.div`
|
||||
padding: 16px;
|
||||
`;
|
||||
|
||||
const SubmitButton = styled(ModalActionItem)`
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
font-size: 16px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--background-secondary-highlight);
|
||||
}
|
||||
`;
|
||||
|
||||
function ForgotPasswordModal() {
|
||||
const { openModal, closeModal } = useModals();
|
||||
|
||||
if (!open) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalContainer>
|
||||
<ModalWrapper>
|
||||
<ModalCloseWrapper>
|
||||
<button
|
||||
onClick={closeModal}
|
||||
style={{
|
||||
background: "none",
|
||||
border: "none",
|
||||
outline: "none",
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
icon="mdiClose"
|
||||
size={1}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
color: "var(--text)",
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
</ModalCloseWrapper>
|
||||
|
||||
<ModalHeader>
|
||||
<ModalHeaderText>Instructions Sent</ModalHeaderText>
|
||||
</ModalHeader>
|
||||
|
||||
<ModelContentContainer>
|
||||
We sent instructions to change your password to
|
||||
user@example.com, please check both your inbox and spam
|
||||
folder.
|
||||
</ModelContentContainer>
|
||||
|
||||
<ModalFooter>
|
||||
<SubmitButton
|
||||
variant="filled"
|
||||
size="med"
|
||||
onClick={closeModal}
|
||||
>
|
||||
Okay
|
||||
</SubmitButton>
|
||||
</ModalFooter>
|
||||
</ModalWrapper>
|
||||
</ModalContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default ForgotPasswordModal;
|
@ -1,8 +1,10 @@
|
||||
import HCaptchaLib from "@hcaptcha/react-hcaptcha";
|
||||
import { useModals } from "@mattjennings/react-modal-stack";
|
||||
import { Routes } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import React from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ReactComponent as SpacebarLogoBlue } from "../assets/images/logo/Logo-Blue.svg";
|
||||
import {
|
||||
AuthContainer,
|
||||
AuthSwitchPageContainer,
|
||||
@ -17,13 +19,13 @@ import {
|
||||
InputLabel,
|
||||
InputWrapper,
|
||||
LabelWrapper,
|
||||
PasswordResetLink,
|
||||
SubHeader,
|
||||
SubmitButton,
|
||||
Wrapper,
|
||||
} from "../components/AuthComponents";
|
||||
import HCaptcha, { HeaderContainer } from "../components/HCaptcha";
|
||||
import MFA from "../components/MFA";
|
||||
import ForgotPasswordModal from "../components/modals/ForgotPasswordModal";
|
||||
import { AUTH_NO_BRANDING, useAppStore } from "../stores/AppStore";
|
||||
import {
|
||||
IAPILoginRequest,
|
||||
@ -47,6 +49,7 @@ function LoginPage() {
|
||||
const [mfaData, setMfaData] =
|
||||
React.useState<IAPILoginResponseMFARequired>();
|
||||
const captchaRef = React.useRef<HCaptchaLib>(null);
|
||||
const { openModal } = useModals();
|
||||
|
||||
const {
|
||||
register,
|
||||
@ -154,6 +157,10 @@ function LoginPage() {
|
||||
onSubmit();
|
||||
};
|
||||
|
||||
const forgotPassword = () => {
|
||||
openModal(ForgotPasswordModal);
|
||||
};
|
||||
|
||||
if (captchaSiteKey) {
|
||||
return (
|
||||
<HCaptcha
|
||||
@ -178,11 +185,7 @@ function LoginPage() {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{/* Note: This would need to change depending on the theme */}
|
||||
<img
|
||||
src="https://github.com/spacebarchat/spacebarchat/blob/master/branding/png/Spacebar__Logo-White.png?raw=true"
|
||||
height={48}
|
||||
/>
|
||||
<SpacebarLogoBlue height={48} width="auto" />
|
||||
<SubHeader noBranding>Log into Spacebar</SubHeader>
|
||||
</>
|
||||
)}
|
||||
@ -216,7 +219,7 @@ function LoginPage() {
|
||||
</InputWrapper>
|
||||
</InputContainer>
|
||||
|
||||
<InputContainer marginBottom={false}>
|
||||
<InputContainer marginBottom>
|
||||
<LabelWrapper error={!!errors.password}>
|
||||
<InputLabel>Password</InputLabel>
|
||||
{errors.password && (
|
||||
@ -239,17 +242,10 @@ function LoginPage() {
|
||||
</InputWrapper>
|
||||
</InputContainer>
|
||||
|
||||
<PasswordResetLink
|
||||
onClick={() => {
|
||||
window.open(
|
||||
"https://youtu.be/dQw4w9WgXcQ",
|
||||
"_blank",
|
||||
);
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
{/* TODO: I need to figure this out, clicking this should submit the form or even a different function with only email being required */}
|
||||
{/* <PasswordResetLink onClick={forgotPassword} type="button">
|
||||
Forgot your password?
|
||||
</PasswordResetLink>
|
||||
</PasswordResetLink> */}
|
||||
|
||||
<SubmitButton
|
||||
variant="primary"
|
||||
|
@ -3,6 +3,7 @@ import { Routes } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import React from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ReactComponent as SpacebarLogoBlue } from "../assets/images/logo/Logo-Blue.svg";
|
||||
import {
|
||||
AuthContainer,
|
||||
AuthSwitchPageContainer,
|
||||
@ -178,11 +179,7 @@ function RegistrationPage() {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{/* Note: This would need to change depending on the theme */}
|
||||
<img
|
||||
src="https://github.com/spacebarchat/spacebarchat/blob/master/branding/png/Spacebar__Logo-White.png?raw=true"
|
||||
height={48}
|
||||
/>
|
||||
<SpacebarLogoBlue height={48} width="auto" />
|
||||
<SubHeader noBranding>Create an account</SubHeader>
|
||||
</>
|
||||
)}
|
||||
|
Loading…
Reference in New Issue
Block a user