Skip to content

Commit a2f398d

Browse files
authored
feat: added waitlist page (#299)
* feat: added waitlist page * feat: made footer stick to bottom
1 parent 858d0c3 commit a2f398d

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
"use client";
2+
3+
import { useState, FormEvent } from "react";
4+
import { Button, Input } from "@/components/ui";
5+
import { CheckCircle2 } from "lucide-react";
6+
7+
export default function WaitlistForm() {
8+
const [email, setEmail] = useState("");
9+
const [name, setName] = useState("");
10+
const [status, setStatus] = useState<
11+
"idle" | "loading" | "success" | "error"
12+
>("idle");
13+
const [errorMessage, setErrorMessage] = useState("");
14+
15+
const validateEmail = (email: string): boolean => {
16+
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
17+
return re.test(email);
18+
};
19+
20+
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
21+
e.preventDefault();
22+
23+
if (!name.trim()) {
24+
setStatus("error");
25+
setErrorMessage("Please enter your name");
26+
return;
27+
}
28+
29+
if (!validateEmail(email)) {
30+
setStatus("error");
31+
setErrorMessage("Please enter a valid email address");
32+
return;
33+
}
34+
35+
setStatus("loading");
36+
setErrorMessage("");
37+
38+
// Simulate API call - replace with actual endpoint
39+
try {
40+
await new Promise((resolve) => setTimeout(resolve, 1500));
41+
setStatus("success");
42+
setName("");
43+
setEmail("");
44+
// eslint-disable-next-line
45+
} catch (_) {
46+
setStatus("error");
47+
setErrorMessage("Something went wrong. Please try again.");
48+
}
49+
};
50+
51+
return (
52+
<section className="relative py-12 md:py-[105px] flex flex-col items-center text-center overflow-visible px-5">
53+
{/* Background Pattern */}
54+
<img
55+
src="/swirl-pattern.png"
56+
alt=""
57+
aria-hidden="true"
58+
className="absolute inset-0 w-full h-full object-cover pointer-events-none z-0"
59+
/>
60+
61+
{/* Main Content */}
62+
<div className="relative z-10 flex flex-col items-center max-w-2xl w-full">
63+
{/* Heading */}
64+
<h1 className="max-w-[736px] font-medium text-[48px] leading-[110%] md:text-[80px] md:leading-[120%] -tracking-[0.05em] md:-tracking-[10%] bg-[linear-gradient(263.91deg,#CEFFF7_30.32%,#59B1A6_93.13%)] bg-clip-text text-transparent mb-4 md:mb-6">
65+
Join the Waitlist
66+
</h1>
67+
68+
{/* Early Access Message */}
69+
<div className="mb-8 md:mb-12 space-y-4">
70+
<p className="text-[#E0FFFB] text-base md:text-[18px]/[140%] tracking-[2%] max-w-xl">
71+
PrediFi is currently in <span className="font-semibold text-white">early access</span> and coming soon!
72+
</p>
73+
<p className="text-[#B3CECB] text-sm md:text-base tracking-[2%] max-w-lg">
74+
Be among the first to experience decentralized prediction markets.
75+
Join our waitlist to get early access and stay updated on our launch.
76+
</p>
77+
</div>
78+
79+
{/* Form Card */}
80+
<div className="w-full max-w-md text-left">
81+
{status !== "success" ? (
82+
<form onSubmit={handleSubmit} className="space-y-6">
83+
<div className="rounded-[24px] md:rounded-[33px] bg-[#03353A4D] backdrop-blur-[15px] p-6 md:py-10 md:px-8 space-y-6 border border-[#ffffff0d]">
84+
<div className="space-y-4">
85+
<Input
86+
id="name"
87+
name="name"
88+
type="text"
89+
label="Full Name"
90+
required
91+
value={name}
92+
onChange={(e) => setName(e.target.value)}
93+
placeholder="Enter your full name"
94+
disabled={status === "loading"}
95+
className="bg-[#001518] border-[#EBFDFF33] text-white placeholder:text-[#B3CECB] focus-visible:ring-[#37B7C3]"
96+
/>
97+
<Input
98+
id="email"
99+
name="email"
100+
type="email"
101+
label="Email Address"
102+
required
103+
value={email}
104+
onChange={(e) => setEmail(e.target.value)}
105+
placeholder="Enter your email address"
106+
disabled={status === "loading"}
107+
className="bg-[#001518] border-[#EBFDFF33] text-white placeholder:text-[#B3CECB] focus-visible:ring-[#37B7C3]"
108+
/>
109+
</div>
110+
111+
{status === "error" && (
112+
<div className="rounded-lg bg-red-900/20 border border-red-800 p-3">
113+
<p className="text-sm text-red-400 text-center">
114+
{errorMessage}
115+
</p>
116+
</div>
117+
)}
118+
119+
<Button
120+
type="submit"
121+
disabled={status === "loading"}
122+
variant="primary"
123+
size="large"
124+
loading={status === "loading"}
125+
className="w-full bg-[#37B7C3] text-black hover:bg-[#2aa0ac] font-semibold text-base md:text-lg"
126+
>
127+
{status === "loading" ? "Joining Waitlist..." : "Join Waitlist"}
128+
</Button>
129+
</div>
130+
</form>
131+
) : (
132+
<div className="rounded-[24px] md:rounded-[33px] bg-[#03353A4D] backdrop-blur-[15px] p-8 md:py-12 md:px-10 border border-[#37B7C3]/30 space-y-6">
133+
<div className="mx-auto w-16 h-16 bg-[#37B7C3] rounded-full flex items-center justify-center">
134+
<CheckCircle2 className="w-8 h-8 text-black" />
135+
</div>
136+
<div className="space-y-3">
137+
<h3 className="text-2xl md:text-3xl font-semibold text-white">
138+
You&apos;re on the list!
139+
</h3>
140+
<p className="text-[#B3CECB] text-sm md:text-base">
141+
Thank you for joining the waitlist. We&apos;ll notify you when
142+
PrediFi launches so you can be among the first to start predicting!
143+
</p>
144+
</div>
145+
</div>
146+
)}
147+
</div>
148+
149+
{/* Additional Info */}
150+
<div className="mt-8 md:mt-12 text-[#758382] text-xs md:text-sm max-w-lg">
151+
<p>
152+
By joining the waitlist, you&apos;ll receive updates about our launch,
153+
early access opportunities, and exclusive features.
154+
</p>
155+
</div>
156+
</div>
157+
</section>
158+
);
159+
}

frontend/app/waitlist/page.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Navbar from "../(marketing)/components/NavBar";
2+
import Footer from "../(marketing)/components/Footer";
3+
import WaitlistForm from "./components/WaitlistForm";
4+
5+
export default function WaitlistPage() {
6+
return (
7+
<div className="text-sm min-h-screen bg-[#001112] flex flex-col">
8+
<Navbar />
9+
10+
<main className="w-screen overflow-x-hidden flex-1">
11+
<WaitlistForm />
12+
</main>
13+
14+
<Footer />
15+
</div>
16+
);
17+
}

0 commit comments

Comments
 (0)