diff --git a/src/routes/auth.tsx b/src/routes/auth.tsx new file mode 100644 index 0000000..2371882 --- /dev/null +++ b/src/routes/auth.tsx @@ -0,0 +1,99 @@ +import { createFileRoute, useNavigate } from "@tanstack/react-router"; +import { useState } from "react"; +import { z } from "zod"; +import { supabase } from "@/integrations/supabase/client"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; +import { toast } from "sonner"; +import { GraduationCap } from "lucide-react"; + +const searchSchema = z.object({ mode: z.enum(["signin", "signup"]).optional() }); + +export const Route = createFileRoute("/auth")({ + validateSearch: searchSchema, + head: () => ({ meta: [{ title: "Sign in — Bayside Academy" }] }), + component: AuthPage, +}); + +function AuthPage() { + const navigate = useNavigate(); + const { mode } = Route.useSearch(); + const [tab, setTab] = useState<"signin" | "signup">(mode ?? "signin"); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [fullName, setFullName] = useState(""); + const [loading, setLoading] = useState(false); + + const onSignIn = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + const { error } = await supabase.auth.signInWithPassword({ email, password }); + setLoading(false); + if (error) return toast.error(error.message); + navigate({ to: "/dashboard" }); + }; + + const onSignUp = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + const { error } = await supabase.auth.signUp({ + email, + password, + options: { emailRedirectTo: window.location.origin, data: { full_name: fullName } }, + }); + setLoading(false); + if (error) return toast.error(error.message); + toast.success("Account created. You can sign in now."); + setTab("signin"); + }; + + const onGoogle = async () => { + // Native Supabase OAuth: redirects the browser to Google, then back to + // redirectTo. supabase-js (detectSessionInUrl) restores the session on + // return, and useAuth's onAuthStateChange picks it up. + const { error } = await supabase.auth.signInWithOAuth({ + provider: "google", + options: { redirectTo: `${window.location.origin}/dashboard` }, + }); + if (error) toast.error(error.message ?? "Google sign-in failed"); + }; + + return ( +
+