pwf-website-new/client/src/pages/auth-page.tsx

279 lines
12 KiB
TypeScript

import { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useAuth, registrationSchema, RegistrationData } from "@/hooks/use-auth";
import { useLocation } from "wouter";
import { loginSchema, Login } from "@shared/schema";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Loader2 } from "lucide-react";
export default function AuthPage() {
const { user, loginMutation, registerMutation } = useAuth();
const [_, navigate] = useLocation();
const [activeTab, setActiveTab] = useState<"login" | "register">("login");
// Redirect if user is already logged in
useEffect(() => {
if (user) {
navigate("/");
}
}, [user, navigate]);
// Set meta data for SEO
useEffect(() => {
document.title = "Login or Sign Up | Pilates with Fadia";
const metaDescription = document.querySelector('meta[name="description"]');
if (metaDescription) {
metaDescription.setAttribute("content", "Create an account or login to book classes, access community features, and more with Pilates with Fadia.");
}
}, []);
// Login form
const loginForm = useForm<Login>({
resolver: zodResolver(loginSchema),
defaultValues: {
username: "",
password: "",
},
});
// Registration form
const registerForm = useForm<RegistrationData>({
resolver: zodResolver(registrationSchema),
defaultValues: {
username: "",
email: "",
fullName: "",
password: "",
confirmPassword: "",
},
});
const onLoginSubmit = (data: Login) => {
loginMutation.mutate(data);
};
const onRegisterSubmit = (data: RegistrationData) => {
// Remove confirmPassword before sending to API
const { confirmPassword, ...registerData } = data;
registerMutation.mutate(registerData);
};
return (
<div className="min-h-screen bg-gray-50 py-16">
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col md:flex-row gap-8 max-w-7xl mx-auto">
{/* Left column with auth forms */}
<div className="md:w-1/2">
<Tabs value={activeTab} onValueChange={(value) => setActiveTab(value as "login" | "register")} className="w-full">
<TabsList className="grid w-full grid-cols-2 mb-8">
<TabsTrigger value="login">Login</TabsTrigger>
<TabsTrigger value="register">Sign Up</TabsTrigger>
</TabsList>
<TabsContent value="login">
<Card>
<CardHeader>
<CardTitle>Welcome Back</CardTitle>
<CardDescription>Login to access your account</CardDescription>
</CardHeader>
<CardContent>
<Form {...loginForm}>
<form onSubmit={loginForm.handleSubmit(onLoginSubmit)} className="space-y-6">
<FormField
control={loginForm.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="Enter your username" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={loginForm.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input type="password" placeholder="Enter your password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<Checkbox id="remember-me" />
<label htmlFor="remember-me" className="text-sm text-gray-600">Remember me</label>
</div>
<a href="#" className="text-sm text-teal hover:underline">Forgot password?</a>
</div>
<Button
type="submit"
className="w-full bg-teal text-white"
disabled={loginMutation.isPending}
>
{loginMutation.isPending ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Logging in...
</>
) : (
"Login"
)}
</Button>
</form>
</Form>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="register">
<Card>
<CardHeader>
<CardTitle>Create an Account</CardTitle>
<CardDescription>Sign up to book classes and access exclusive content</CardDescription>
</CardHeader>
<CardContent>
<Form {...registerForm}>
<form onSubmit={registerForm.handleSubmit(onRegisterSubmit)} className="space-y-6">
<FormField
control={registerForm.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="Choose a username" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={registerForm.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" placeholder="Enter your email" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={registerForm.control}
name="fullName"
render={({ field }) => (
<FormItem>
<FormLabel>Full Name</FormLabel>
<FormControl>
<Input placeholder="Enter your full name" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={registerForm.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input type="password" placeholder="Create a password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={registerForm.control}
name="confirmPassword"
render={({ field }) => (
<FormItem>
<FormLabel>Confirm Password</FormLabel>
<FormControl>
<Input type="password" placeholder="Confirm your password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className="w-full bg-purple text-white"
disabled={registerMutation.isPending}
>
{registerMutation.isPending ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Creating account...
</>
) : (
"Sign Up"
)}
</Button>
</form>
</Form>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
{/* Right column with hero section */}
<div className="md:w-1/2 bg-teal rounded-lg p-8 text-white flex flex-col justify-center">
<h2 className="text-3xl md:text-4xl font-playfair font-bold mb-6">Begin Your Pilates Journey</h2>
<p className="text-teal-50 mb-6">
Join our community of wellness enthusiasts and transform your body and mind through the art of Pilates. Create an account to access:
</p>
<ul className="space-y-3 mb-8">
<li className="flex items-center">
<i className="fas fa-check-circle mr-2"></i>
<span>Convenient class booking and scheduling</span>
</li>
<li className="flex items-center">
<i className="fas fa-check-circle mr-2"></i>
<span>Community resources and support</span>
</li>
<li className="flex items-center">
<i className="fas fa-check-circle mr-2"></i>
<span>Special member-only workshops</span>
</li>
<li className="flex items-center">
<i className="fas fa-check-circle mr-2"></i>
<span>Personalized fitness tracking</span>
</li>
</ul>
<div>
<p className="italic text-sm text-teal-100 border-l-4 border-white pl-4 py-2 font-aref text-lg">
"The mind, when housed within a healthful body, possesses a glorious sense of power."
</p>
</div>
</div>
</div>
</div>
</div>
);
}