Add invite page with invitation code validation
This commit introduces a new invite page where users can input and validate their invitation codes. The page redirects valid users to the related event, and displays appropriate errors for invalid or failed submissions. It includes a responsive UI with loading states and error handling.
This commit is contained in:
118
frontend/src/app/(public)/invite/page.tsx
Normal file
118
frontend/src/app/(public)/invite/page.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Navbar from "@/components/layout/navbar";
|
||||
import { client } from "@/client/client.gen";
|
||||
|
||||
export default function InvitePage() {
|
||||
const [invitationCode, setInvitationCode] = useState("");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!invitationCode.trim()) {
|
||||
setError("Please enter your invitation code");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
// Assuming your API has an endpoint to validate invitation codes
|
||||
const response = await client.get({
|
||||
url: `/api/v1/guests/validate-code/${invitationCode}`,
|
||||
throwOnError: true,
|
||||
});
|
||||
|
||||
// If successful, redirect to the event page
|
||||
const data: any = response.data;
|
||||
router.push(`/events/${data.event_slug}?guest_id=${data.guest_id}`);
|
||||
} catch (err: any) {
|
||||
console.error("Error validating invitation code:", err);
|
||||
|
||||
if (err.response?.status === 404) {
|
||||
setError("Invalid invitation code. Please check and try again.");
|
||||
} else {
|
||||
setError("An error occurred. Please try again later.");
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<div className="min-h-screen bg-gradient-to-b from-blue-50 to-white dark:from-slate-900 dark:to-slate-800 py-12">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-md mx-auto">
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-3xl font-bold text-slate-900 dark:text-white">
|
||||
Enter Invitation Code
|
||||
</h1>
|
||||
<p className="mt-2 text-slate-600 dark:text-slate-300">
|
||||
Please enter the invitation code you received
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white dark:bg-slate-800 rounded-lg shadow-md p-8">
|
||||
{error && (
|
||||
<div className="mb-6 p-4 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 text-red-600 dark:text-red-400 rounded-lg">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="invitationCode"
|
||||
className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2"
|
||||
>
|
||||
Invitation Code
|
||||
</label>
|
||||
<input
|
||||
id="invitationCode"
|
||||
type="text"
|
||||
value={invitationCode}
|
||||
onChange={(e) => setInvitationCode(e.target.value)}
|
||||
placeholder="Enter your code here"
|
||||
className="w-full p-3 text-center text-lg tracking-wider uppercase border border-slate-300 dark:border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-slate-700 dark:text-white"
|
||||
autoComplete="off"
|
||||
autoFocus
|
||||
maxLength={16}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading}
|
||||
className="w-full py-3 px-4 bg-blue-600 text-white font-medium rounded-md shadow hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
{isLoading ? "Checking..." : "Continue to Event"}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center">
|
||||
<p className="text-sm text-slate-600 dark:text-slate-400">
|
||||
Need to manage your events?{" "}
|
||||
<Link
|
||||
href="/login"
|
||||
className="text-blue-600 dark:text-blue-400 font-medium hover:underline"
|
||||
>
|
||||
Sign in
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user