Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
91 changes: 66 additions & 25 deletions src/contexts/AuthContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,47 +110,88 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}, []);

const login = async (email: string, password: string): Promise<AuthResult> => {
setIsLoading(true);
const { error } = await supabase.auth.signInWithPassword({ email, password });
setIsLoading(false);

try {
const { error } = await supabase.auth.signInWithPassword({
email: email.trim().toLowerCase(),
password,
});

if (error) {
// eslint-disable-next-line no-console
console.error("login error:", error);

const message = error.message.toLowerCase();

if (
message.includes("invalid login credentials") ||
message.includes("invalid credentials") ||
message.includes("email not confirmed")
) {
return { ok: false, error: "Incorrect email or password." };
}

return { ok: false, error: error.message };
}

return { ok: true };
};
} finally {
}
};

const register = async (
email: string,
password: string,
username: string
): Promise<AuthResult> => {
setIsLoading(true);
email: string,
password: string,
username: string
): Promise<AuthResult> => {
setIsLoading(true);

const { data, error } = await supabase.auth.signUp({
email,
password,
options: { data: { username, xp: 0, badges: [] } },
});
const { data: existingUser, error: existingUserError } = await supabase
.from("users")
.select("id")
.eq("email", email)
.maybeSingle();

if (existingUserError) {
setIsLoading(false);
console.error("existing user check error:", existingUserError);
return { ok: false, error: "Unable to verify email. Please try again." };
}

if (error) {
// eslint-disable-next-line no-console
console.error("register error:", error);
return { ok: false, error: error.message };
if (existingUser) {
setIsLoading(false);
return { ok: false, error: "An account with this email already exists." };
}

const { data, error } = await supabase.auth.signUp({
email,
password,
options: { data: { username, xp: 0, badges: [] } },
});

setIsLoading(false);

if (error) {
console.error("register error:", error);

const message = error.message.toLowerCase();

if (
message.includes("already registered") ||
message.includes("already exists") ||
message.includes("user already registered")
) {
return { ok: false, error: "An account with this email already exists." };
}

// If email confirmations are enabled, user may be created but no session exists yet.
// We treat this as success and let UI instruct user.
// eslint-disable-next-line no-console
console.log("register ok:", { userId: data.user?.id, session: !!data.session });
return { ok: false, error: error.message };
}

return { ok: true };
};
console.log("register ok:", { userId: data.user?.id, session: !!data.session });
if (!data.session && !data.user?.identities?.length) {
return { ok: false, error: "An account with this email already exists." };
}
return { ok: true };
};

const logout = () => {
setIsLoading(true);
Expand Down
11 changes: 3 additions & 8 deletions src/pages/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import { useNavigate, Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useToast } from "@/hooks/use-toast";
import { toast } from "sonner";
import { useAuth } from "@/contexts/AuthContext";
import { Eye, EyeOff } from "lucide-react";

export function LoginPage() {
const navigate = useNavigate();
const { toast } = useToast();
const { login, isLoading } = useAuth();

const [email, setEmail] = useState("");
Expand All @@ -25,15 +24,11 @@ export function LoginPage() {
const res = await login(email, password);

if (!res.ok) {
toast({
title: "Sign in failed",
description: res.error,
variant: "destructive",
});
toast.error("Sign in failed", { description: res.error });
return;
}

toast({ title: "Signed in", description: "Welcome back." });
toast.success("Signed in", { description: "Welcome back." });
navigate("/dashboard");
};

Expand Down