Frontend Revamp
This commit is contained in:
@@ -4,6 +4,12 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
|
|
||||||
|
<!-- Google Fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Nunito+Sans:wght@400;600;700;800&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
@@ -17,7 +23,7 @@
|
|||||||
work correctly both with client-side routing and a non-root public URL.
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>Membershi Website</title>
|
<title>LOAF - Lesbians Over Age Fifty</title>
|
||||||
<script src="#"></script>
|
<script src="#"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
22
src/App.css
22
src/App.css
@@ -5,28 +5,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', sans-serif;
|
font-family: 'Nunito Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', sans-serif;
|
||||||
background-color: #FDFCF8;
|
background-color: #FFFFFF;
|
||||||
color: #3D405B;
|
color: #422268;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
font-family: 'Fraunces', serif;
|
font-family: 'Inter', sans-serif;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fraunces {
|
.inter {
|
||||||
font-family: 'Fraunces', serif;
|
font-family: 'Inter', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dm-sans {
|
.nunito-sans {
|
||||||
font-family: 'DM Sans', sans-serif;
|
font-family: 'Nunito Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-warm-gradient {
|
.bg-purple-gradient {
|
||||||
background: linear-gradient(135deg, rgba(242, 204, 143, 0.2) 0%, rgba(224, 122, 95, 0.2) 100%);
|
background: linear-gradient(135deg, rgba(100, 76, 159, 0.2) 0%, rgba(72, 40, 110, 0.2) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-soft-mesh {
|
.bg-soft-mesh {
|
||||||
background: radial-gradient(ellipse at top right, rgba(242, 204, 143, 0.4) 0%, #FDFCF8 50%, #FDFCF8 100%);
|
background: radial-gradient(ellipse at top right, rgba(221, 216, 235, 0.4) 0%, #FFFFFF 50%, #FFFFFF 100%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,29 +20,29 @@ code {
|
|||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 0 0% 3.9%;
|
--foreground: 280 47% 27%;
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
--card-foreground: 0 0% 3.9%;
|
--card-foreground: 280 47% 27%;
|
||||||
--popover: 0 0% 100%;
|
--popover: 0 0% 100%;
|
||||||
--popover-foreground: 0 0% 3.9%;
|
--popover-foreground: 280 47% 27%;
|
||||||
--primary: 0 0% 9%;
|
--primary: 280 47% 27%;
|
||||||
--primary-foreground: 0 0% 98%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--secondary: 0 0% 96.1%;
|
--secondary: 268 33% 89%;
|
||||||
--secondary-foreground: 0 0% 9%;
|
--secondary-foreground: 280 47% 27%;
|
||||||
--muted: 0 0% 96.1%;
|
--muted: 268 43% 95%;
|
||||||
--muted-foreground: 0 0% 45.1%;
|
--muted-foreground: 268 35% 47%;
|
||||||
--accent: 0 0% 96.1%;
|
--accent: 17 100% 73%;
|
||||||
--accent-foreground: 0 0% 9%;
|
--accent-foreground: 280 47% 27%;
|
||||||
--destructive: 0 84.2% 60.2%;
|
--destructive: 0 84.2% 60.2%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 0 0% 89.8%;
|
--border: 268 33% 89%;
|
||||||
--input: 0 0% 89.8%;
|
--input: 268 33% 89%;
|
||||||
--ring: 0 0% 3.9%;
|
--ring: 268 35% 47%;
|
||||||
--chart-1: 12 76% 61%;
|
--chart-1: 268 36% 46%;
|
||||||
--chart-2: 173 58% 39%;
|
--chart-2: 17 100% 73%;
|
||||||
--chart-3: 197 37% 24%;
|
--chart-3: 268 33% 89%;
|
||||||
--chart-4: 43 74% 66%;
|
--chart-4: 280 44% 29%;
|
||||||
--chart-5: 27 87% 67%;
|
--chart-5: 268 35% 47%;
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
.dark {
|
.dark {
|
||||||
|
|||||||
@@ -83,19 +83,19 @@ const ChangePasswordRequired = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-md mx-auto px-6 py-12">
|
<div className="max-w-md mx-auto px-6 py-12">
|
||||||
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg">
|
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg">
|
||||||
<div className="mb-8 text-center">
|
<div className="mb-8 text-center">
|
||||||
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#FFEBEE] mb-4">
|
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#FFEBEE] mb-4">
|
||||||
<AlertTriangle className="h-8 w-8 text-[#E07A5F]" />
|
<AlertTriangle className="h-8 w-8 text-orange-500" />
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Password Change Required
|
Password Change Required
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Your password was reset by an administrator. Please create a new password to continue.
|
Your password was reset by an administrator. Please create a new password to continue.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -111,7 +111,7 @@ const ChangePasswordRequired = () => {
|
|||||||
value={formData.currentPassword}
|
value={formData.currentPassword}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="Enter temporary password"
|
placeholder="Enter temporary password"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ const ChangePasswordRequired = () => {
|
|||||||
value={formData.newPassword}
|
value={formData.newPassword}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="Enter new password (min. 6 characters)"
|
placeholder="Enter new password (min. 6 characters)"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -139,15 +139,15 @@ const ChangePasswordRequired = () => {
|
|||||||
value={formData.confirmPassword}
|
value={formData.confirmPassword}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="Re-enter new password"
|
placeholder="Re-enter new password"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-[#FFF3E0] border-l-4 border-[#E07A5F] p-4 rounded-lg">
|
<div className="bg-[#f1eef9] border-l-4 border-[#664fa3] p-4 rounded-lg">
|
||||||
<div className="flex items-start">
|
<div className="flex items-start">
|
||||||
<Lock className="h-5 w-5 text-[#E07A5F] mr-2 mt-0.5 flex-shrink-0" />
|
<Lock className="h-5 w-5 text-[#664fa3] mr-2 mt-0.5 flex-shrink-0" />
|
||||||
<div className="text-sm text-[#6B708D]">
|
<div className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
<p className="font-medium text-[#3D405B] mb-1">Password Requirements:</p>
|
<p className="font-medium text-[#422268] mb-1">Password Requirements:</p>
|
||||||
<ul className="list-disc list-inside space-y-1">
|
<ul className="list-disc list-inside space-y-1">
|
||||||
<li>At least 6 characters long</li>
|
<li>At least 6 characters long</li>
|
||||||
<li>Both passwords must match</li>
|
<li>Both passwords must match</li>
|
||||||
@@ -159,17 +159,17 @@ const ChangePasswordRequired = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="w-full bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
className="w-full bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
||||||
>
|
>
|
||||||
{loading ? 'Changing Password...' : 'Change Password'}
|
{loading ? 'Changing Password...' : 'Change Password'}
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<div className="text-center pt-4 border-t border-[#EAE0D5]">
|
<div className="text-center pt-4 border-t border-[#ddd8eb]">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleLogout}
|
onClick={handleLogout}
|
||||||
className="text-[#6B708D] hover:text-[#E07A5F] text-sm underline"
|
className="text-[#664fa3] hover:text-[#ff9e77] text-sm underline"
|
||||||
>
|
>
|
||||||
Logout instead
|
Logout instead
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ const Dashboard = () => {
|
|||||||
|
|
||||||
const getStatusBadge = (status) => {
|
const getStatusBadge = (status) => {
|
||||||
const statusConfig = {
|
const statusConfig = {
|
||||||
pending_email: { icon: Clock, label: 'Pending Email', className: 'bg-[#F2CC8F] text-[#3D405B]' },
|
pending_email: { icon: Clock, label: 'Pending Email', className: 'bg-orange-100 text-orange-700' },
|
||||||
pending_approval: { icon: Clock, label: 'Pending Approval', className: 'bg-[#A3B1C6] text-white' },
|
pending_approval: { icon: Clock, label: 'Pending Approval', className: 'bg-gray-200 text-gray-700' },
|
||||||
pre_approved: { icon: CheckCircle, label: 'Pre-Approved', className: 'bg-[#81B29A] text-white' },
|
pre_approved: { icon: CheckCircle, label: 'Pre-Approved', className: 'bg-[#81B29A] text-white' },
|
||||||
payment_pending: { icon: AlertCircle, label: 'Payment Pending', className: 'bg-[#E07A5F] text-white' },
|
payment_pending: { icon: AlertCircle, label: 'Payment Pending', className: 'bg-orange-500 text-white' },
|
||||||
active: { icon: CheckCircle, label: 'Active', className: 'bg-[#81B29A] text-white' },
|
active: { icon: CheckCircle, label: 'Active', className: 'bg-[#81B29A] text-white' },
|
||||||
inactive: { icon: AlertCircle, label: 'Inactive', className: 'bg-[#6B708D] text-white' }
|
inactive: { icon: AlertCircle, label: 'Inactive', className: 'bg-gray-400 text-white' }
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = statusConfig[status] || statusConfig.inactive;
|
const config = statusConfig[status] || statusConfig.inactive;
|
||||||
@@ -79,30 +79,30 @@ const Dashboard = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-7xl mx-auto px-6 py-12">
|
<div className="max-w-7xl mx-auto px-6 py-12">
|
||||||
{/* Welcome Section */}
|
{/* Welcome Section */}
|
||||||
<div className="mb-12">
|
<div className="mb-12">
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Welcome Back, {user?.first_name}!
|
Welcome Back, {user?.first_name}!
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Here's an overview of your membership status and upcoming events.
|
Here's an overview of your membership status and upcoming events.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Email Verification Alert */}
|
{/* Email Verification Alert */}
|
||||||
{user && !user.email_verified && (
|
{user && !user.email_verified && (
|
||||||
<Card className="p-6 bg-[#FFF3E0] border-2 border-[#E07A5F] mb-8">
|
<Card className="p-6 bg-[#f1eef9] border-2 border-[#664fa3] mb-8">
|
||||||
<div className="flex items-start gap-4">
|
<div className="flex items-start gap-4">
|
||||||
<AlertCircle className="h-6 w-6 text-[#E07A5F] flex-shrink-0 mt-1" />
|
<AlertCircle className="h-6 w-6 text-[#664fa3] flex-shrink-0 mt-1" />
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h3 className="text-lg font-semibold text-[#3D405B] mb-2">
|
<h3 className="text-lg font-semibold text-[#422268] mb-2" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Verify Your Email Address
|
Verify Your Email Address
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#6B708D] mb-4">
|
<p className="text-[#664fa3] mb-4" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Please verify your email address to complete your registration.
|
Please verify your email address to complete your registration.
|
||||||
Check your inbox for the verification link.
|
Check your inbox for the verification link.
|
||||||
</p>
|
</p>
|
||||||
@@ -110,7 +110,7 @@ const Dashboard = () => {
|
|||||||
onClick={handleResendVerification}
|
onClick={handleResendVerification}
|
||||||
disabled={resendLoading}
|
disabled={resendLoading}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-2 border-[#E07A5F] text-[#E07A5F] hover:bg-[#E07A5F] hover:text-white"
|
className="border-2 border-[#664fa3] text-[#664fa3] hover:bg-[#664fa3] hover:text-white"
|
||||||
>
|
>
|
||||||
<Mail className="h-4 w-4 mr-2" />
|
<Mail className="h-4 w-4 mr-2" />
|
||||||
{resendLoading ? 'Sending...' : 'Resend Verification Email'}
|
{resendLoading ? 'Sending...' : 'Resend Verification Email'}
|
||||||
@@ -121,22 +121,22 @@ const Dashboard = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Status Card */}
|
{/* Status Card */}
|
||||||
<Card className="p-8 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg mb-8" data-testid="status-card">
|
<Card className="p-8 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg mb-8" data-testid="status-card">
|
||||||
<div className="flex items-start justify-between flex-wrap gap-4">
|
<div className="flex items-start justify-between flex-wrap gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-semibold fraunces text-[#3D405B] mb-2">
|
<h2 className="text-2xl font-semibold text-[#422268] mb-2" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Membership Status
|
Membership Status
|
||||||
</h2>
|
</h2>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
{getStatusBadge(user?.status)}
|
{getStatusBadge(user?.status)}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-[#6B708D]">
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{getStatusMessage(user?.status)}
|
{getStatusMessage(user?.status)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Link to="/profile">
|
<Link to="/profile">
|
||||||
<Button
|
<Button
|
||||||
className="bg-[#F2CC8F] text-[#3D405B] hover:bg-[#E5B875] rounded-full px-6"
|
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-6"
|
||||||
data-testid="view-profile-button"
|
data-testid="view-profile-button"
|
||||||
>
|
>
|
||||||
<User className="h-4 w-4 mr-2" />
|
<User className="h-4 w-4 mr-2" />
|
||||||
@@ -149,22 +149,22 @@ const Dashboard = () => {
|
|||||||
{/* Grid Layout */}
|
{/* Grid Layout */}
|
||||||
<div className="grid lg:grid-cols-3 gap-8">
|
<div className="grid lg:grid-cols-3 gap-8">
|
||||||
{/* Quick Stats */}
|
{/* Quick Stats */}
|
||||||
<Card className="p-6 bg-white rounded-2xl border border-[#EAE0D5]" data-testid="quick-stats-card">
|
<Card className="p-6 bg-white rounded-2xl border border-[#ddd8eb]" data-testid="quick-stats-card">
|
||||||
<h3 className="text-xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h3 className="text-xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Quick Info
|
Quick Info
|
||||||
</h3>
|
</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[#6B708D]">Email</p>
|
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Email</p>
|
||||||
<p className="text-[#3D405B] font-medium">{user?.email}</p>
|
<p className="text-[#422268] font-medium" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{user?.email}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[#6B708D]">Role</p>
|
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Role</p>
|
||||||
<p className="text-[#3D405B] font-medium capitalize">{user?.role}</p>
|
<p className="text-[#422268] font-medium capitalize" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{user?.role}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[#6B708D]">Member Since</p>
|
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Member Since</p>
|
||||||
<p className="text-[#3D405B] font-medium">
|
<p className="text-[#422268] font-medium" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{user?.created_at ? new Date(user.created_at).toLocaleDateString() : 'N/A'}
|
{user?.created_at ? new Date(user.created_at).toLocaleDateString() : 'N/A'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,15 +172,15 @@ const Dashboard = () => {
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Upcoming Events */}
|
{/* Upcoming Events */}
|
||||||
<Card className="lg:col-span-2 p-6 bg-white rounded-2xl border border-[#EAE0D5]" data-testid="upcoming-events-card">
|
<Card className="lg:col-span-2 p-6 bg-white rounded-2xl border border-[#ddd8eb]" data-testid="upcoming-events-card">
|
||||||
<div className="flex justify-between items-center mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
<h3 className="text-xl font-semibold fraunces text-[#3D405B]">
|
<h3 className="text-xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Upcoming Events
|
Upcoming Events
|
||||||
</h3>
|
</h3>
|
||||||
<Link to="/events">
|
<Link to="/events">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="text-[#E07A5F] hover:text-[#D0694E]"
|
className="text-[#ff9e77] hover:text-[#664fa3]"
|
||||||
data-testid="view-all-events-button"
|
data-testid="view-all-events-button"
|
||||||
>
|
>
|
||||||
View All
|
View All
|
||||||
@@ -189,26 +189,26 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<p className="text-[#6B708D]">Loading events...</p>
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Loading events...</p>
|
||||||
) : events.length > 0 ? (
|
) : events.length > 0 ? (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{events.map((event) => (
|
{events.map((event) => (
|
||||||
<Link to={`/events/${event.id}`} key={event.id}>
|
<Link to={`/events/${event.id}`} key={event.id}>
|
||||||
<div
|
<div
|
||||||
className="p-4 border border-[#EAE0D5] rounded-xl hover:border-[#E07A5F] hover:shadow-md transition-all cursor-pointer"
|
className="p-4 border border-[#ddd8eb] rounded-xl hover:border-[#664fa3] hover:shadow-md transition-all cursor-pointer"
|
||||||
data-testid={`event-card-${event.id}`}
|
data-testid={`event-card-${event.id}`}
|
||||||
>
|
>
|
||||||
<div className="flex items-start gap-4">
|
<div className="flex items-start gap-4">
|
||||||
<div className="bg-[#F2CC8F]/20 p-3 rounded-lg">
|
<div className="bg-[#DDD8EB]/20 p-3 rounded-lg">
|
||||||
<Calendar className="h-6 w-6 text-[#E07A5F]" />
|
<Calendar className="h-6 w-6 text-[#664fa3]" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h4 className="font-semibold text-[#3D405B] mb-1">{event.title}</h4>
|
<h4 className="font-semibold text-[#422268] mb-1" style={{ fontFamily: "'Inter', sans-serif" }}>{event.title}</h4>
|
||||||
<p className="text-sm text-[#6B708D] mb-2">
|
<p className="text-sm text-[#664fa3] mb-2" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{new Date(event.start_at).toLocaleDateString()} at{' '}
|
{new Date(event.start_at).toLocaleDateString()} at{' '}
|
||||||
{new Date(event.start_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
{new Date(event.start_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-[#6B708D]">{event.location}</p>
|
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{event.location}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -217,9 +217,9 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
<Calendar className="h-16 w-16 text-[#EAE0D5] mx-auto mb-4" />
|
<Calendar className="h-16 w-16 text-[#ddd8eb] mx-auto mb-4" />
|
||||||
<p className="text-[#6B708D] mb-4">No upcoming events at the moment.</p>
|
<p className="text-[#664fa3] mb-4" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>No upcoming events at the moment.</p>
|
||||||
<p className="text-sm text-[#6B708D]">Check back later for new events!</p>
|
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Check back later for new events!</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
@@ -227,12 +227,12 @@ const Dashboard = () => {
|
|||||||
|
|
||||||
{/* CTA Section */}
|
{/* CTA Section */}
|
||||||
{user?.status === 'pending_approval' && (
|
{user?.status === 'pending_approval' && (
|
||||||
<Card className="mt-8 p-8 bg-gradient-to-br from-[#F2CC8F]/20 to-[#E07A5F]/20 rounded-2xl border border-[#EAE0D5]">
|
<Card className="mt-8 p-8 bg-gradient-to-br from-[#DDD8EB]/20 to-[#f1eef9]/20 rounded-2xl border border-[#ddd8eb]">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<h3 className="text-2xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h3 className="text-2xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Application Under Review
|
Application Under Review
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#6B708D] mb-6">
|
<p className="text-[#664fa3] mb-6" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Your membership application is being reviewed by our admin team. You'll be notified once approved!
|
Your membership application is being reviewed by our admin team. You'll be notified once approved!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -241,20 +241,20 @@ const Dashboard = () => {
|
|||||||
|
|
||||||
{/* Payment Prompt for payment_pending status */}
|
{/* Payment Prompt for payment_pending status */}
|
||||||
{user?.status === 'payment_pending' && (
|
{user?.status === 'payment_pending' && (
|
||||||
<Card className="mt-8 p-8 bg-gradient-to-br from-[#E07A5F]/20 to-[#F2CC8F]/20 rounded-2xl border-2 border-[#E07A5F]">
|
<Card className="mt-8 p-8 bg-gradient-to-br from-[#DDD8EB]/20 to-[#f1eef9]/20 rounded-2xl border-2 border-[#664fa3]">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<AlertCircle className="h-16 w-16 text-[#E07A5F] mx-auto" />
|
<AlertCircle className="h-16 w-16 text-[#664fa3] mx-auto" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h3 className="text-2xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Complete Your Payment
|
Complete Your Payment
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#6B708D] mb-6">
|
<p className="text-[#664fa3] mb-6" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Great news! Your membership application has been approved. Complete your payment to activate your membership and gain full access to all member benefits.
|
Great news! Your membership application has been approved. Complete your payment to activate your membership and gain full access to all member benefits.
|
||||||
</p>
|
</p>
|
||||||
<Link to="/plans">
|
<Link to="/plans">
|
||||||
<Button
|
<Button
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-8 py-6 text-lg font-semibold"
|
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-8 py-6 text-lg font-semibold"
|
||||||
data-testid="complete-payment-cta"
|
data-testid="complete-payment-cta"
|
||||||
>
|
>
|
||||||
<CheckCircle className="mr-2 h-5 w-5" />
|
<CheckCircle className="mr-2 h-5 w-5" />
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ const Events = () => {
|
|||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
yes: { label: 'Going', className: 'bg-[#81B29A] text-white' },
|
yes: { label: 'Going', className: 'bg-[#81B29A] text-white' },
|
||||||
no: { label: 'Not Going', className: 'bg-[#6B708D] text-white' },
|
no: { label: 'Not Going', className: 'bg-gray-400 text-white' },
|
||||||
maybe: { label: 'Maybe', className: 'bg-[#F2CC8F] text-[#3D405B]' }
|
maybe: { label: 'Maybe', className: 'bg-orange-100 text-orange-700' }
|
||||||
};
|
};
|
||||||
|
|
||||||
const rsvpConfig = config[rsvpStatus];
|
const rsvpConfig = config[rsvpStatus];
|
||||||
@@ -45,67 +45,67 @@ const Events = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-7xl mx-auto px-6 py-12">
|
<div className="max-w-7xl mx-auto px-6 py-12">
|
||||||
<div className="mb-12">
|
<div className="mb-12">
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Upcoming Events
|
Upcoming Events
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Browse and RSVP to our community events.
|
Browse and RSVP to our community events.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="text-center py-20">
|
<div className="text-center py-20">
|
||||||
<p className="text-[#6B708D]">Loading events...</p>
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Loading events...</p>
|
||||||
</div>
|
</div>
|
||||||
) : events.length > 0 ? (
|
) : events.length > 0 ? (
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
{events.map((event) => (
|
{events.map((event) => (
|
||||||
<Link to={`/events/${event.id}`} key={event.id}>
|
<Link to={`/events/${event.id}`} key={event.id}>
|
||||||
<Card
|
<Card
|
||||||
className="p-6 bg-white rounded-2xl border border-[#EAE0D5] hover:shadow-lg hover:-translate-y-1 transition-all cursor-pointer h-full"
|
className="p-6 bg-white rounded-2xl border border-[#ddd8eb] hover:shadow-lg hover:-translate-y-1 transition-all cursor-pointer h-full"
|
||||||
data-testid={`event-card-${event.id}`}
|
data-testid={`event-card-${event.id}`}
|
||||||
>
|
>
|
||||||
<div className="flex justify-between items-start mb-4">
|
<div className="flex justify-between items-start mb-4">
|
||||||
<div className="bg-[#F2CC8F]/20 p-3 rounded-lg">
|
<div className="bg-[#DDD8EB]/20 p-3 rounded-lg">
|
||||||
<Calendar className="h-6 w-6 text-[#E07A5F]" />
|
<Calendar className="h-6 w-6 text-[#664fa3]" />
|
||||||
</div>
|
</div>
|
||||||
{getRSVPBadge(event.user_rsvp_status)}
|
{getRSVPBadge(event.user_rsvp_status)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 className="text-xl font-semibold fraunces text-[#3D405B] mb-3">
|
<h3 className="text-xl font-semibold text-[#422268] mb-3" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
{event.title}
|
{event.title}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{event.description && (
|
{event.description && (
|
||||||
<p className="text-[#6B708D] mb-4 line-clamp-2">
|
<p className="text-[#664fa3] mb-4 line-clamp-2" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{event.description}
|
{event.description}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
<div className="flex items-center gap-2 text-[#6B708D]">
|
<div className="flex items-center gap-2 text-[#664fa3]">
|
||||||
<Calendar className="h-4 w-4" />
|
<Calendar className="h-4 w-4" />
|
||||||
<span>
|
<span style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{new Date(event.start_at).toLocaleDateString()} at{' '}
|
{new Date(event.start_at).toLocaleDateString()} at{' '}
|
||||||
{new Date(event.start_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
{new Date(event.start_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 text-[#6B708D]">
|
<div className="flex items-center gap-2 text-[#664fa3]">
|
||||||
<MapPin className="h-4 w-4" />
|
<MapPin className="h-4 w-4" />
|
||||||
<span>{event.location}</span>
|
<span style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{event.location}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 text-[#6B708D]">
|
<div className="flex items-center gap-2 text-[#664fa3]">
|
||||||
<Users className="h-4 w-4" />
|
<Users className="h-4 w-4" />
|
||||||
<span>{event.rsvp_count || 0} attending</span>
|
<span style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{event.rsvp_count || 0} attending</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 flex items-center text-[#E07A5F] font-medium">
|
<div className="mt-6 flex items-center text-[#ff9e77] font-medium">
|
||||||
View Details
|
View Details
|
||||||
<ArrowRight className="ml-2 h-4 w-4" />
|
<ArrowRight className="ml-2 h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
@@ -115,11 +115,11 @@ const Events = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-20">
|
<div className="text-center py-20">
|
||||||
<Calendar className="h-20 w-20 text-[#EAE0D5] mx-auto mb-6" />
|
<Calendar className="h-20 w-20 text-[#ddd8eb] mx-auto mb-6" />
|
||||||
<h3 className="text-2xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h3 className="text-2xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
No Events Available
|
No Events Available
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#6B708D]">
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
There are no upcoming events at the moment. Check back later!
|
There are no upcoming events at the moment. Check back later!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,28 +31,28 @@ const ForgotPassword = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-md mx-auto px-6 py-12">
|
<div className="max-w-md mx-auto px-6 py-12">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<Link to="/login" className="inline-flex items-center text-[#6B708D] hover:text-[#E07A5F] transition-colors">
|
<Link to="/login" className="inline-flex items-center text-[#664fa3] hover:text-[#ff9e77] transition-colors">
|
||||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||||
Back to Login
|
Back to Login
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg">
|
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg">
|
||||||
{!submitted ? (
|
{!submitted ? (
|
||||||
<>
|
<>
|
||||||
<div className="mb-8 text-center">
|
<div className="mb-8 text-center">
|
||||||
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#FFF3E0] mb-4">
|
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#f1eef9] mb-4">
|
||||||
<Mail className="h-8 w-8 text-[#E07A5F]" />
|
<Mail className="h-8 w-8 text-[#664fa3]" />
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Forgot Password?
|
Forgot Password?
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
No worries! Enter your email and we'll send you reset instructions.
|
No worries! Enter your email and we'll send you reset instructions.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,22 +68,22 @@ const ForgotPassword = () => {
|
|||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
placeholder="your.email@example.com"
|
placeholder="your.email@example.com"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="w-full bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
className="w-full bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
||||||
>
|
>
|
||||||
{loading ? 'Sending...' : 'Send Reset Link'}
|
{loading ? 'Sending...' : 'Send Reset Link'}
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<p className="text-center text-[#6B708D]">
|
<p className="text-center text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Remember your password?{' '}
|
Remember your password?{' '}
|
||||||
<Link to="/login" className="text-[#E07A5F] hover:underline font-medium">
|
<Link to="/login" className="text-[#ff9e77] hover:underline font-medium">
|
||||||
Login here
|
Login here
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
@@ -94,18 +94,18 @@ const ForgotPassword = () => {
|
|||||||
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#E8F5E9] mb-6">
|
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#E8F5E9] mb-6">
|
||||||
<CheckCircle className="h-8 w-8 text-[#4CAF50]" />
|
<CheckCircle className="h-8 w-8 text-[#4CAF50]" />
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Check Your Email
|
Check Your Email
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D] mb-8">
|
<p className="text-lg text-[#664fa3] mb-8" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
If an account exists for <span className="font-medium text-[#3D405B]">{email}</span>,
|
If an account exists for <span className="font-medium text-[#422268]">{email}</span>,
|
||||||
you will receive a password reset link shortly.
|
you will receive a password reset link shortly.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-[#6B708D] mb-8">
|
<p className="text-sm text-[#664fa3] mb-8" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
The link will expire in 1 hour. If you don't see the email, check your spam folder.
|
The link will expire in 1 hour. If you don't see the email, check your spam folder.
|
||||||
</p>
|
</p>
|
||||||
<Link to="/login">
|
<Link to="/login">
|
||||||
<Button className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-8 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform">
|
<Button className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-8 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform">
|
||||||
Return to Login
|
Return to Login
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -2,136 +2,204 @@ import React from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Button } from '../components/ui/button';
|
import { Button } from '../components/ui/button';
|
||||||
import { Card } from '../components/ui/card';
|
import { Card } from '../components/ui/card';
|
||||||
import { Calendar, Users, Heart, ArrowRight } from 'lucide-react';
|
|
||||||
import Navbar from '../components/Navbar';
|
|
||||||
|
|
||||||
const Landing = () => {
|
const Landing = () => {
|
||||||
|
// LOAF brand assets from Figma
|
||||||
|
const loafLogo = "https://www.figma.com/api/mcp/asset/5e3c057c-ffb0-4ceb-aa60-70a5ddbe10ab";
|
||||||
|
const taglineImage = "https://www.figma.com/api/mcp/asset/ce184873-0c46-45eb-8480-76a9411011bf";
|
||||||
|
const shootingStar = "https://www.figma.com/api/mcp/asset/6db528f4-493b-4560-9ff6-076bc42421ca";
|
||||||
|
const iconMeetGreet = "https://www.figma.com/api/mcp/asset/3519deee-3f78-45e1-b537-f9c61102c18b";
|
||||||
|
const iconSocials = "https://www.figma.com/api/mcp/asset/e95f23c6-e893-472e-a3cf-38a05290790b";
|
||||||
|
const iconActive = "https://www.figma.com/api/mcp/asset/cab1679a-a7d6-4a5f-8732-c6c1cd578320";
|
||||||
|
const heroLoaf = "https://www.figma.com/api/mcp/asset/f3fb05af-0fef-49b7-bc50-f5914dfe1705";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
{/* Top Header - Auth Actions */}
|
||||||
|
<header className="bg-gradient-to-r from-[#644c9f] to-[#48286e] px-16 py-4 flex justify-end items-center gap-6">
|
||||||
|
<Link to="/register" className="text-white text-base font-medium hover:opacity-80 transition-opacity">
|
||||||
|
Register
|
||||||
|
</Link>
|
||||||
|
<Link to="/login" className="text-white text-base font-medium hover:opacity-80 transition-opacity">
|
||||||
|
Login
|
||||||
|
</Link>
|
||||||
|
<Button className="bg-[#ff9e77] hover:bg-[#ff8c64] text-[#644c9f] rounded-full px-6 py-3 text-base font-medium">
|
||||||
|
Donate
|
||||||
|
</Button>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{/* Main Header - Navigation */}
|
||||||
|
<header className="bg-[#664fa3] px-16 py-2 flex justify-between items-center">
|
||||||
|
<img src={loafLogo} alt="LOAF Logo" className="h-28 w-28 object-contain" />
|
||||||
|
<nav className="flex gap-10 items-center">
|
||||||
|
<a href="#welcome" className="text-white text-lg font-bold hover:opacity-80 transition-opacity" style={{ fontFamily: "'Nunito Sans', sans-serif", textShadow: '0px 4px 4px rgba(0,0,0,0.25)' }}>
|
||||||
|
Welcome
|
||||||
|
</a>
|
||||||
|
<a href="#about" className="text-white text-lg font-bold hover:opacity-80 transition-opacity" style={{ fontFamily: "'Nunito Sans', sans-serif", textShadow: '0px 4px 4px rgba(0,0,0,0.25)' }}>
|
||||||
|
About Us
|
||||||
|
</a>
|
||||||
|
<Link to="/register" className="text-white text-lg font-bold hover:opacity-80 transition-opacity" style={{ fontFamily: "'Nunito Sans', sans-serif", textShadow: '0px 4px 4px rgba(0,0,0,0.25)' }}>
|
||||||
|
Become a Member
|
||||||
|
</Link>
|
||||||
|
<Link to="/login" className="text-white text-lg font-bold hover:opacity-80 transition-opacity" style={{ fontFamily: "'Nunito Sans', sans-serif", textShadow: '0px 4px 4px rgba(0,0,0,0.25)' }}>
|
||||||
|
Members Only
|
||||||
|
</Link>
|
||||||
|
<a href="#resources" className="text-white text-lg font-bold hover:opacity-80 transition-opacity" style={{ fontFamily: "'Nunito Sans', sans-serif", textShadow: '0px 4px 4px rgba(0,0,0,0.25)' }}>
|
||||||
|
Resources
|
||||||
|
</a>
|
||||||
|
<a href="#contact" className="text-white text-lg font-bold hover:opacity-80 transition-opacity" style={{ fontFamily: "'Nunito Sans', sans-serif", textShadow: '0px 4px 4px rgba(0,0,0,0.25)' }}>
|
||||||
|
Contact Us
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="relative overflow-hidden">
|
<section className="bg-gradient-to-b from-[#48286e] to-[#664fa3] px-16 py-0 flex gap-16 items-center justify-center">
|
||||||
<div className="absolute inset-0 bg-soft-mesh"></div>
|
<div className="py-10 flex flex-col gap-8 items-center justify-center w-[420px]">
|
||||||
<div className="max-w-7xl mx-auto px-6 py-20 lg:py-32 relative">
|
<div className="flex flex-col gap-6 items-center">
|
||||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
<img src={heroLoaf} alt="LOAF" className="w-[334px] h-[105px] object-contain" />
|
||||||
<div className="space-y-8">
|
</div>
|
||||||
<h1 className="text-5xl md:text-7xl font-semibold fraunces text-[#3D405B] leading-tight">
|
<div className="flex flex-col gap-4 items-center justify-center w-full">
|
||||||
Building Friendships, One Event at a Time
|
<Link to="/register" className="w-full max-w-[339px]">
|
||||||
</h1>
|
<Button className="bg-[#DDD8EB] hover:bg-white text-[#422268] rounded-full px-6 py-[32px] text-lg font-medium w-full transition-colors">
|
||||||
<p className="text-lg md:text-xl text-[#6B708D] leading-relaxed">
|
|
||||||
Join our vibrant community of members connecting through shared experiences, events, and meaningful relationships.
|
|
||||||
</p>
|
|
||||||
<div className="flex gap-4 flex-wrap">
|
|
||||||
<Link to="/register">
|
|
||||||
<Button
|
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-8 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform"
|
|
||||||
data-testid="hero-join-button"
|
|
||||||
>
|
|
||||||
Become a Member
|
Become a Member
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<Link to="/login">
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
className="border-2 border-[#3D405B] text-[#3D405B] hover:bg-[#3D405B] hover:text-white rounded-full px-8 py-6 text-lg font-medium transition-all"
|
|
||||||
data-testid="hero-login-button"
|
|
||||||
>
|
|
||||||
Member Login
|
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
<p className="text-white text-lg text-center" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
|
LOAF is supported by the Hollyfield Foundation
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
<div className="py-16 flex items-center justify-center w-[594px] h-[636px]">
|
||||||
<img
|
<img src={taglineImage} alt="LOAF Tagline" className="w-[483px] h-[297px] object-contain" />
|
||||||
src="https://images.unsplash.com/photo-1660405251862-c023df45d075?crop=entropy&cs=srgb&fm=jpg&ixid=M3w3NDk1ODF8MHwxfHNlYXJjaHwxfHxhY3RpdmUlMjBzZW5pb3IlMjB3b21lbiUyMGdyb3VwJTIwaGlraW5nJTIwbmF0dXJlfGVufDB8fHx8MTc2NDc1NjIwM3ww&ixlib=rb-4.1.0&q=85"
|
|
||||||
alt="Community members enjoying outdoor activities"
|
|
||||||
className="rounded-2xl shadow-2xl w-full h-[500px] object-cover"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Features Section */}
|
{/* About Section */}
|
||||||
<section className="max-w-7xl mx-auto px-6 py-20">
|
<section id="about" className="bg-gradient-to-b from-white to-[#f1eef9] px-16 pt-30 pb-0 flex flex-col gap-8">
|
||||||
<div className="text-center mb-16">
|
<div className="flex flex-col items-center pt-12">
|
||||||
<h2 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h3 className="text-[#48286e] text-5xl font-extrabold text-center" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
What We Offer
|
Welcome to LOAF
|
||||||
</h2>
|
|
||||||
<p className="text-lg text-[#6B708D] max-w-2xl mx-auto">
|
|
||||||
No matter your age or ability, there is something for everyone in our community.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-3 gap-8">
|
|
||||||
<Card className="p-8 bg-white rounded-2xl border border-[#EAE0D5] hover:shadow-lg transition-shadow" data-testid="feature-community-card">
|
|
||||||
<div className="bg-[#F2CC8F]/20 w-16 h-16 rounded-full flex items-center justify-center mb-6">
|
|
||||||
<Users className="h-8 w-8 text-[#E07A5F]" strokeWidth={1.5} />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-2xl font-semibold fraunces text-[#3D405B] mb-4">
|
|
||||||
Meet & Greet
|
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#6B708D] leading-relaxed">
|
</div>
|
||||||
Connect with prospective members and get acquainted with our community. Meet the board and ask questions in a welcoming environment.
|
<p className="text-[rgba(0,0,0,0.55)] text-lg text-center font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
LOAF is Houston's social networking group for lesbians who are 50 years of age and older. LOAF hosts three main activities each month, Meet and Greets, Socials, and ActiveLOAFers. TheaterLOAFers coordinate events throughout the year.
|
||||||
</p>
|
</p>
|
||||||
|
<img src={shootingStar} alt="Decorative element" className="w-full h-[197px] object-contain" />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Feature Cards Section */}
|
||||||
|
<section className="bg-gradient-to-b from-[#f1eef9] to-[#ddd8eb] px-16 py-30 flex gap-8 items-start justify-center">
|
||||||
|
<Card className="bg-white rounded-2xl overflow-hidden flex flex-col gap-3.5 items-center pt-5 pb-0 w-full max-w-[363px]">
|
||||||
|
<img src={iconMeetGreet} alt="Meet and Greet" className="w-[300px] h-[270px] object-contain" />
|
||||||
|
<div className="p-6 flex flex-col gap-4.5 w-full">
|
||||||
|
<h5 className="text-[#48286e] text-2xl font-semibold text-center" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
Meet and Greet
|
||||||
|
</h5>
|
||||||
|
<p className="text-[#48286e] text-lg text-center" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
|
The MEET and GREETs provide opportunities for prospective members to get acquainted with LOAF, have conversations with members, and ask the board of directors questions. They are held the 3rd Sunday of the month and usually take place at a restaurant or other fun places conducive to its purpose. Please email{' '}
|
||||||
|
<a href="mailto:info@loaftx.org" className="underline">info@loaftx.org</a> for upcoming times and locations.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card className="p-8 bg-white rounded-2xl border border-[#EAE0D5] hover:shadow-lg transition-shadow" data-testid="feature-events-card">
|
<Card className="bg-white rounded-2xl overflow-hidden flex flex-col gap-3.5 items-center pt-5 pb-0 w-full max-w-[363px]">
|
||||||
<div className="bg-[#F2CC8F]/20 w-16 h-16 rounded-full flex items-center justify-center mb-6">
|
<img src={iconSocials} alt="Socials" className="w-[300px] h-[270px] object-contain" />
|
||||||
<Calendar className="h-8 w-8 text-[#E07A5F]" strokeWidth={1.5} />
|
<div className="p-6 flex flex-col gap-4.5 w-full">
|
||||||
</div>
|
<h5 className="text-[#48286e] text-2xl font-semibold text-center" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
<h3 className="text-2xl font-semibold fraunces text-[#3D405B] mb-4">
|
Socials
|
||||||
Social Events
|
</h5>
|
||||||
</h3>
|
<p className="text-[#48286e] text-lg text-center" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
<p className="text-[#6B708D] leading-relaxed">
|
Our social events provide opportunities for members to explore Houston and connect with other lesbians. Past social events include, bowling, museums, painting lessons, sporting events, Miller Outdoor Theater, bingo and board games, pool parties, putt putt golf, camping and holiday get togethers. No matter your age or ability, there is something for everyone.
|
||||||
Explore your city with fellow members. From museums to sporting events, board games to pool parties - there's always something happening.
|
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card className="p-8 bg-white rounded-2xl border border-[#EAE0D5] hover:shadow-lg transition-shadow" data-testid="feature-activities-card">
|
<Card className="bg-white rounded-2xl overflow-hidden flex flex-col gap-3.5 items-center pt-5 pb-0 w-full max-w-[363px]">
|
||||||
<div className="bg-[#F2CC8F]/20 w-16 h-16 rounded-full flex items-center justify-center mb-6">
|
<img src={iconActive} alt="Active LOAFers" className="w-[300px] h-[270px] object-contain" />
|
||||||
<Heart className="h-8 w-8 text-[#E07A5F]" strokeWidth={1.5} />
|
<div className="p-6 flex flex-col gap-4.5 w-full">
|
||||||
</div>
|
<h5 className="text-[#48286e] text-2xl font-semibold text-center" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
<h3 className="text-2xl font-semibold fraunces text-[#3D405B] mb-4">
|
Active LOAFers
|
||||||
Active Living
|
</h5>
|
||||||
</h3>
|
<p className="text-[#48286e] text-lg text-center" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
<p className="text-[#6B708D] leading-relaxed">
|
ActiveLOAFers events provide members with opportunities to be physically active. Past activities have included, hiking/walking in the park, swimming (or floating), pickleball, kayaking, bike riding, axe throwing, and strolling through the botanic gardens or the Arboretum.
|
||||||
Stay active with hiking, swimming, pickleball, kayaking, and more. Activities designed for all abilities and fitness levels.
|
|
||||||
</p>
|
</p>
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
|
</Card>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* CTA Section */}
|
{/* CTA Section */}
|
||||||
<section className="bg-gradient-to-br from-[#F2CC8F]/20 to-[#E07A5F]/20 py-20">
|
<section className="bg-gradient-to-b from-[#644c9f] to-[#48286e] px-16 py-30 flex items-center justify-center">
|
||||||
<div className="max-w-4xl mx-auto px-6 text-center">
|
<div className="flex gap-12 items-center justify-center h-[191px]">
|
||||||
<h2 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-6">
|
|
||||||
Ready to Join Our Community?
|
|
||||||
</h2>
|
|
||||||
<p className="text-lg text-[#6B708D] mb-8">
|
|
||||||
Start your membership journey today and connect with amazing people in your area.
|
|
||||||
</p>
|
|
||||||
<Link to="/register">
|
<Link to="/register">
|
||||||
<Button
|
<Button className="bg-[#DDD8EB] hover:bg-white text-[#422268] rounded-full px-6 py-[32px] text-lg font-medium w-[392px] transition-colors">
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-12 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform"
|
Become a Member
|
||||||
data-testid="cta-register-button"
|
|
||||||
>
|
|
||||||
Get Started Now
|
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
<div className="flex-1 flex items-center justify-center">
|
||||||
|
<h4 className="text-white text-4xl font-bold max-w-[718px]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
No matter your age or ability, there is something for everyone.
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Main Footer */}
|
||||||
<footer className="bg-[#3D405B] text-white py-12">
|
<footer className="bg-[#644c9f] px-16 py-0 flex items-center justify-center h-[420px]">
|
||||||
<div className="max-w-7xl mx-auto px-6 text-center">
|
<div className="border-t border-[rgba(0,0,0,0.1)] py-20 flex gap-30 items-center justify-center flex-1">
|
||||||
<p className="text-[#A3B1C6]">
|
<div className="w-[232px]">
|
||||||
© 2025 Membership Platform. Building connections, creating community.
|
<img src={loafLogo} alt="LOAF Logo" className="w-[232px] h-[232px] object-contain" />
|
||||||
|
</div>
|
||||||
|
<nav className="flex gap-28 items-start justify-center w-[811px]">
|
||||||
|
<div className="flex flex-col gap-2 w-[163px]">
|
||||||
|
<div className="pb-4">
|
||||||
|
<p className="text-white text-base font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>About</p>
|
||||||
|
</div>
|
||||||
|
<a href="#history" className="text-[#ddd8eb] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>History</a>
|
||||||
|
<a href="#mission" className="text-[#ddd8eb] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>Mission and Values</a>
|
||||||
|
<a href="#board" className="text-[#ddd8eb] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>Board of Directors</a>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 w-[148px]">
|
||||||
|
<div className="pb-4">
|
||||||
|
<p className="text-white text-base font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>Connect</p>
|
||||||
|
</div>
|
||||||
|
<Link to="/register" className="text-[#ddd8eb] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>Become a Member</Link>
|
||||||
|
<a href="#contact" className="text-[#ddd8eb] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>Contact Us</a>
|
||||||
|
<a href="#resources" className="text-[#ddd8eb] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>Resources</a>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 items-center w-[271px]">
|
||||||
|
<div className="pb-4 w-full">
|
||||||
|
<Button className="bg-[#ff9e77] hover:bg-[#ff8c64] text-[#48286e] rounded-full px-6 py-3 text-lg font-medium w-[217px]">
|
||||||
|
Donate
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<p className="text-[#ddd8eb] text-base font-medium text-center w-full" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
LOAF is supported by<br />the Hollyfield Foundation
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
{/* Bottom Footer */}
|
||||||
|
<footer className="bg-gradient-to-r from-[#48286e] to-[#644c9f] border-t border-[rgba(0,0,0,0.1)] px-16 py-6 flex justify-between items-center h-[76px]">
|
||||||
|
<nav className="flex gap-8 items-center">
|
||||||
|
<a href="#terms" className="text-[#c5b4e3] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
Terms of Service
|
||||||
|
</a>
|
||||||
|
<a href="#privacy" className="text-[#c5b4e3] text-base font-medium hover:text-white transition-colors" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
Privacy Policy
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
<p className="text-[#c5b4e3] text-base font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
© 2025 LOAF. All Rights Reserved.
|
||||||
|
</p>
|
||||||
|
<p className="text-[#c5b4e3] text-base font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
|
Designed and Managed by{' '}
|
||||||
|
<a href="https://konceptkit.com/" className="text-[#d1c3e9] underline hover:text-white transition-colors">
|
||||||
|
Koncept Kit
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -54,23 +54,23 @@ const Login = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-md mx-auto px-6 py-12">
|
<div className="max-w-md mx-auto px-6 py-12">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<Link to="/" className="inline-flex items-center text-[#6B708D] hover:text-[#E07A5F] transition-colors">
|
<Link to="/" className="inline-flex items-center text-[#664fa3] hover:text-[#ff9e77] transition-colors">
|
||||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||||
Back to Home
|
Back to Home
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg">
|
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg">
|
||||||
<div className="mb-8 text-center">
|
<div className="mb-8 text-center">
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Welcome Back
|
Welcome Back
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Login to access your member dashboard.
|
Login to access your member dashboard.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -86,7 +86,7 @@ const Login = () => {
|
|||||||
value={formData.email}
|
value={formData.email}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="your.email@example.com"
|
placeholder="your.email@example.com"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="login-email-input"
|
data-testid="login-email-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,7 +94,7 @@ const Login = () => {
|
|||||||
<div>
|
<div>
|
||||||
<div className="flex items-center justify-between mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<Label htmlFor="password">Password</Label>
|
<Label htmlFor="password">Password</Label>
|
||||||
<Link to="/forgot-password" className="text-sm text-[#E07A5F] hover:underline">
|
<Link to="/forgot-password" className="text-sm text-[#ff9e77] hover:underline">
|
||||||
Forgot password?
|
Forgot password?
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@@ -105,7 +105,7 @@ const Login = () => {
|
|||||||
value={formData.password}
|
value={formData.password}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="Enter your password"
|
placeholder="Enter your password"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="login-password-input"
|
data-testid="login-password-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,16 +113,16 @@ const Login = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="w-full bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
className="w-full bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
||||||
data-testid="login-submit-button"
|
data-testid="login-submit-button"
|
||||||
>
|
>
|
||||||
{loading ? 'Logging in...' : 'Login'}
|
{loading ? 'Logging in...' : 'Login'}
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<p className="text-center text-[#6B708D]">
|
<p className="text-center text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Don't have an account?{' '}
|
Don't have an account?{' '}
|
||||||
<Link to="/register" className="text-[#E07A5F] hover:underline font-medium">
|
<Link to="/register" className="text-[#ff9e77] hover:underline font-medium">
|
||||||
Register here
|
Register here
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -66,43 +66,43 @@ const Plans = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-7xl mx-auto px-6 py-12">
|
<div className="max-w-7xl mx-auto px-6 py-12">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-12 text-center">
|
<div className="mb-12 text-center">
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Membership Plans
|
Membership Plans
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D] max-w-2xl mx-auto">
|
<p className="text-lg text-[#664fa3] max-w-2xl mx-auto" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Choose the membership plan that works best for you and become part of our vibrant community.
|
Choose the membership plan that works best for you and become part of our vibrant community.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="text-center py-20">
|
<div className="text-center py-20">
|
||||||
<Loader2 className="h-12 w-12 text-[#E07A5F] mx-auto mb-4 animate-spin" />
|
<Loader2 className="h-12 w-12 text-[#664fa3] mx-auto mb-4 animate-spin" />
|
||||||
<p className="text-[#6B708D]">Loading plans...</p>
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Loading plans...</p>
|
||||||
</div>
|
</div>
|
||||||
) : plans.length > 0 ? (
|
) : plans.length > 0 ? (
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8 max-w-5xl mx-auto">
|
||||||
{plans.map((plan) => (
|
{plans.map((plan) => (
|
||||||
<Card
|
<Card
|
||||||
key={plan.id}
|
key={plan.id}
|
||||||
className="p-8 bg-white rounded-2xl border-2 border-[#EAE0D5] hover:border-[#E07A5F] hover:shadow-xl transition-all"
|
className="p-8 bg-white rounded-2xl border-2 border-[#ddd8eb] hover:border-[#664fa3] hover:shadow-xl transition-all"
|
||||||
data-testid={`plan-card-${plan.id}`}
|
data-testid={`plan-card-${plan.id}`}
|
||||||
>
|
>
|
||||||
{/* Plan Header */}
|
{/* Plan Header */}
|
||||||
<div className="text-center mb-6">
|
<div className="text-center mb-6">
|
||||||
<div className="bg-[#F2CC8F]/20 p-4 rounded-full w-16 h-16 mx-auto mb-4 flex items-center justify-center">
|
<div className="bg-[#DDD8EB]/20 p-4 rounded-full w-16 h-16 mx-auto mb-4 flex items-center justify-center">
|
||||||
<CreditCard className="h-8 w-8 text-[#E07A5F]" />
|
<CreditCard className="h-8 w-8 text-[#664fa3]" />
|
||||||
</div>
|
</div>
|
||||||
<h2 className="text-2xl font-semibold fraunces text-[#3D405B] mb-2">
|
<h2 className="text-2xl font-semibold text-[#422268] mb-2" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
{plan.name}
|
{plan.name}
|
||||||
</h2>
|
</h2>
|
||||||
{plan.description && (
|
{plan.description && (
|
||||||
<p className="text-sm text-[#6B708D] mb-4">
|
<p className="text-sm text-[#664fa3] mb-4" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{plan.description}
|
{plan.description}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@@ -110,10 +110,10 @@ const Plans = () => {
|
|||||||
|
|
||||||
{/* Pricing */}
|
{/* Pricing */}
|
||||||
<div className="text-center mb-8">
|
<div className="text-center mb-8">
|
||||||
<div className="text-4xl font-bold fraunces text-[#3D405B] mb-2">
|
<div className="text-4xl font-bold text-[#422268] mb-2" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
{formatPrice(plan.price_cents)}
|
{formatPrice(plan.price_cents)}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-[#6B708D]">
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{getBillingCycleLabel(plan.billing_cycle)}
|
{getBillingCycleLabel(plan.billing_cycle)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -122,19 +122,19 @@ const Plans = () => {
|
|||||||
<div className="space-y-3 mb-8">
|
<div className="space-y-3 mb-8">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
||||||
<span className="text-sm text-[#3D405B]">Access to all member events</span>
|
<span className="text-sm text-[#422268]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Access to all member events</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
||||||
<span className="text-sm text-[#3D405B]">Community directory access</span>
|
<span className="text-sm text-[#422268]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Community directory access</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
||||||
<span className="text-sm text-[#3D405B]">Exclusive member benefits</span>
|
<span className="text-sm text-[#422268]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Exclusive member benefits</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
<CheckCircle className="h-5 w-5 text-[#81B29A] flex-shrink-0 mt-0.5" />
|
||||||
<span className="text-sm text-[#3D405B]">Newsletter subscription</span>
|
<span className="text-sm text-[#422268]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Newsletter subscription</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ const Plans = () => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => handleSubscribe(plan.id)}
|
onClick={() => handleSubscribe(plan.id)}
|
||||||
disabled={processingPlanId === plan.id}
|
disabled={processingPlanId === plan.id}
|
||||||
className="w-full bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full py-6 text-lg font-semibold"
|
className="w-full bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full py-6 text-lg font-semibold"
|
||||||
data-testid={`subscribe-button-${plan.id}`}
|
data-testid={`subscribe-button-${plan.id}`}
|
||||||
>
|
>
|
||||||
{processingPlanId === plan.id ? (
|
{processingPlanId === plan.id ? (
|
||||||
@@ -159,11 +159,11 @@ const Plans = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center py-20">
|
<div className="text-center py-20">
|
||||||
<CreditCard className="h-20 w-20 text-[#EAE0D5] mx-auto mb-6" />
|
<CreditCard className="h-20 w-20 text-[#ddd8eb] mx-auto mb-6" />
|
||||||
<h3 className="text-2xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h3 className="text-2xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
No Plans Available
|
No Plans Available
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#6B708D]">
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Membership plans are not currently available. Please check back later!
|
Membership plans are not currently available. Please check back later!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -171,17 +171,17 @@ const Plans = () => {
|
|||||||
|
|
||||||
{/* Info Section */}
|
{/* Info Section */}
|
||||||
<div className="mt-16 max-w-3xl mx-auto">
|
<div className="mt-16 max-w-3xl mx-auto">
|
||||||
<Card className="p-8 bg-gradient-to-br from-[#F2CC8F]/20 to-[#E07A5F]/20 rounded-2xl border border-[#EAE0D5]">
|
<Card className="p-8 bg-gradient-to-br from-[#DDD8EB]/20 to-[#f1eef9]/20 rounded-2xl border border-[#ddd8eb]">
|
||||||
<h3 className="text-xl font-semibold fraunces text-[#3D405B] mb-4 text-center">
|
<h3 className="text-xl font-semibold text-[#422268] mb-4 text-center" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Need Help Choosing?
|
Need Help Choosing?
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[#6B708D] text-center mb-4">
|
<p className="text-[#664fa3] text-center mb-4" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
If you have any questions about our membership plans or need assistance, please contact us.
|
If you have any questions about our membership plans or need assistance, please contact us.
|
||||||
</p>
|
</p>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<a
|
<a
|
||||||
href="mailto:support@loaf.org"
|
href="mailto:support@loaf.org"
|
||||||
className="text-[#E07A5F] hover:text-[#D0694E] font-medium"
|
className="text-[#ff9e77] hover:text-[#664fa3] font-medium"
|
||||||
>
|
>
|
||||||
support@loaf.org
|
support@loaf.org
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -69,52 +69,52 @@ const Profile = () => {
|
|||||||
|
|
||||||
if (!profileData) {
|
if (!profileData) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div className="flex items-center justify-center min-h-[60vh]">
|
<div className="flex items-center justify-center min-h-[60vh]">
|
||||||
<p className="text-[#6B708D]">Loading profile...</p>
|
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Loading profile...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-4xl mx-auto px-6 py-12">
|
<div className="max-w-4xl mx-auto px-6 py-12">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
My Profile
|
My Profile
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Update your personal information below.
|
Update your personal information below.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card className="p-8 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg">
|
<Card className="p-8 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg">
|
||||||
{/* Read-only Information */}
|
{/* Read-only Information */}
|
||||||
<div className="mb-8 pb-8 border-b border-[#EAE0D5]">
|
<div className="mb-8 pb-8 border-b border-[#ddd8eb]">
|
||||||
<h2 className="text-2xl font-semibold fraunces text-[#3D405B] mb-6 flex items-center gap-2">
|
<h2 className="text-2xl font-semibold text-[#422268] mb-6 flex items-center gap-2" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
<User className="h-6 w-6 text-[#E07A5F]" />
|
<User className="h-6 w-6 text-[#664fa3]" />
|
||||||
Account Information
|
Account Information
|
||||||
</h2>
|
</h2>
|
||||||
<div className="grid md:grid-cols-2 gap-6">
|
<div className="grid md:grid-cols-2 gap-6">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[#6B708D] mb-1">Email</p>
|
<p className="text-sm text-[#664fa3] mb-1" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Email</p>
|
||||||
<p className="text-[#3D405B] font-medium">{profileData.email}</p>
|
<p className="text-[#422268] font-medium" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{profileData.email}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[#6B708D] mb-1">Status</p>
|
<p className="text-sm text-[#664fa3] mb-1" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Status</p>
|
||||||
<p className="text-[#3D405B] font-medium capitalize">{profileData.status.replace('_', ' ')}</p>
|
<p className="text-[#422268] font-medium capitalize" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{profileData.status.replace('_', ' ')}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[#6B708D] mb-1">Role</p>
|
<p className="text-sm text-[#664fa3] mb-1" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Role</p>
|
||||||
<p className="text-[#3D405B] font-medium capitalize">{profileData.role}</p>
|
<p className="text-[#422268] font-medium capitalize" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{profileData.role}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-[#6B708D] mb-1">Date of Birth</p>
|
<p className="text-sm text-[#664fa3] mb-1" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Date of Birth</p>
|
||||||
<p className="text-[#3D405B] font-medium">
|
<p className="text-[#422268] font-medium" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{new Date(profileData.date_of_birth).toLocaleDateString()}
|
{new Date(profileData.date_of_birth).toLocaleDateString()}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -125,7 +125,7 @@ const Profile = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => setPasswordDialogOpen(true)}
|
onClick={() => setPasswordDialogOpen(true)}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="border-2 border-[#E07A5F] text-[#E07A5F] hover:bg-[#FFF3E0] rounded-full px-6 py-3"
|
className="border-2 border-[#664fa3] text-[#664fa3] hover:bg-[#f1eef9] rounded-full px-6 py-3"
|
||||||
>
|
>
|
||||||
<Lock className="h-4 w-4 mr-2" />
|
<Lock className="h-4 w-4 mr-2" />
|
||||||
Change Password
|
Change Password
|
||||||
@@ -135,7 +135,7 @@ const Profile = () => {
|
|||||||
|
|
||||||
{/* Editable Form */}
|
{/* Editable Form */}
|
||||||
<form onSubmit={handleSubmit} className="space-y-6" data-testid="profile-form">
|
<form onSubmit={handleSubmit} className="space-y-6" data-testid="profile-form">
|
||||||
<h2 className="text-2xl font-semibold fraunces text-[#3D405B] mb-6">
|
<h2 className="text-2xl font-semibold text-[#422268] mb-6" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Personal Information
|
Personal Information
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ const Profile = () => {
|
|||||||
name="first_name"
|
name="first_name"
|
||||||
value={formData.first_name}
|
value={formData.first_name}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="first-name-input"
|
data-testid="first-name-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -158,7 +158,7 @@ const Profile = () => {
|
|||||||
name="last_name"
|
name="last_name"
|
||||||
value={formData.last_name}
|
value={formData.last_name}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="last-name-input"
|
data-testid="last-name-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,7 +172,7 @@ const Profile = () => {
|
|||||||
type="tel"
|
type="tel"
|
||||||
value={formData.phone}
|
value={formData.phone}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="phone-input"
|
data-testid="phone-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -184,7 +184,7 @@ const Profile = () => {
|
|||||||
name="address"
|
name="address"
|
||||||
value={formData.address}
|
value={formData.address}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="address-input"
|
data-testid="address-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -197,7 +197,7 @@ const Profile = () => {
|
|||||||
name="city"
|
name="city"
|
||||||
value={formData.city}
|
value={formData.city}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="city-input"
|
data-testid="city-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -208,7 +208,7 @@ const Profile = () => {
|
|||||||
name="state"
|
name="state"
|
||||||
value={formData.state}
|
value={formData.state}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="state-input"
|
data-testid="state-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -219,7 +219,7 @@ const Profile = () => {
|
|||||||
name="zipcode"
|
name="zipcode"
|
||||||
value={formData.zipcode}
|
value={formData.zipcode}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
data-testid="zipcode-input"
|
data-testid="zipcode-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -228,7 +228,7 @@ const Profile = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-8 py-6 text-lg font-medium shadow-lg disabled:opacity-50"
|
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-8 py-6 text-lg font-medium shadow-lg disabled:opacity-50"
|
||||||
data-testid="save-profile-button"
|
data-testid="save-profile-button"
|
||||||
>
|
>
|
||||||
<Save className="h-5 w-5 mr-2" />
|
<Save className="h-5 w-5 mr-2" />
|
||||||
|
|||||||
@@ -182,23 +182,23 @@ const Register = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-4xl mx-auto px-6 py-12">
|
<div className="max-w-4xl mx-auto px-6 py-12">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<Link to="/" className="inline-flex items-center text-[#6B708D] hover:text-[#E07A5F] transition-colors">
|
<Link to="/" className="inline-flex items-center text-[#664fa3] hover:text-[#ff9e77] transition-colors">
|
||||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||||
Back to Home
|
Back to Home
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg">
|
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Join Our Community
|
Join Our Community
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Fill out the form below to start your membership journey.
|
Fill out the form below to start your membership journey.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -244,7 +244,7 @@ const Register = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={handleBack}
|
onClick={handleBack}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="rounded-full px-6 py-6 text-lg border-2 border-[#EAE0D5] hover:border-[#6B708D] text-[#3D405B]"
|
className="rounded-full px-6 py-6 text-lg border-2 border-[#ddd8eb] hover:border-[#664fa3] text-[#422268]"
|
||||||
>
|
>
|
||||||
<ArrowLeft className="mr-2 h-5 w-5" />
|
<ArrowLeft className="mr-2 h-5 w-5" />
|
||||||
Back
|
Back
|
||||||
@@ -257,7 +257,7 @@ const Register = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleNext}
|
onClick={handleNext}
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-6 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform"
|
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-6 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform"
|
||||||
>
|
>
|
||||||
Next
|
Next
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
@@ -266,7 +266,7 @@ const Register = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-6 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50 disabled:cursor-not-allowed"
|
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-6 py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
data-testid="submit-register-button"
|
data-testid="submit-register-button"
|
||||||
>
|
>
|
||||||
{loading ? 'Creating Account...' : 'Create Account'}
|
{loading ? 'Creating Account...' : 'Create Account'}
|
||||||
@@ -275,9 +275,9 @@ const Register = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-center text-[#6B708D] mt-4">
|
<p className="text-center text-[#664fa3] mt-4" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Already have an account?{' '}
|
Already have an account?{' '}
|
||||||
<Link to="/login" className="text-[#E07A5F] hover:underline font-medium">
|
<Link to="/login" className="text-[#ff9e77] hover:underline font-medium">
|
||||||
Login here
|
Login here
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -63,19 +63,19 @@ const ResetPassword = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-md mx-auto px-6 py-12">
|
<div className="max-w-md mx-auto px-6 py-12">
|
||||||
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg">
|
<Card className="p-8 md:p-12 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg">
|
||||||
<div className="mb-8 text-center">
|
<div className="mb-8 text-center">
|
||||||
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#FFF3E0] mb-4">
|
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-[#f1eef9] mb-4">
|
||||||
<Lock className="h-8 w-8 text-[#E07A5F]" />
|
<Lock className="h-8 w-8 text-[#664fa3]" />
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-4xl md:text-5xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-4xl md:text-5xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Reset Password
|
Reset Password
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Enter your new password below.
|
Enter your new password below.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -91,7 +91,7 @@ const ResetPassword = () => {
|
|||||||
value={formData.newPassword}
|
value={formData.newPassword}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="Enter new password (min. 6 characters)"
|
placeholder="Enter new password (min. 6 characters)"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -105,15 +105,15 @@ const ResetPassword = () => {
|
|||||||
value={formData.confirmPassword}
|
value={formData.confirmPassword}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
placeholder="Re-enter new password"
|
placeholder="Re-enter new password"
|
||||||
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
|
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-[#FFF3E0] border-l-4 border-[#E07A5F] p-4 rounded-lg">
|
<div className="bg-[#f1eef9] border-l-4 border-[#664fa3] p-4 rounded-lg">
|
||||||
<div className="flex items-start">
|
<div className="flex items-start">
|
||||||
<AlertCircle className="h-5 w-5 text-[#E07A5F] mr-2 mt-0.5 flex-shrink-0" />
|
<AlertCircle className="h-5 w-5 text-[#664fa3] mr-2 mt-0.5 flex-shrink-0" />
|
||||||
<div className="text-sm text-[#6B708D]">
|
<div className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
<p className="font-medium text-[#3D405B] mb-1">Password Requirements:</p>
|
<p className="font-medium text-[#422268] mb-1">Password Requirements:</p>
|
||||||
<ul className="list-disc list-inside space-y-1">
|
<ul className="list-disc list-inside space-y-1">
|
||||||
<li>At least 6 characters long</li>
|
<li>At least 6 characters long</li>
|
||||||
<li>Both passwords must match</li>
|
<li>Both passwords must match</li>
|
||||||
@@ -125,15 +125,15 @@ const ResetPassword = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="w-full bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
className="w-full bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full py-6 text-lg font-medium shadow-lg hover:scale-105 transition-transform disabled:opacity-50"
|
||||||
>
|
>
|
||||||
{loading ? 'Resetting Password...' : 'Reset Password'}
|
{loading ? 'Resetting Password...' : 'Reset Password'}
|
||||||
<ArrowRight className="ml-2 h-5 w-5" />
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<p className="text-center text-[#6B708D]">
|
<p className="text-center text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Remember your password?{' '}
|
Remember your password?{' '}
|
||||||
<Link to="/login" className="text-[#E07A5F] hover:underline font-medium">
|
<Link to="/login" className="text-[#ff9e77] hover:underline font-medium">
|
||||||
Login here
|
Login here
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -37,18 +37,18 @@ const VerifyEmail = () => {
|
|||||||
}, [token]);
|
}, [token]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#FDFCF8]">
|
<div className="min-h-screen bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="max-w-2xl mx-auto px-6 py-20">
|
<div className="max-w-2xl mx-auto px-6 py-20">
|
||||||
<Card className="p-12 bg-white rounded-2xl border border-[#EAE0D5] shadow-lg text-center">
|
<Card className="p-12 bg-white rounded-2xl border border-[#ddd8eb] shadow-lg text-center">
|
||||||
{status === 'loading' && (
|
{status === 'loading' && (
|
||||||
<>
|
<>
|
||||||
<Loader2 className="h-20 w-20 text-[#E07A5F] mx-auto mb-6 animate-spin" />
|
<Loader2 className="h-20 w-20 text-[#664fa3] mx-auto mb-6 animate-spin" />
|
||||||
<h1 className="text-3xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-3xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Verifying Your Email...
|
Verifying Your Email...
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D]">
|
<p className="text-lg text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Please wait while we verify your email address.
|
Please wait while we verify your email address.
|
||||||
</p>
|
</p>
|
||||||
</>
|
</>
|
||||||
@@ -57,18 +57,18 @@ const VerifyEmail = () => {
|
|||||||
{status === 'success' && (
|
{status === 'success' && (
|
||||||
<>
|
<>
|
||||||
<CheckCircle className="h-20 w-20 text-[#81B29A] mx-auto mb-6" />
|
<CheckCircle className="h-20 w-20 text-[#81B29A] mx-auto mb-6" />
|
||||||
<h1 className="text-3xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-3xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Email Verified Successfully!
|
Email Verified Successfully!
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D] mb-8">
|
<p className="text-lg text-[#664fa3] mb-8" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{message}
|
{message}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-base text-[#6B708D] mb-8">
|
<p className="text-base text-[#664fa3] mb-8" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
Next steps: Attend an event and meet a board member within 90 days. Once you've attended an event, our admin team will review your application.
|
Next steps: Attend an event and meet a board member within 90 days. Once you've attended an event, our admin team will review your application.
|
||||||
</p>
|
</p>
|
||||||
<Link to="/login">
|
<Link to="/login">
|
||||||
<Button
|
<Button
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-12 py-6 text-lg font-medium shadow-lg"
|
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-12 py-6 text-lg font-medium shadow-lg"
|
||||||
data-testid="login-redirect-button"
|
data-testid="login-redirect-button"
|
||||||
>
|
>
|
||||||
Go to Login
|
Go to Login
|
||||||
@@ -79,16 +79,16 @@ const VerifyEmail = () => {
|
|||||||
|
|
||||||
{status === 'error' && (
|
{status === 'error' && (
|
||||||
<>
|
<>
|
||||||
<XCircle className="h-20 w-20 text-[#E07A5F] mx-auto mb-6" />
|
<XCircle className="h-20 w-20 text-red-500 mx-auto mb-6" />
|
||||||
<h1 className="text-3xl font-semibold fraunces text-[#3D405B] mb-4">
|
<h1 className="text-3xl font-semibold text-[#422268] mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Verification Failed
|
Verification Failed
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-[#6B708D] mb-8">
|
<p className="text-lg text-[#664fa3] mb-8" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{message}
|
{message}
|
||||||
</p>
|
</p>
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<Button
|
<Button
|
||||||
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-12 py-6 text-lg font-medium shadow-lg"
|
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-12 py-6 text-lg font-medium shadow-lg"
|
||||||
data-testid="home-redirect-button"
|
data-testid="home-redirect-button"
|
||||||
>
|
>
|
||||||
Go to Home
|
Go to Home
|
||||||
|
|||||||
Reference in New Issue
Block a user