Skip to content

Commit e4c9a57

Browse files
committed
Donation calculator landing (#3596)
* landing markup * customizable subtitle * autoplay vid * video reorg * page meta * remove redundant styles * mobile * link space * added form * donation calculator landing-d * modal height * more button space * remove top marging * add shadows * copy update * remove landing-c
1 parent 3ac831e commit e4c9a57

File tree

13 files changed

+220
-14
lines changed

13 files changed

+220
-14
lines changed
File renamed without changes.
30.5 KB
Binary file not shown.

src/components/video/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { videos, Video } from "./video";

src/components/about-video.tsx renamed to src/components/video/video.tsx

+32-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
1-
import poster from "assets/images/about-video-preview.webp";
21
import { useEffect, useRef, useState } from "react";
3-
import subtitle from "./about-video.vtt";
2+
import aboutSubtitle from "./about.vtt";
3+
import aboutPoster from "./about.webp";
4+
import bgCalculatorPoster from "./bg-calculator.webp";
45

56
type VideoStatus = "loading" | "error" | "loaded";
67

7-
const videoUrl =
8-
"https://elktqtbc25yfiipw.public.blob.vercel-storage.com/about-better-giving-HXqlfIWwctto66xyOTStih3rWj9Ajg";
9-
export const AboutVideo = ({ classes = "" }) => {
8+
interface Vid {
9+
url: string;
10+
poster: string;
11+
subtitle?: string;
12+
}
13+
interface Props {
14+
classes?: string;
15+
vid: Vid;
16+
}
17+
18+
export const videos = {
19+
about: {
20+
url: "https://elktqtbc25yfiipw.public.blob.vercel-storage.com/about-better-giving-HXqlfIWwctto66xyOTStih3rWj9Ajg",
21+
poster: aboutPoster,
22+
subtitle: aboutSubtitle,
23+
},
24+
donation_calculator: {
25+
url: "https://elktqtbc25yfiipw.public.blob.vercel-storage.com/donation-calculator-SZju4lCvUjU6HUYWi2adrQVR9NDCaz",
26+
poster: bgCalculatorPoster,
27+
},
28+
};
29+
30+
export const Video = ({ classes = "", vid }: Props) => {
1031
const videoRef = useRef<HTMLVideoElement>(null);
1132
const containerRef = useRef<HTMLDivElement>(null);
1233
const [isIntersecting, setIsIntersecting] = useState<boolean>(false);
@@ -67,18 +88,21 @@ export const AboutVideo = ({ classes = "" }) => {
6788
</div>
6889
)}
6990
<video
70-
poster={poster}
71-
src={videoUrl}
91+
poster={vid.poster}
92+
src={vid.url}
7293
ref={videoRef}
7394
className={`absolute top-0 left-0 w-full h-full object-cover`}
7495
playsInline
7596
controls
97+
autoPlay
98+
muted
99+
loop
76100
preload="none"
77101
onError={handleError}
78102
>
79103
<track
80104
kind="captions"
81-
src={subtitle}
105+
src={vid.subtitle}
82106
srcLang="en"
83107
label="English"
84108
default
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useEffect, useState } from "react";
2+
3+
type State = "loading" | "loaded" | "error";
4+
5+
export function useHubspotDonCalculatorForm() {
6+
const [state, setState] = useState<State | undefined>();
7+
8+
//biome-ignore lint: no deps
9+
useEffect(() => {
10+
function load() {
11+
if (state === "loading" || state === "loaded") return;
12+
setState("loading");
13+
const script = document.createElement("script");
14+
script.src = "https://js-eu1.hsforms.net/forms/embed/24900163.js";
15+
script.defer = true;
16+
17+
script.onload = () => {
18+
setState("loaded");
19+
};
20+
21+
script.onerror = () => {
22+
setState("error");
23+
};
24+
25+
document.body.appendChild(script);
26+
}
27+
load();
28+
}, []);
29+
30+
return { state };
31+
}

src/pages/donation-calculator/pdf-export/page1/index.tsx

Whitespace-only changes.

src/pages/home/feature1.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Link } from "@remix-run/react";
22
import { laira } from "assets/laira/laira";
3-
import { AboutVideo } from "components/about-video";
43
import Image from "components/image";
4+
import { Video, videos } from "components/video/video";
55
import { BOOK_A_DEMO } from "constants/env";
66
import { appRoutes } from "constants/routes";
77
import { ArrowRight } from "lucide-react";
@@ -52,7 +52,7 @@ export function Feature1({ className = "" }) {
5252
long-term financial sustainability.
5353
</p>
5454

55-
<AboutVideo classes="max-w-2xl justify-self-center p-4" />
55+
<Video classes="max-w-2xl justify-self-center p-4" vid={videos.about} />
5656

5757
<ul className="mt-20 lg:divide-x divide-gray-l3 grid gap-y-20 lg:gap-y-0 lg:grid-cols-3">
5858
{items.map((item, idx) => (

src/pages/informational/nonprofit-info/hero.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Link } from "@remix-run/react";
2-
import { AboutVideo } from "components/about-video";
2+
import { Video, videos } from "components/video/video";
33
import { BOOK_A_DEMO } from "constants/env";
44
import { appRoutes } from "constants/routes";
55

@@ -38,7 +38,10 @@ export default function Hero({ className = "" }) {
3838
</Link>
3939
</div>
4040
</div>
41-
<AboutVideo classes="max-w-2xl @6xl:max-w-auto order-1 @6xl:order-2 w-full self-center" />
41+
<Video
42+
classes="max-w-2xl @6xl:max-w-auto order-1 @6xl:order-2 w-full self-center"
43+
vid={videos.about}
44+
/>
4245
{/* <Image
4346
src={benefits.donors[1].img}
4447
width={420}

src/pages/landing-a/feature.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { laira } from "assets/laira/laira";
2-
import { AboutVideo } from "components/about-video";
32
import Image from "components/image";
3+
import { Video, videos } from "components/video/video";
44

55
type TListItem = {
66
title1: string;
@@ -50,7 +50,7 @@ export function Feature({ className = "" }) {
5050
</p>
5151
</div>
5252

53-
<AboutVideo classes="max-w-2xl justify-self-center p-4" />
53+
<Video vid={videos.about} classes="max-w-2xl justify-self-center p-4" />
5454

5555
<ul className="col-span-full mt-10 lg:divide-x divide-gray-l3 grid gap-y-20 lg:gap-y-0 lg:grid-cols-3">
5656
{items.map((item, idx) => (

src/pages/landing-d/index.tsx

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Link } from "@remix-run/react";
2+
import type { MetaFunction } from "@vercel/remix";
3+
import { Footer } from "components/footer";
4+
import { DappLogo } from "components/image";
5+
import { appRoutes } from "constants/routes";
6+
import { metas } from "helpers/seo";
7+
import { Top } from "./top";
8+
export const meta: MetaFunction = () =>
9+
metas({
10+
title: "You’re Losing Donations - Find Out How Much | Better Giving",
11+
description:
12+
"Don’t let lost fees, idle cash, and missed gifts drain your nonprofit’s revenue. Use the free Better Giving Donation Calculator to see what you’re missing in under a minute.",
13+
url: "https://better.giving/see-what-youre-losing",
14+
});
15+
export default function Component() {
16+
return (
17+
<main className="w-full grid content-start pb-16 @container">
18+
<div
19+
className="sticky top-[-1px] z-50 bg-white"
20+
ref={(node) => {
21+
if (!node) return;
22+
const observer = new IntersectionObserver(
23+
([e]) => {
24+
const isIntersecting = e.intersectionRatio < 1;
25+
e.target.classList.toggle("bg-white", isIntersecting);
26+
e.target.classList.toggle("shadow-lg", isIntersecting);
27+
},
28+
{ threshold: [1] }
29+
);
30+
observer.observe(node);
31+
}}
32+
>
33+
<div className="xl:container xl:mx-auto px-10 py-4 flex justify-between gap-x-4 items-center">
34+
<DappLogo classes="h-12" />
35+
<Link
36+
to={appRoutes.signup}
37+
className="btn btn-blue max-xl:text-sm normal-case text-nowrap px-6 py-2 rounded-full"
38+
>
39+
Sign up
40+
</Link>
41+
</div>
42+
</div>
43+
44+
<Top classes="xl:container xl:mx-auto px-10 bg-transparent mt-16 mb-28" />
45+
46+
<Footer classes="xl:container xl:mx-auto px-10" />
47+
</main>
48+
);
49+
}

src/pages/landing-d/top.tsx

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { useNavigate } from "@remix-run/react";
2+
import { Modal } from "components/modal";
3+
import { Video, videos } from "components/video";
4+
import { useHubspotDonCalculatorForm } from "hooks/use-hubspot-don-calculator-form";
5+
import { useState } from "react";
6+
7+
export function Top({ classes = "" }) {
8+
const [open, setOpen] = useState(false);
9+
const navigate = useNavigate();
10+
const { state } = useHubspotDonCalculatorForm();
11+
return (
12+
<section
13+
className={`${classes} grid grid-cols-1 lg:grid-cols-2 gap-12 p-4 @container`}
14+
>
15+
<div className="h-fit self-center relative">
16+
<Tooltip className="max-xl:hidden absolute -right-24 z-10" />
17+
<Video
18+
vid={videos.donation_calculator}
19+
classes="relative shadow-xl shadow-black/10 rounded-lg"
20+
/>
21+
</div>
22+
<div>
23+
<h1 className="text-4.5xl leading-snug max-lg:text-center text-right">
24+
<div className="relative w-fit max-lg:mx-auto lg:ml-auto text-nowrap">
25+
You're Losing Donations{" "}
26+
<span className="absolute bottom-2 left-0 w-full h-4 bg-blue-l3 -z-10"></span>
27+
</div>
28+
</h1>
29+
<p className="mb-4 text-gray-d4 text-lg max-lg:text-center text-right mt-4">
30+
Thousands of dollars are slipping through the cracks every year – lost
31+
to fees, idle cash, and outdated donation methods.
32+
</p>
33+
<p className="mb-4 text-gray-d4 font-semibold text-lg max-lg:text-center text-right mt-4">
34+
The longer you wait, the more you miss.
35+
</p>
36+
<div className="mb-4 text-gray-d4 text-lg max-lg:text-center text-right">
37+
See see exactly how much revenue is being left on the table – and how
38+
quickly you could turn that around.
39+
</div>
40+
<button
41+
onClick={() => {
42+
if (state !== "loaded") {
43+
return navigate("/donation-calculator");
44+
}
45+
setOpen(true);
46+
}}
47+
type="button"
48+
className="mt-8 shadow-xl capitalize shadow-black/10 btn btn-blue text-center lg:text-right justify-self-center lg:justify-self-end rounded-lg py-4 px-8 w-full md:w-auto"
49+
>
50+
See what you're losing
51+
</button>
52+
{open && (
53+
<Modal
54+
classes="fixed-center z-10 grid text-gray-d4 bg-white w-[calc(100%-2.5rem)] max-w-4xl rounded-lg"
55+
open={open}
56+
onClose={() => setOpen(false)}
57+
>
58+
<div
59+
className="hs-form-frame"
60+
data-region="eu1"
61+
data-form-id="17bb2a2b-322c-4a8c-b8d6-50bb1a59881c"
62+
data-portal-id="24900163"
63+
/>
64+
</Modal>
65+
)}
66+
67+
<p className="max-lg:text-center text-right text-sm text-gray mt-2">
68+
"It takes less than a minute — find out how much you're leaving on the
69+
table."
70+
</p>
71+
</div>
72+
</section>
73+
);
74+
}
75+
76+
function Tooltip({ className = "" }) {
77+
return (
78+
<span className={`text-gray-d4 ${className}`}>
79+
<svg
80+
xmlns="http://www.w3.org/2000/svg"
81+
width="99"
82+
height="50.6"
83+
viewBox="0 0 90.2 49.5"
84+
fill="none"
85+
className="rotate-320"
86+
>
87+
<path
88+
d="M86.5184 47.9261C86.9386 48.7464 87.891 49.0896 88.7113 48.6694C89.5316 48.2492 89.8748 47.2968 89.4546 46.4765L86.5184 47.9261ZM0.750315 12.1702C0.292122 12.8603 0.480187 13.7913 1.17037 14.2495L12.4175 21.7161C13.1077 22.1743 14.0387 21.9863 14.4969 21.2961C14.955 20.6059 14.767 19.675 14.0768 19.2168L4.07932 12.5797L10.7164 2.58225C11.1746 1.89207 10.9865 0.961128 10.2963 0.502936C9.60613 0.0447435 8.67518 0.232808 8.21699 0.92299L0.750315 12.1702ZM89.4546 46.4765C82.5494 32.4322 74.5 21.0234 61.0685 14.6649C47.6713 8.3195 29.2413 7.1537 1.87328 12.6825L2.46732 15.6231C28.8433 10.0943 46.2017 11.7514 58.6565 17.6475C71.0773 23.5315 78.7006 33.7177 86.5184 47.9261L89.4546 46.4765Z"
89+
fill="#183244"
90+
/>
91+
</svg>
92+
<p className="text-gray-d4 -top-6 left-8 relative -rotate-[12deg] font-gochi text-nowrap">
93+
Watch how it works!
94+
</p>
95+
</span>
96+
);
97+
}

vite.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const rmx = remix({
2121
r("donate-fund/:fundId", "./pages/donate-fund/redirect.ts");
2222
r("fundraisers/:fundId/donate", "./pages/donate-fund/index.tsx");
2323
r("donate-thanks", "./pages/donate-thanks.tsx");
24+
r("see-what-youre-losing", "./pages/landing-d/index.tsx");
2425
r("simplify-fundraising-maximize-impact", "./pages/landing-a/index.tsx", {
2526
id: "page-a",
2627
});

0 commit comments

Comments
 (0)