Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show opt in modal for scorecard #45

Merged
merged 4 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/components/index-page/IndexScorecard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ import React from "react";

import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
import { useModal } from "@launchware/replicator";
import { StaticImage } from "gatsby-plugin-image";

import { ScorecardModal } from "../scorecard/ScorecardModal";
import "./css/index-scorecard.css";

export const IndexScorecard = () => {
const { modal, setVisibility } = useModal(() => <ScorecardModal />, { scrollToTop: false });

return (
<section className="index-scorecard">
{modal}
<div className="index-scorecard__contents">
<div className="index-scorecard__text-container">
<h2 className="index-scorecard__heading">Is your project set up for success?</h2>
Expand All @@ -21,8 +25,8 @@ export const IndexScorecard = () => {
Success Scorecard. By answering just 21 quick questions, you’ll see if you’re set up for
success – or what you need to change for you to reach your goals.
</p>
<button className="index-scorecard__button button" type="button">
<span>Download the Scorecard{" "}</span>
<button className="index-scorecard__button button" type="button" onClick={() => setVisibility(true)}>
<span>Download the Scorecard </span>
<FontAwesomeIcon icon={faArrowRight} />
</button>
</div>
Expand Down
26 changes: 26 additions & 0 deletions src/components/scorecard/ScorecardModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";

import "@launchware/replicator/dist/css/Modal/modal.css";
import { StaticImage } from "gatsby-plugin-image";

import { ScorecardOptInForm } from "./ScorecardOptInForm";
import "./css/scorecard-modal.css";

export const ScorecardModal = () => (
<div className="scorecard-modal">
{/* <StaticImage
alt=""
className="scorecard-modal__decorative-square"
role="presentation"
src="../../images/decorations/decorative_square.png"
/> */}
<div className="scorecard-modal__text-container">
<h2 className="scorecard-modal__heading">The Software Success Scorecard</h2>
<p className="scorecard-modal__text">
By answering just 21 quick questions, you’ll see if you’re set up for success – or what you
need to change for you to reach your goals.
</p>
<ScorecardOptInForm />
</div>
</div>
);
89 changes: 89 additions & 0 deletions src/components/scorecard/ScorecardOptInForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from "react";

import { zodResolver } from "@hookform/resolvers/zod";
import { SubmitHandler, useForm } from "react-hook-form";

import { useScorecardOptIn } from "./hooks/useScorecardOptIn";
import { scorecardOptInSchema, ScorecardOptInSchema } from "./models/ScorecardOptInSchema";
import { getFieldClassName } from "../general/services/getFieldClassName";
import { useNotifications } from "../../hooks/useNotifications";
import "./css/scorecard-form.css";

export const ScorecardOptInForm = () => {
const { addNotification } = useNotifications();
const {
handleSubmit,
register,
formState: { errors },
} = useForm<ScorecardOptInSchema>({
resolver: zodResolver(scorecardOptInSchema),
});

const {
mutate: postScorecardOptIn,
error: backendErrors,
isSuccess,
isLoading,
} = useScorecardOptIn();

const onSubmit: SubmitHandler<ScorecardOptInSchema> = (formValues) => {
postScorecardOptIn(formValues, {
onSuccess: () => {
addNotification("Thanks for contacting us!", {
appearance: "success",
});
},
onError: (err: Error) => {
addNotification("There was a problem, please try again later.", {
appearance: "error",
});
},
});
};

const blockClassName = "scorecard-form";
const errorClassPrefix = `${blockClassName}__input`;

const successContent = "Thank you! Check your inbox for the scorecard."

const formContent = (
<form
className="scorecard-form__form"
data-netlify="true"
name="scorecardOptIn"
onSubmit={handleSubmit(onSubmit)}
>
<input
autoFocus
className={getFieldClassName({
errorClassPrefix,
errors,
fieldName: "firstName",
className: "scorecard-form__input",
})}
placeholder="Your first name"
type="text"
id="firstName"
{...register("firstName")}
/>
{errors.firstName && <p className="scorecard-form__error">First name required</p>}
<input
className={getFieldClassName({
errorClassPrefix,
errors,
fieldName: "email",
className: "scorecard-form__input",
})}
placeholder="Your email"
type="text"
id="email"
{...register("email")}
/>
{errors.email && <p className="scorecard-form__error">Email required</p>}
<input type="hidden" value="scorecardOptIn" {...register("form-name")} />
<input className="button" type="submit" disabled={isLoading} value="Download the Scorecard" />
</form>
);

return (isSuccess ? successContent : formContent)
};
51 changes: 51 additions & 0 deletions src/components/scorecard/css/scorecard-form.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.scorecard-form {
@apply lg:py-0 relative z-30 md:overflow-x-clip;
}

.scorecard-form__contents {
@apply contents-container;
@apply relative;
}

.scorecard-form__alternate-circle {
@apply absolute -z-10 -right-72 lg:-top-72 md:top-80 hidden md:inline;
}

.scorecard-form__text-container {
@apply flex flex-col md:items-start;
@apply text-left w-full;
}

.scorecard-form__heading {
@apply text-4xl mb-6 font-semibold;
}

.scorecard-form__text {
@apply text-base text-launch-black-80 mb-4 leading-relaxed;
}

.scorecard-form__form {
@apply form;
}

.scorecard-form__input,
.scorecard-form__textarea,
.scorecard-form__select {
@apply form__field;
}

.scorecard-form__select {
@apply form__dropdown;
}

.scorecard-form__input_error {
@apply form__field_error;
}

.scorecard-form__error {
@apply form__error;
}

.scorecard-form__image-container {
@apply pt-8 md:pt-0;
}
35 changes: 35 additions & 0 deletions src/components/scorecard/css/scorecard-modal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.modal__contents,
.modal__contents_large {
@apply p-0 border-none max-w-2xl mx-2 md:mx-auto;
}

.modal__header {
@apply -mb-10 pr-4 pt-3 relative z-10;
}

.scorecard-modal {
@apply parent-section;
@apply p-0 relative overflow-clip flex-col md:flex-row;
}

div.scorecard-modal__decorative-square {
@apply absolute hidden md:block;
@apply -left-40 -bottom-40;
}

.scorecard-modal__text-container {
@apply w-full p-8 md:p-16;
@apply bg-launch-neutral-20;
}

.scorecard-modal__heading {
@apply text-4xl pb-4;
}

.scorecard-modal__text {
@apply text-base text-launch-black-80;
}

.scorecard-modal__widget-container {
@apply md:w-1/2 p-8 md:p-16;
}
24 changes: 24 additions & 0 deletions src/components/scorecard/hooks/useScorecardOptIn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useMutation } from "@tanstack/react-query";
import { AxiosError } from "axios";
import { useApiClient } from "../../../api-client/hooks/useApiClient";
import { ScorecardOptInSchema } from "../models/ScorecardOptInSchema";

export const useScorecardOptIn = () => {
const client = useApiClient();

return useMutation(
async (data: ScorecardOptInSchema) => {
const resp = await client.post(`/general-opt-in`, data, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
return resp.data;
},
{
onError: (err: Error | AxiosError) => {
console.error(err);
},
},
);
};
9 changes: 9 additions & 0 deletions src/components/scorecard/models/ScorecardOptInSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { z } from "zod";

export const scorecardOptInSchema = z.object({
firstName: z.string().trim().nonempty(),
email: z.string().email(),
"form-name": z.string().default("scorecardOptIn"),
});

export type ScorecardOptInSchema = z.infer<typeof scorecardOptInSchema>;
Loading