Some checks failed
Build Frontend / build (push) Failing after 7s
Replaces imports from 'components/ui' with 'components/common' across the app and dashboard pages, and updates model and API imports to use new paths under 'lib'. Removes redundant authentication checks from several dashboard pages. Adds new dashboard components and utility files, and reorganizes hooks and services into the 'lib' directory for improved structure.
169 lines
6.6 KiB
TypeScript
169 lines
6.6 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import { Button } from "@/components/common/button";
|
|
import { Input } from "@/components/common/input";
|
|
import { Label } from "@/components/common/label";
|
|
import { Loader2, ArrowRight } from "lucide-react";
|
|
import { motion } from "framer-motion";
|
|
import { toast } from "@/lib/hooks/use-toast";
|
|
|
|
// Matches LoginPage background
|
|
const AuthBackground = () => (
|
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
|
<div className="absolute inset-0 bg-black" />
|
|
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-br from-indigo-500/20 via-purple-500/10 to-transparent" />
|
|
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-blue-500/20 rounded-full blur-3xl opacity-50 animate-pulse" />
|
|
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-purple-500/20 rounded-full blur-3xl opacity-50 animate-pulse delay-1000" />
|
|
</div>
|
|
);
|
|
|
|
export default function RegisterPage() {
|
|
const [username, setUsername] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [invitationCode, setInvitationCode] = useState("");
|
|
const [loading, setLoading] = useState(false);
|
|
const router = useRouter();
|
|
|
|
async function handleRegister(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
setLoading(true);
|
|
|
|
try {
|
|
const res = await fetch(`/api/auth/register`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ username, password, invitationCode }),
|
|
});
|
|
|
|
const data = await res.json();
|
|
|
|
if (res.ok) {
|
|
toast({
|
|
title: "Account Created! 🎉",
|
|
description: "Welcome to Ember Market. Redirecting to login...",
|
|
variant: "default",
|
|
});
|
|
setTimeout(() => router.push("/auth/login"), 1500);
|
|
} else {
|
|
toast({
|
|
title: "Registration Failed",
|
|
description: data.error || "Please check your details.",
|
|
variant: "destructive",
|
|
});
|
|
setLoading(false);
|
|
}
|
|
} catch (error) {
|
|
toast({
|
|
title: "Error",
|
|
description: "Something went wrong. Please try again.",
|
|
variant: "destructive",
|
|
});
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="relative flex items-center justify-center min-h-screen overflow-hidden">
|
|
<AuthBackground />
|
|
|
|
<div className="flex flex-col items-center w-full px-4 text-center z-10">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.5 }}
|
|
className="w-full max-w-md"
|
|
>
|
|
<div className="overflow-hidden rounded-2xl border border-white/10 shadow-2xl bg-black/40 backdrop-blur-xl p-8">
|
|
<div className="text-center mb-8">
|
|
<h2 className="text-xl font-semibold text-white">Create your account</h2>
|
|
<p className="mt-2 text-sm text-zinc-400">Start managing your store today</p>
|
|
</div>
|
|
|
|
<form className="space-y-5" onSubmit={handleRegister}>
|
|
<div className="space-y-4 text-left">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="username" className="text-zinc-300">Username</Label>
|
|
<Input
|
|
id="username"
|
|
name="username"
|
|
type="text"
|
|
autoComplete="username"
|
|
required
|
|
value={username}
|
|
onChange={(e) => setUsername(e.target.value)}
|
|
className="bg-white/5 border-white/10 text-white placeholder:text-zinc-500 focus:border-indigo-500/50 focus:ring-indigo-500/20 transition-all duration-300"
|
|
placeholder="Choose a username"
|
|
disabled={loading}
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="password" className="text-zinc-300">Password</Label>
|
|
<Input
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
autoComplete="new-password"
|
|
required
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
className="bg-white/5 border-white/10 text-white placeholder:text-zinc-500 focus:border-indigo-500/50 focus:ring-indigo-500/20 transition-all duration-300"
|
|
placeholder="Create a strong password"
|
|
disabled={loading}
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="invitationCode" className="text-zinc-300">Invitation Code</Label>
|
|
<Input
|
|
id="invitationCode"
|
|
name="invitationCode"
|
|
type="text"
|
|
required
|
|
value={invitationCode}
|
|
onChange={(e) => setInvitationCode(e.target.value)}
|
|
className="bg-white/5 border-white/10 text-white placeholder:text-zinc-500 focus:border-indigo-500/50 focus:ring-indigo-500/20 transition-all duration-300"
|
|
placeholder="Enter your invite code"
|
|
disabled={loading}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<Button
|
|
type="submit"
|
|
className="w-full h-11 font-medium bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500 text-white shadow-lg shadow-indigo-500/25 transition-all duration-300"
|
|
disabled={loading}
|
|
>
|
|
{loading ? (
|
|
<span className="flex items-center justify-center gap-2">
|
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
Creating account...
|
|
</span>
|
|
) : (
|
|
"Create Account"
|
|
)}
|
|
</Button>
|
|
</form>
|
|
|
|
<div className="mt-8 pt-6 border-t border-white/10 text-center">
|
|
<p className="text-sm text-zinc-400">
|
|
Already have an account?{" "}
|
|
<Link
|
|
href="/auth/login"
|
|
className="text-indigo-400 hover:text-indigo-300 font-medium transition-colors inline-flex items-center gap-1"
|
|
>
|
|
Sign in <ArrowRight className="w-3 h-3" />
|
|
</Link>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
|