Skip to content
Snippets Groups Projects
Unverified Commit bec0524a authored by Alexander Polyankin's avatar Alexander Polyankin Committed by GitHub
Browse files

Migrate NewsletterForm to formik (#26192)

parent d9a57083
Branches
Tags
No related merge requests found
import styled from "@emotion/styled";
import { color } from "metabase/lib/colors";
import Icon from "metabase/components/Icon";
import Button from "metabase/core/components/Button";
import Form from "metabase/core/components/Form";
import FormInput from "metabase/core/components/FormInput";
export const FormRoot = styled.div`
export const EmailFormRoot = styled.div`
position: relative;
padding: 2rem;
border: 1px solid ${color("border")};
border-radius: 0.5rem;
`;
export const FormLabel = styled.div`
export const EmailFormLabel = styled.div`
position: absolute;
top: 0;
left: 0;
......@@ -20,57 +21,57 @@ export const FormLabel = styled.div`
transform: translateY(-50%);
`;
export const FormLabelCard = styled.div`
export const EmailFormLabelCard = styled.div`
display: flex;
padding: 0 1.5rem;
color: ${color("text-medium")};
background-color: ${color("white")};
`;
export const FormLabelIcon = styled(Icon)`
export const EmailFormLabelIcon = styled(Icon)`
width: 1rem;
height: 1rem;
margin-right: 0.5rem;
`;
export const FormLabelText = styled.div`
export const EmailFormLabelText = styled.div`
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
`;
export const FormHeader = styled.div`
export const EmailFormHeader = styled.div`
color: ${color("text-medium")};
font-size: 1rem;
font-weight: 700;
margin-bottom: 1.5rem;
`;
export const FormContainer = styled.div`
export const EmailForm = styled(Form)`
display: flex;
`;
export const FormFieldContainer = styled.div`
export const EmailFormInput = styled(FormInput)`
flex: 1 0 auto;
margin-right: 1rem;
margin-bottom: -1.5em;
margin-bottom: 0;
`;
export const FormSuccessContainer = styled.div`
export const EmailFormSuccessContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
padding: 0.5rem;
`;
export const FormSuccessIcon = styled(Icon)`
export const EmailFormSuccessIcon = styled(Icon)`
color: ${color("success")};
width: 1rem;
height: 1rem;
margin-right: 1rem;
`;
export const FormSuccessText = styled.div`
export const EmailFormSuccessText = styled.div`
color: ${color("success")};
font-size: 1rem;
font-weight: bold;
......
import React, { useState } from "react";
import React, { useCallback, useState } from "react";
import { t } from "ttag";
import Users from "metabase/entities/users";
import Form from "metabase/containers/FormikForm";
import * as Yup from "yup";
import FormProvider from "metabase/core/components/FormProvider";
import FormSubmitButton from "metabase/core/components/FormSubmitButton";
import { SubscribeInfo } from "metabase-types/store";
import {
FormContainer,
FormFieldContainer,
FormHeader,
FormLabel,
FormLabelCard,
FormLabelIcon,
FormLabelText,
FormRoot,
FormSuccessContainer,
FormSuccessIcon,
FormSuccessText,
EmailForm,
EmailFormHeader,
EmailFormLabel,
EmailFormLabelCard,
EmailFormLabelIcon,
EmailFormLabelText,
EmailFormRoot,
EmailFormSuccessContainer,
EmailFormSuccessIcon,
EmailFormSuccessText,
EmailFormInput,
} from "./NewsletterForm.styled";
import { FormProps } from "./types";
const NewsletterSchema = Yup.object({
email: Yup.string()
.required(t`required`)
.email(t`must be a valid email address`),
});
export interface NewsletterFormProps {
initialEmail?: string;
......@@ -30,50 +36,52 @@ const NewsletterForm = ({
const initialValues = { email: initialEmail };
const [isSubscribed, setIsSubscribed] = useState(false);
const onSubmit = async ({ email }: SubscribeInfo) => {
await onSubscribe(email);
setIsSubscribed(true);
};
const handleSubmit = useCallback(
async ({ email }: SubscribeInfo) => {
await onSubscribe(email);
setIsSubscribed(true);
},
[onSubscribe],
);
return (
<FormRoot>
<FormLabel>
<FormLabelCard>
<FormLabelIcon name="mail" />
<FormLabelText>{t`Metabase Newsletter`}</FormLabelText>
</FormLabelCard>
</FormLabel>
<FormHeader>
<EmailFormRoot>
<EmailFormLabel>
<EmailFormLabelCard>
<EmailFormLabelIcon name="mail" />
<EmailFormLabelText>{t`Metabase Newsletter`}</EmailFormLabelText>
</EmailFormLabelCard>
</EmailFormLabel>
<EmailFormHeader>
{t`Get infrequent emails about new releases and feature updates.`}
</FormHeader>
</EmailFormHeader>
{!isSubscribed && (
<Form<{ email: string }>
form={Users.forms.newsletter}
<FormProvider
initialValues={initialValues}
submitTitle={t`Subscribe`}
onSubmit={onSubmit}
validationSchema={NewsletterSchema}
onSubmit={handleSubmit}
>
{({ Form, FormField, FormSubmit }: FormProps) => (
<Form>
<FormContainer>
<FormFieldContainer>
<FormField name="email" />
</FormFieldContainer>
<FormSubmit primary={false} />
</FormContainer>
</Form>
)}
</Form>
<EmailForm>
<EmailFormInput
name="email"
type="email"
placeholder="nicetoseeyou@email.com"
autoFocus
fullWidth
/>
<FormSubmitButton title={t`Subscribe`} />
</EmailForm>
</FormProvider>
)}
{isSubscribed && (
<FormSuccessContainer>
<FormSuccessIcon name="check" />
<FormSuccessText>
<EmailFormSuccessContainer>
<EmailFormSuccessIcon name="check" />
<EmailFormSuccessText>
{t`You're subscribed. Thanks for using Metabase!`}
</FormSuccessText>
</FormSuccessContainer>
</EmailFormSuccessText>
</EmailFormSuccessContainer>
)}
</FormRoot>
</EmailFormRoot>
);
};
......
import React, { FormHTMLAttributes } from "react";
import { render, screen } from "@testing-library/react";
import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import NewsletterForm from "./NewsletterForm";
const FormMock = (props: FormHTMLAttributes<HTMLFormElement>) => (
<form {...props}>
<button>Subscribe</button>
</form>
);
jest.mock("metabase/containers/FormikForm", () => FormMock);
jest.mock("metabase/entities/users", () => ({
forms: { newsletter: jest.fn() },
}));
describe("NewsletterForm", () => {
it("allows to submit the form with an email", async () => {
const onSubscribe = jest.fn();
it("should allow to submit the form with the provided email", async () => {
const email = "user@metabase.test";
const onSubscribe = jest.fn().mockResolvedValue({});
render(<NewsletterForm onSubscribe={onSubscribe} />);
render(<NewsletterForm initialEmail={email} onSubscribe={onSubscribe} />);
userEvent.click(screen.getByText("Subscribe"));
expect(await screen.findByText(/You're subscribed/)).toBeInTheDocument();
await waitFor(() => {
expect(onSubscribe).toHaveBeenCalledWith(email);
expect(screen.getByText(/You're subscribed/)).toBeInTheDocument();
});
});
});
import { ComponentType } from "react";
export interface FormField {
name: string;
}
export interface FormProps {
Form: ComponentType;
FormField: ComponentType<FormFieldProps>;
FormSubmit: ComponentType<FormSubmitProps>;
}
export interface FormFieldProps {
name: string;
}
export interface FormSubmitProps {
primary?: boolean;
submitTitle?: string;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment