tahamajs/IE / Projects /front /src /components /auth /RegisterWindow.tsx
tahamajs's picture
download
raw
6.82 kB
import { useState } from "react";
import { useRegister } from "@/hooks/useRegister";
import { GlassCard } from "@/components/ui/GlassCard";
import { Mail, Lock, User, Eye, EyeOff, UserPlus, AlertCircle } from "lucide-react";
import { motion } from "framer-motion";
interface RegisterWindowProps {
onLoginClick?: () => void;
onSuccess?: () => void;
}
export function RegisterWindow({ onLoginClick, onSuccess }: RegisterWindowProps) {
const { form, updateForm, error, loading, handleSubmit, passwordStrength, strengthColor, strengthText } = useRegister();
const [showPassword, setShowPassword] = useState(false);
const [showConfirm, setShowConfirm] = useState(false);
const onSubmit = async (e: React.FormEvent) => {
await handleSubmit(e);
if (!error) {
onSuccess?.();
// Close window and show login
window.dispatchEvent(new CustomEvent("openWindow", { detail: { app: "login" } }));
if (onLoginClick) onLoginClick();
}
};
return (
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
className="w-full max-w-md"
>
<GlassCard className="p-6 md:p-8">
<div className="text-center mb-6">
<h2 className="text-2xl font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">
Join IE Research
</h2>
<p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
Start collaborating with researchers worldwide
</p>
</div>
<form onSubmit={onSubmit} className="space-y-4">
{/* Username */}
<div className="relative">
<User className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type="text"
name="username"
placeholder="Username (min 3 characters)"
value={form.username}
onChange={(e) => updateForm("username", e.target.value)}
className="w-full pl-9 pr-3 py-2 bg-white/50 dark:bg-gray-800/50 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary"
required
disabled={loading}
/>
</div>
{/* Email */}
<div className="relative">
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type="email"
name="email"
placeholder="Email (optional)"
value={form.email}
onChange={(e) => updateForm("email", e.target.value)}
className="w-full pl-9 pr-3 py-2 bg-white/50 dark:bg-gray-800/50 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary"
disabled={loading}
/>
</div>
{/* Password */}
<div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type={showPassword ? "text" : "password"}
name="password"
placeholder="Password"
value={form.password}
onChange={(e) => updateForm("password", e.target.value)}
className="w-full pl-9 pr-10 py-2 bg-white/50 dark:bg-gray-800/50 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary"
required
disabled={loading}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showPassword ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
</button>
</div>
{/* Confirm Password */}
<div className="relative">
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input
type={showConfirm ? "text" : "password"}
name="confirmPassword"
placeholder="Confirm Password"
value={form.confirmPassword}
onChange={(e) => updateForm("confirmPassword", e.target.value)}
className="w-full pl-9 pr-10 py-2 bg-white/50 dark:bg-gray-800/50 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-primary"
required
disabled={loading}
/>
<button
type="button"
onClick={() => setShowConfirm(!showConfirm)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showConfirm ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
</button>
</div>
{/* Password strength indicator */}
<div>
<div className="h-1 w-full bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
<div className={`h-full ${strengthColor()}`} style={{ width: `${passwordStrength * 25}%` }} />
</div>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
Password strength: <span className="font-medium">{strengthText()}</span> (min 6 chars)
</p>
</div>
{/* Error message */}
{error && (
<div className="flex items-center gap-2 p-2 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm">
<AlertCircle className="w-4 h-4" />
<span>{error}</span>
</div>
)}
{/* Submit button */}
<button
type="submit"
disabled={loading}
className="w-full py-2.5 rounded-lg bg-gradient-to-r from-primary to-secondary text-white font-semibold flex items-center justify-center gap-2 transition hover:opacity-90 disabled:opacity-50"
>
{loading ? (
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
) : (
<UserPlus className="w-5 h-5" />
)}
{loading ? "Creating account..." : "Create account"}
</button>
<div className="text-center text-sm text-gray-600 dark:text-gray-400">
Already have an account?{" "}
<button
type="button"
onClick={() => window.dispatchEvent(new CustomEvent("openWindow", { detail: { app: "login" } }))}
className="text-primary font-semibold hover:underline"
>
Sign In
</button>
</div>
</form>
</GlassCard>
</motion.div>
);
}

Xet Storage Details

Size:
6.82 kB
·
Xet hash:
b4dcc3b2eebab8b690181a7444490f55b87b1181d85805df715af64112a5e5ff

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.