Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 63 additions & 16 deletions src/components/ui/AuthModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { X } from "lucide-react";
import { X, Eye, EyeOff } from "lucide-react";
import { useCurrentUser } from "@/context/CurrentUserContext";

interface AuthModalProps {
Expand All @@ -16,6 +16,9 @@ export function AuthModal({ isOpen, onClose, onLoginSuccess }: AuthModalProps) {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [busy, setBusy] = useState(false);
const [error, setError] = useState<string | null>(null);

Expand All @@ -25,6 +28,9 @@ export function AuthModal({ isOpen, onClose, onLoginSuccess }: AuthModalProps) {
setUsername("");
setEmail("");
setPassword("");
setConfirmPassword("");
setShowPassword(false);
setShowConfirmPassword(false);
setError(null);
};

Expand Down Expand Up @@ -52,6 +58,12 @@ export function AuthModal({ isOpen, onClose, onLoginSuccess }: AuthModalProps) {
return;
}

if (!isLogin && password !== confirmPassword) {
setError("Passwords do not match.");
setBusy(false);
return;
}

try {
const res = isLogin
? await login(email, password)
Expand Down Expand Up @@ -96,14 +108,12 @@ export function AuthModal({ isOpen, onClose, onLoginSuccess }: AuthModalProps) {
{isLogin ? "Welcome Back" : "Create Account"}
</h2>
{/* underline */}
<div className="w-16 h-0.5 mx-auto my-2 rounded-full
bg-gradient-to-r from-orange-500 via-orange-400 to-orange-100">
</div>

<div
className="w-16 h-0.5 mx-auto my-2 rounded-full
bg-gradient-to-r from-orange-500 via-orange-400 to-orange-100"
></div>
</div>



<form onSubmit={handleSubmit} className="space-y-3">
{/* subtitle */}
<p className="text-sm text-gray-600 dark:text-gray-300">
Expand All @@ -129,19 +139,56 @@ export function AuthModal({ isOpen, onClose, onLoginSuccess }: AuthModalProps) {
required
className="bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-300 border-gray-300 dark:border-gray-600 transition-colors"
/>
<Input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
className="bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-300 border-gray-300 dark:border-gray-600 transition-colors"
/>
<div className="relative">
<Input
type={showPassword ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
className="bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-300 border-gray-300 dark:border-gray-600 transition-colors pr-10"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:text-gray-300 dark:hover:text-gray-100"
aria-label={showPassword ? "Hide password" : "Show password"}
>
{showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
Comment on lines +151 to +158
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The password visibility toggle button lacks keyboard focus styling. Add focus-visible styles to ensure keyboard users can see which element is focused, for example: 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-orange-500'.

Copilot uses AI. Check for mistakes.
</div>

{!isLogin && (
<div className="relative">
<Input
type={showConfirmPassword ? "text" : "password"}
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
placeholder="Confirm Password"
required={!isLogin}
className="bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-300 border-gray-300 dark:border-gray-600 transition-colors pr-10"
/>
<button
type="button"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:text-gray-300 dark:hover:text-gray-100"
aria-label={showConfirmPassword ? "Hide confirm password" : "Show confirm password"}
>
{showConfirmPassword ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
Comment on lines 171 to 178
Copy link

Copilot AI Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The confirm password visibility toggle button lacks keyboard focus styling. Add focus-visible styles to ensure keyboard users can see which element is focused, for example: 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-orange-500'.

Copilot uses AI. Check for mistakes.
</div>
)}

{error && <div className="text-sm text-red-600">{error}</div>}

<Button type="submit" className="w-full" disabled={busy}>
{busy ? (isLogin ? "Logging in…" : "Signing up…") : isLogin ? "Login" : "Sign Up"}
{busy
? isLogin
? "Logging in…"
: "Signing up…"
: isLogin
? "Login"
: "Sign Up"}
</Button>
</form>

Expand Down
Loading