many styling changes and updates

This commit is contained in:
2026-02-04 16:57:25 -06:00
parent 79a727e7ba
commit 356031ad15
21 changed files with 163 additions and 122 deletions

View File

@@ -6,7 +6,7 @@
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<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="#664fa3" /> <meta name="theme-color" content="#664fa3" />
<meta name="description" content="LOAF - Lesbian Organization of Atlanta Family" /> <meta name="description" content="LOAF - Lesbians Over Age Fifty" />
<!-- Google Fonts --> <!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">

View File

@@ -10,7 +10,7 @@ const MemberBadge = ({ memberSince, tiers }) => {
return ( return (
<Badge className={`px-3 py-2 rounded-md text-sm flex items-center gap-2 border hover:text-white ${tier.badgeClass}`}> <Badge className={`px-3 py-2 rounded-md text-sm flex items-center gap-2 border hover:text-white ${tier.badgeClass}`}>
<Icon className="size-6" /> <Icon className="size-4" />
{tier.label} {tier.label}
</Badge> </Badge>
); );

View File

@@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import { Card } from './ui/card'; import { Card } from './ui/card';
import { Button } from './ui/button'; import { Button } from './ui/button';
import { Heart, Calendar, Mail, Phone, MapPin, Facebook, Instagram, Twitter, Linkedin, UserCircle } from 'lucide-react'; import { Heart, Calendar, Mail, User, Phone, MapPin, Facebook, Instagram, Twitter, Linkedin, UserCircle, UserRound } from 'lucide-react';
import MemberBadge from './MemberBadge'; import MemberBadge from './MemberBadge';
import useDirectoryConfig from '../hooks/use-directory-config'; import useDirectoryConfig from '../hooks/use-directory-config';
@@ -28,15 +28,17 @@ const MemberCard = ({ member, onViewProfile, tiers }) => {
<div className='flex justify-end items-center mb-2'> <div className='flex justify-end items-center mb-2'>
<MemberBadge memberSince={memberSince} tiers={tiers} /> <MemberBadge memberSince={memberSince} tiers={tiers} />
</div> </div>
<div className='flex gap-3 items-start'>
<div className="flex justify-center mb-4"> <div className="flex justify-center mb-4">
{member.profile_photo_url ? ( {member.profile_photo_url ? (
<img <img
src={member.profile_photo_url} src={member.profile_photo_url}
alt={`${member.first_name} ${member.last_name}`} alt={`${member.first_name} ${member.last_name}`}
className="w-32 h-32 rounded-full object-cover border-4 border-[var(--neutral-800)]" className="size-20 rounded-full object-cover border-4 border-[var(--neutral-800)]"
/> />
) : ( ) : (
<div className="w-32 h-32 rounded-full bg-[var(--neutral-800)] border-4 border-[var(--neutral-800)] flex items-center justify-center"> <div className="size-20 rounded-full bg-[var(--neutral-800)] border-4 border-[var(--neutral-800)] flex items-center justify-center">
<span className="text-4xl font-semibold text-brand-purple " style={{ fontFamily: "'Inter', sans-serif" }}> <span className="text-4xl font-semibold text-brand-purple " style={{ fontFamily: "'Inter', sans-serif" }}>
{getInitials(member.first_name, member.last_name)} {getInitials(member.first_name, member.last_name)}
</span> </span>
@@ -44,10 +46,26 @@ const MemberCard = ({ member, onViewProfile, tiers }) => {
)} )}
</div> </div>
<div className='pt-4'>
{/* Name */} {/* Name */}
<h3 className="text-2xl font-semibold text-[var(--purple-ink)] text-center mb-3" style={{ fontFamily: "'Inter', sans-serif" }}> <h3 className="text-2xl font-semibold text-[var(--purple-ink)] text-center mb-3" style={{ fontFamily: "'Inter', sans-serif" }}>
{member.first_name} {member.last_name} {member.first_name} {member.last_name}
</h3> </h3>
{/* Member Since */}
{memberSince && (
<div className="flex gap-2 mb-4">
<Calendar className="size-4 text-brand-lavender " />
<span className="text-sm text-brand-purple font-medium" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Member since {new Date(memberSince).toLocaleDateString('en-US', {
// month: 'short',
year: 'numeric'
})}
</span>
</div>
)}
</div>
</div>
{/* Partner Name */} {/* Partner Name */}
{isFieldEnabled('directory_partner_name') && member.directory_partner_name && ( {isFieldEnabled('directory_partner_name') && member.directory_partner_name && (
@@ -66,19 +84,6 @@ const MemberCard = ({ member, onViewProfile, tiers }) => {
</p> </p>
)} )}
{/* Member Since */}
{memberSince && (
<div className="flex items-center justify-center gap-2 mb-4">
<Calendar className="h-4 w-4 text-brand-purple " />
<span className="text-sm text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Member since {new Date(memberSince).toLocaleDateString('en-US', {
month: 'long',
year: 'numeric'
})}
</span>
</div>
)}
{/* Contact Information */} {/* Contact Information */}
<div className="space-y-3 mb-4"> <div className="space-y-3 mb-4">
{isFieldEnabled('directory_email') && member.directory_email && ( {isFieldEnabled('directory_email') && member.directory_email && (
@@ -94,27 +99,6 @@ const MemberCard = ({ member, onViewProfile, tiers }) => {
</div> </div>
)} )}
{isFieldEnabled('directory_phone') && member.directory_phone && (
<div className="flex items-center gap-2 text-sm">
<Phone className="h-4 w-4 text-brand-purple flex-shrink-0" />
<a
href={`tel:${member.directory_phone}`}
className="text-brand-purple hover:text-[var(--purple-ink)]"
style={{ fontFamily: "'Nunito Sans', sans-serif" }}
>
{member.directory_phone}
</a>
</div>
)}
{isFieldEnabled('directory_address') && member.directory_address && (
<div className="flex items-start gap-2 text-sm">
<MapPin className="h-4 w-4 text-brand-purple flex-shrink-0 mt-0.5" />
<span className="text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{member.directory_address}
</span>
</div>
)}
</div> </div>
{/* Social Media Links */} {/* Social Media Links */}
@@ -171,14 +155,14 @@ const MemberCard = ({ member, onViewProfile, tiers }) => {
</div> </div>
</div> </div>
)} )}
<div className='border-b-2 mx-4 border-[var(--neutral-800)] mb-6'></div>
{/* View Profile Button */} {/* View Profile Button */}
<div className="pt-4 mt-4 border-t border-[var(--neutral-800)]"> <div className=" ">
<Button <Button
onClick={() => onViewProfile?.(member.id)} onClick={() => onViewProfile?.(member.id)}
className="w-full bg-[var(--neutral-800)] text-[var(--purple-ink)] hover:bg-brand-purple hover:text-white rounded-full py-5" className="w-full bg-brand-purple text-background hover:bg-brand-purple/90 hover:text-white rounded-full py-5"
> >
<UserCircle className="h-4 w-4 mr-2" /> <UserRound className="size-6 mr-2 font-bold text-brand-lavender" />
View Full Profile View Full Profile
</Button> </Button>
</div> </div>

View File

@@ -13,7 +13,7 @@ const MemberFooter = () => {
LOAF LOAF
</h3> </h3>
<p className="text-gray-300 text-sm" style={{ fontFamily: "'Nunito Sans', sans-serif" }}> <p className="text-gray-300 text-sm" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Lesbian Organization of Atlanta Family Lesbians Over Age Fifty
</p> </p>
</div> </div>

View File

@@ -71,7 +71,7 @@ const BecomeMember = () => {
</div> </div>
{/* Membership Process Section */} {/* Membership Process Section */}
<div className="relative bg-gray-50 py-32 bg-gradient-to-bl from-[var(--neutral-100:)] to-[var(--neutral-800)] "> <div className="relative bg-gray-50 py-32 bg-gradient-to-bl from-[var(--neutral-100)] to-[var(--neutral-800)] ">
{/* Decorative shooting star element */} {/* Decorative shooting star element */}
<div className="hidden lg:block absolute left-0 top-64 w-[195px] h-[1130px] pointer-events-none opacity-50"> <div className="hidden lg:block absolute left-0 top-64 w-[195px] h-[1130px] pointer-events-none opacity-50">
<img <img

View File

@@ -69,7 +69,7 @@ const BoardOfDirectors = () => {
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-background">
<PublicNavbar /> <PublicNavbar />
<main className="bg-gradient-to-b from-[var(--neutral-100:)] to-[var(--neutral-800)] pt-8 sm:pt-10 md:pt-12"> <main className="bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)] pt-8 sm:pt-10 md:pt-12">
{/* Hero Section */} {/* Hero Section */}
<section className=" pt-16 pb-4 px-4 sm:px-6 md:px-8 lg:px-12 xl:px-20"> <section className=" pt-16 pb-4 px-4 sm:px-6 md:px-8 lg:px-12 xl:px-20">
<div className="max-w-5xl mx-auto text-center px-8"> <div className="max-w-5xl mx-auto text-center px-8">

View File

@@ -136,7 +136,7 @@ const Dashboard = () => {
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<Navbar /> <Navbar />
<div className="max-w-7xl mx-auto px-6 py-12"> <div className="max-w-7xl mx-auto px-6 py-12">
@@ -286,7 +286,7 @@ const Dashboard = () => {
{loading ? ( {loading ? (
<p className="text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Loading events...</p> <p className="text-brand-purple " 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 gap-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
@@ -311,7 +311,7 @@ const Dashboard = () => {
))} ))}
</div> </div>
) : ( ) : (
<div className="text-center py-12"> <div className="text-center gap-4 py-12">
<Calendar className="h-16 w-16 text-[var(--neutral-800)] mx-auto mb-4" /> <Calendar className="h-16 w-16 text-[var(--neutral-800)] mx-auto mb-4" />
<p className="text-brand-purple mb-4" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>No upcoming events at the moment.</p> <p className="text-brand-purple mb-4" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>No upcoming events at the moment.</p>
<p className="text-sm text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Check back later for new events!</p> <p className="text-sm text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>Check back later for new events!</p>

View File

@@ -58,7 +58,7 @@ const Donate = () => {
<div className="min-h-screen"> <div className="min-h-screen">
<PublicNavbar /> <PublicNavbar />
<main className="bg-gradient-to-bl from-[var(--neutral-100:)] to-[var(--neutral-800)] px-4 sm:px-6 md:px-8 lg:px-12 xl:px-16 py-8 sm:py-10 md:py-12"> <main className="bg-gradient-to-bl from-[var(--neutral-100)] to-[var(--neutral-800)] px-4 sm:px-6 md:px-8 lg:px-12 xl:px-16 py-8 sm:py-10 md:py-12">
{/* Hero Section */} {/* Hero Section */}
<section className="py-12"> <section className="py-12">
<div className="max-w-4xl mx-auto text-center h-full"> <div className="max-w-4xl mx-auto text-center h-full">

View File

@@ -46,7 +46,7 @@ const Events = () => {
}; };
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<Navbar /> <Navbar />
<div className="max-w-7xl mx-auto px-6 py-12"> <div className="max-w-7xl mx-auto px-6 py-12">

View File

@@ -46,7 +46,7 @@ const History = () => {
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-background">
<PublicNavbar /> <PublicNavbar />
<main className="bg-gradient-to-br from-[var(--neutral-100:)] to-[var(--neutral-700)] px-4 sm:px-6 md:px-8 lg:px-12 xl:px-16 py-8 sm:py-10 md:py-12"> <main className="bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)] px-4 sm:px-6 md:px-8 lg:px-12 xl:px-16 py-8 sm:py-10 md:py-12">
{/* Hero Section */} {/* Hero Section */}
<section className="py-12"> <section className="py-12">
<div className="max-w-3xl mx-auto flex justify-around mb-12 flex-col gap-6 items-center lg:flex-row"> <div className="max-w-3xl mx-auto flex justify-around mb-12 flex-col gap-6 items-center lg:flex-row">

View File

@@ -84,12 +84,14 @@ const Landing = () => {
<div className="absolute inset-0 z-[1] bg-background/5 backdrop-blur-xs"></div> <div className="absolute inset-0 z-[1] bg-background/5 backdrop-blur-xs"></div>
{/* Left column Loaf Image */} {/* Left column Loaf Image */}
<div className="relative z-10 lg:py-20 py-7 flex flex-col gap-6 sm:gap-8 items-center justify-center w-full lg:w-[530px] lg:flex-shrink-0"> <div className="relative z-10 lg:py-20 py-7 flex flex-col gap-6 sm:gap-8 items-center justify-center w-full lg:w-[530px] lg:flex-shrink-0">
<div className="flex flex-col gap-6 items-center"> <div className="flex flex-col gap-3 items-center">
<img src={heroLoaf} alt="LOAF" className="w-full max-w-xs md:max-w-[370px] h-auto object-contain" /> <img src={heroLoaf} alt="LOAF" className="w-full max-w-xs md:max-w-[370px] h-auto object-contain" />
<div className='text-background font-medium text-[2rem] text-center mb-2'>Lesbians Over Age Fifty</div>
</div> </div>
<div className="flex flex-col gap-4 items-center justify-center w-full max-w-[339px]"> <div className="flex flex-col gap-4 items-center justify-center w-full max-w-[339px]">
<Link to="/become-a-member" className="w-full"> <Link to="/become-a-member" className="w-full">
<Button style={{ fontFamily: "'Nunito sans', sans-serif" }} className="bg-[var(--neutral-800)] hover:bg-background text-[var(--purple-ink)] rounded-full px-6 py-6 sm:py-[32px] text-base sm:text-lg font-medium w-full transition-colors"> <Button style={{ fontFamily: "'Nunito sans', sans-serif" }} className="bg-[var(--neutral-800)] hover:bg-background text-[var(--purple-ink)] rounded-full px-6 py-6 sm:py-[32px] text-base sm:text-lg font-semibold w-full transition-colors">
Become a Member Become a Member
</Button> </Button>
</Link> </Link>
@@ -107,11 +109,11 @@ const Landing = () => {
{/* About Section */} {/* About Section */}
<section id="about" className="bg-gradient-to-b pb-10 lg:pb-44 from-white to-[var(--lavender-300)] px-4 sm:px-6 md:px-8 lg:px-12 xl:px-16 pt-4 sm:pt-16 md:pt-20 lg:pt-30 flex flex-col"> <section id="about" className="bg-gradient-to-b pb-10 lg:pb-44 from-white to-[var(--lavender-300)] px-4 sm:px-6 md:px-8 lg:px-12 xl:px-16 pt-4 sm:pt-16 md:pt-20 lg:pt-30 flex flex-col">
<div className="flex flex-col items-center pt-4"> <div className="flex flex-col items-center pt-4">
<h3 className="text-[var(--purple-deep)] px-4 pb-6 md:py-8 text-4xl leading-[60px] md:text-5xl lg:text-6xl font-extrabold text-center" style={{ fontFamily: "'Inter', sans-serif" }}> <h3 className="text-[var(--purple-deep)] px-4 pb-6 md:py-8 text-4xl leading-[60px] md:text-5xl lg:text-6xl font-extrabold text-center" style={{ fontFamily: "'Poppins', sans-serif" }}>
Welcome to LOAF Welcome to LOAF
</h3> </h3>
</div> </div>
<p className="text-[rgba(0,0,0,0.55)] text-lg lg:text-2xl text-center font-medium" style={{ fontFamily: "'Inter', sans-serif" }}> <p className="text-[rgba(0,0,0,0.55)] text-lg lg:text-2xl text-center mx-auto font-medium max-w-[940px]" style={{ fontFamily: "'Poppins', 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. 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" /> <img src={shootingStar} alt="Decorative element" className="w-full h-[197px] object-contain" />
@@ -129,7 +131,7 @@ const Landing = () => {
<div className="flex flex-col-reverse md:flex-col lg:flex-row gap-8 sm:gap-10 md:gap-12 items-center justify-center w-full max-w-6xl"> <div className="flex flex-col-reverse md:flex-col lg:flex-row gap-8 sm:gap-10 md:gap-12 items-center justify-center w-full max-w-6xl">
<Link to="/register" className="w-full sm:w-auto flex items-center justify-center"> <Link to="/register" className="w-full sm:w-auto flex items-center justify-center">
<Button className="bg-[var(--neutral-800)] hover:bg-background text-[var(--purple-ink)] rounded-full <Button className="bg-[var(--neutral-800)] hover:bg-background text-[var(--purple-ink)] rounded-full
py-8 text-xl font-normal px-12 sm:w-[392px] transition-colors "> py-8 text-xl font-medium px-12 sm:w-[392px] transition-colors ">
Become a Member Become a Member
</Button> </Button>
</Link> </Link>

View File

@@ -82,10 +82,10 @@ const Login = () => {
}; };
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<PublicNavbar /> <PublicNavbar />
<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-brand-purple hover:text-[var(--orange-light)] transition-colors"> <Link to="/" className="inline-flex items-center text-brand-purple hover:text-[var(--orange-light)] transition-colors">
<ArrowLeft className="h-4 w-4 mr-2" /> <ArrowLeft className="h-4 w-4 mr-2" />

View File

@@ -12,7 +12,7 @@ const MissionValues = () => {
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-background">
<PublicNavbar /> <PublicNavbar />
<main className="bg-gradient-to-b from-[var(--neutral-100:)] to-[var(--neutral-800)] px-4 sm:px-6 py-8 sm:py-12 md:py-20"> <main className="bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)] px-4 sm:px-6 py-8 sm:py-12 md:py-20">
<div className="max-w-[1400px] mx-auto"> <div className="max-w-[1400px] mx-auto">
<div className="flex md:flex-row flex-col gap-10 items-stretch"> <div className="flex md:flex-row flex-col gap-10 items-stretch">
{/* Left Card - Mission (Purple Gradient) */} {/* Left Card - Mission (Purple Gradient) */}

View File

@@ -7,7 +7,7 @@ export default function PrivacyPolicy() {
return ( return (
<> <>
<PublicNavbar /> <PublicNavbar />
<main className="bg-gradient-to-bl from-[var(--neutral-100:)] to-[var(--neutral-800)] text-[var(--purple-deep)]"> <main className="bg-gradient-to-bl from-[var(--neutral-100)] to-[var(--neutral-800)] text-[var(--purple-deep)]">
<div className="mx-auto w-full max-w-5xl px-4 sm:px-6 lg:px-8 py-10"> <div className="mx-auto w-full max-w-5xl px-4 sm:px-6 lg:px-8 py-10">
<header className="border-b pb-6"> <header className="border-b pb-6">
<h1 className="text-3xl sm:text-4xl font-bold tracking-tight" style={{ fontFamily: 'Poppins' }}> <h1 className="text-3xl sm:text-4xl font-bold tracking-tight" style={{ fontFamily: 'Poppins' }}>

View File

@@ -8,7 +8,7 @@ export default function TermsOfService() {
return ( return (
<> <>
<PublicNavbar /> <PublicNavbar />
<main className="bg-gradient-to-bl from-[var(--neutral-100:)] to-[var(--neutral-800)] text-[var(--purple-deep)]"> <main className="bg-gradient-to-bl from-[var(--neutral-100)] to-[var(--neutral-800)] text-[var(--purple-deep)]">
<div className="mx-auto w-full max-w-5xl px-4 sm:px-6 lg:px-8 py-10"> <div className="mx-auto w-full max-w-5xl px-4 sm:px-6 lg:px-8 py-10">
{/* Title */} {/* Title */}
<header className="border-b pb-6"> <header className="border-b pb-6">

View File

@@ -108,7 +108,7 @@ export default function Bylaws() {
} }
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<Navbar /> <Navbar />
<div className="max-w-5xl mx-auto px-6 py-12"> <div className="max-w-5xl mx-auto px-6 py-12">

View File

@@ -159,7 +159,7 @@ const EventGallery = () => {
// Event Gallery Grid View // Event Gallery Grid View
if (!selectedEvent) { if (!selectedEvent) {
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<Navbar /> <Navbar />
<div className="max-w-7xl mx-auto px-6 py-12"> <div className="max-w-7xl mx-auto px-6 py-12">

View File

@@ -87,7 +87,7 @@ export default function Financials() {
} }
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<Navbar /> <Navbar />
<div className="max-w-5xl mx-auto px-6 py-12"> <div className="max-w-5xl mx-auto px-6 py-12">

View File

@@ -89,6 +89,20 @@ export default function MemberCalendar() {
setRsvpLoading(false); setRsvpLoading(false);
} }
}; };
const getReadableTextColor = (hex) => {
const cleaned = hex.replace('#', '');
const r = parseInt(cleaned.substring(0, 2), 16) / 255;
const g = parseInt(cleaned.substring(2, 4), 16) / 255;
const b = parseInt(cleaned.substring(4, 6), 16) / 255;
const srgb = [r, g, b].map((c) =>
c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
);
const luminance = 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
// tweak threshold to taste
return luminance > 0.6 ? 'var(--brand-purple)' : 'white';
};
const eventStyleGetter = (event) => { const eventStyleGetter = (event) => {
const rsvpStatus = event.resource?.user_rsvp_status; const rsvpStatus = event.resource?.user_rsvp_status;
@@ -99,12 +113,16 @@ export default function MemberCalendar() {
if (rsvpStatus === 'yes') { if (rsvpStatus === 'yes') {
backgroundColor = '#81B29A'; backgroundColor = '#81B29A';
borderColor = '#66927e'; borderColor = '#66927e';
} else if (rsvpStatus === 'no') { } else if (rsvpStatus === 'no') {
backgroundColor = '#9ca3af'; backgroundColor = '#9ca3af';
borderColor = '#6b7280'; borderColor = '#6b7280';
} else if (rsvpStatus === 'maybe') { } else if (rsvpStatus === 'maybe') {
backgroundColor = '#fb923c'; backgroundColor = '#fb923c';
borderColor = '#ea580c'; borderColor = '#ea580c';
} }
return { return {
@@ -114,7 +132,7 @@ export default function MemberCalendar() {
borderWidth: '2px', borderWidth: '2px',
borderStyle: 'solid', borderStyle: 'solid',
borderRadius: '6px', borderRadius: '6px',
color: 'white', color: getReadableTextColor(backgroundColor),
fontWeight: '500', fontWeight: '500',
fontSize: '0.875rem', fontSize: '0.875rem',
padding: '2px 6px', padding: '2px 6px',
@@ -136,7 +154,7 @@ export default function MemberCalendar() {
} }
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<Navbar /> <Navbar />
<div className="max-w-7xl mx-auto px-6 py-12"> <div className="max-w-7xl mx-auto px-6 py-12">
@@ -175,7 +193,7 @@ export default function MemberCalendar() {
</div> </div>
</div> </div>
<Card className="p-6 bg-background rounded-2xl border border-[var(--neutral-800)] shadow-lg"> <Card className="p-6 bg-background text-brand-purple rounded-2xl border border-[var(--neutral-800)] shadow-lg">
<Calendar <Calendar
localizer={localizer} localizer={localizer}
events={calendarEvents} events={calendarEvents}
@@ -190,7 +208,7 @@ export default function MemberCalendar() {
eventPropGetter={eventStyleGetter} eventPropGetter={eventStyleGetter}
views={['month', 'week', 'day', 'agenda']} views={['month', 'week', 'day', 'agenda']}
popup popup
className="member-calendar" className="member-calendar "
/> />
</Card> </Card>
@@ -275,9 +293,10 @@ export default function MemberCalendar() {
onClick={() => handleRSVP('yes')} onClick={() => handleRSVP('yes')}
disabled={rsvpLoading} disabled={rsvpLoading}
size="sm" size="sm"
variant='outline'
className={`rounded-full px-6 flex items-center gap-2 ${selectedEvent.user_rsvp_status === 'yes' className={`rounded-full px-6 flex items-center gap-2 ${selectedEvent.user_rsvp_status === 'yes'
? 'bg-[var(--green-light)] text-white hover:bg-[var(--green-muted)]' ? 'border-success bg-success/20 text-success'
: 'bg-[var(--neutral-800)] text-[var(--purple-ink)] hover:bg-[var(--neutral-400:)]' : 'border-brand-purple text-brand-purple hover:bg-[var(--lavender-300)]'
}`} }`}
> >
<Check className="h-4 w-4" /> <Check className="h-4 w-4" />
@@ -303,7 +322,7 @@ export default function MemberCalendar() {
variant="outline" variant="outline"
className={`rounded-full px-6 flex items-center gap-2 border-2 ${selectedEvent.user_rsvp_status === 'no' className={`rounded-full px-6 flex items-center gap-2 border-2 ${selectedEvent.user_rsvp_status === 'no'
? 'border-gray-400 bg-gray-100 text-gray-700' ? 'border-gray-400 bg-gray-100 text-gray-700'
: 'border-gray-400 text-gray-600 hover:bg-gray-50' : 'border-brand-purple text-brand-purple hover:bg-[var(--lavender-300)]'
}`} }`}
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />

View File

@@ -14,13 +14,33 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from '../../components/ui/dialog'; } from '../../components/ui/dialog';
import { User, Search, Mail, MapPin, Phone, Heart, Facebook, Instagram, Twitter, Linkedin, UserCircle, Calendar } from 'lucide-react'; import {
User,
Search,
Mail,
MapPin,
Phone,
Heart,
Facebook,
Instagram,
Twitter,
Linkedin,
CircleUserRound,
Calendar,
ChevronsRight,
ChevronRight,
ChevronLeft,
ChevronsLeft,
UserRound
} from 'lucide-react';
import { useToast } from '../../hooks/use-toast'; import { useToast } from '../../hooks/use-toast';
import MemberCard from '../../components/MemberCard'; import MemberCard from '../../components/MemberCard';
import MemberBadge from '../../components/MemberBadge'; import MemberBadge from '../../components/MemberBadge';
import useMembers from '../../hooks/use-members'; import useMembers from '../../hooks/use-members';
import useMemberTiers from '../../hooks/use-member-tiers'; import useMemberTiers from '../../hooks/use-member-tiers';
import useDirectoryConfig from '../../hooks/use-directory-config'; import useDirectoryConfig from '../../hooks/use-directory-config';
import { useThemeConfig } from '@/context/ThemeConfigContext';
const MembersDirectory = () => { const MembersDirectory = () => {
const [selectedMember, setSelectedMember] = useState(null); const [selectedMember, setSelectedMember] = useState(null);
@@ -37,6 +57,12 @@ const MembersDirectory = () => {
} }
return status; return status;
}, []); }, []);
const { getLogoUrl } = useThemeConfig();
// Get logo URL from theme config (with fallback to default)
const logo = getLogoUrl();
const normalizeMembers = useCallback( const normalizeMembers = useCallback(
(data) => { (data) => {
const list = Array.isArray(data) const list = Array.isArray(data)
@@ -147,18 +173,27 @@ const MembersDirectory = () => {
<div className='px-9'> <div className='px-9'>
{/* Header */} {/* Header */}
<div className="m-8 mt-14 flex flex-col sm:flex-row justify-between items-center "> <div className="my-8 mb-8 mt-14 gap-4 flex flex-col sm:flex-row items-center ">
<Link to="/dashboard">
<img src={logo} alt="LOAF Logo" className="h-16 w-16 sm:h-20 sm:w-20 md:h-28 md:w-28 object-contain" />
</Link>
<div className='flex flex-col items-start'>
<h1 className="text-4xl md:text-5xl font-bold text-[var(--purple-ink)] mb-4" style={{ fontFamily: "'Poppins', sans-serif" }}> <h1 className="text-4xl md:text-5xl font-bold text-[var(--purple-ink)] mb-4" style={{ fontFamily: "'Poppins', sans-serif" }}>
LOAF Members Members Directory
</h1> </h1>
<p className="text-lg " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<span className='text-foreground'>Number of current members in the directory: </span> <span className='text-brand-purple font-medium'>{totalMembers}</span> <p className="text-lg font-bold flex gap-2" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<UserRound className='text-brand-purple/80' />
<span className='text-foreground'>Active Members Count: </span> <span className='text-brand-purple font-medium'>{totalMembers}</span>
</p> </p>
</div> </div>
</div>
{/* Search Bar */} {/* Search Bar */}
<div className="mb-24 w-full"> <div className=" w-full flex gap-3">
<div className="relative w-full "> <div className="relative w-full ">
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-brand-purple " /> <Search className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-brand-purple " />
<Input <Input
type="text" type="text"
@@ -169,17 +204,19 @@ const MembersDirectory = () => {
style={{ fontFamily: "'Nunito Sans', sans-serif" }} style={{ fontFamily: "'Nunito Sans', sans-serif" }}
/> />
</div> </div>
<Button size='lg' className='self-center bg-brand-purple hover:bg-brand-purple/90 px-16'>Search</Button>
<Button className='text-brand-purple/80 bg-transparent hover:bg-transparent hover:underline shadow-none p-2 self-center'>Clear Search</Button>
</div>
{searchQuery && ( {searchQuery && (
<p className="mt-3 text-sm text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}> <p className="mt-3 text-sm ml-6 text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif " }}>
Found {filteredMembers.length} {filteredMembers.length === 1 ? 'member' : 'members'} Found {filteredMembers.length} {filteredMembers.length === 1 ? 'member' : 'members'}
</p> </p>
)} )}
</div> <div className='mb-24'></div>
</div> </div>
{/* Border Decoration */} {/* Border Decoration */}
<Border className='' />
<Border />
{/* Members Grid */} {/* Members Grid */}
{loading ? ( {loading ? (
@@ -206,23 +243,21 @@ const MembersDirectory = () => {
</div> </div>
)} )}
{/* Border Decoration */} {/* Border Decoration */}
<Border yaxis="true" /> <Border yaxis="true" />
{/* todo: use badge to display if member */} {/* todo: use badge to display if member */}
{/* Info Card */} {/* Info Card */}
{!loading && members.length > 0 && ( {!loading && members.length > 0 && (
<Card className="mt-12 p-6 bg-[var(--lavender-500)] border-[var(--neutral-800)]"> <Card className="mt-12 p-4 bg-[var(--lavender-500)] border-[var(--neutral-800)]">
<div className="flex items-start gap-4"> <div className="flex items-start gap-4">
<div className="bg-[var(--neutral-800)]/20 p-3 rounded-lg"> <div className="bg-[var(--neutral-800)]/20 rounded-lg">
<User className="h-6 w-6 text-brand-purple " /> <CircleUserRound className="size-20 text-brand-lavender " />
</div> </div>
<div> <div className='self-center'>
<h3 className="text-lg font-semibold text-[var(--purple-ink)] mb-2" style={{ fontFamily: "'Inter', sans-serif" }}> <h3 className="text-lg font-semibold text-[var(--purple-ink)] mb-2" style={{ fontFamily: "'Poppins', sans-serif" }}>
Want to appear in the directory? Want to appear in the directory?
</h3> </h3>
<p className="text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}> <p className="text-brand-purple/90 font-medium " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Update your profile settings to show in the directory and add your photo, bio, and contact information.{' '} Update your profile settings to show in the directory and add your photo, bio, and contact information.{' '}
<Link to="/profile" className="text-[var(--orange-light)] hover:underline font-medium"> <Link to="/profile" className="text-[var(--orange-light)] hover:underline font-medium">
@@ -432,16 +467,16 @@ const MembersDirectory = () => {
<Button <Button
onClick={() => setCurrentPage(1)} onClick={() => setCurrentPage(1)}
disabled={currentPage === 1} disabled={currentPage === 1}
className="bg-[var(--neutral-800)] rounded-full text-[var(--purple-ink)] hover:bg-brand-purple hover:text-white" className="bg-transparent text-brand-purple shadow-none "
> >
First Page <ChevronsLeft />
</Button> </Button>
<Button <Button
onClick={() => setCurrentPage((page) => Math.max(1, page - 1))} onClick={() => setCurrentPage((page) => Math.max(1, page - 1))}
disabled={currentPage === 1} disabled={currentPage === 1}
className="bg-[var(--neutral-800)] rounded-full text-[var(--purple-ink)] hover:bg-brand-purple hover:text-white" className="bg-transparent text-brand-purple shadow-none"
> >
Previous <ChevronLeft size={64} />
</Button> </Button>
{Array.from({ length: totalPages }, (_, index) => { {Array.from({ length: totalPages }, (_, index) => {
@@ -465,16 +500,17 @@ const MembersDirectory = () => {
<Button <Button
onClick={() => setCurrentPage((page) => Math.min(totalPages, page + 1))} onClick={() => setCurrentPage((page) => Math.min(totalPages, page + 1))}
disabled={currentPage === totalPages} disabled={currentPage === totalPages}
className="bg-[var(--neutral-800)] text-[var(--purple-ink)] hover:bg-brand-purple rounded-full hover:text-white" className="bg-transparent text-brand-purple shadow-none"
> >
Next <ChevronRight />
</Button> </Button>
<Button <Button
onClick={() => setCurrentPage(totalPages)} onClick={() => setCurrentPage(totalPages)}
disabled={currentPage === totalPages} disabled={currentPage === totalPages}
className="bg-[var(--neutral-800)] text-[var(--purple-ink)] hover:bg-brand-purple rounded-full hover:text-white" className="bg-transparent text-brand-purple shadow-none"
> >
Last Page <ChevronsRight />
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -95,7 +95,7 @@ export default function NewsletterArchive() {
} }
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-gradient-to-b from-[var(--neutral-100)] to-[var(--neutral-800)]">
<Navbar /> <Navbar />
<div className="max-w-7xl mx-auto px-6 py-12"> <div className="max-w-7xl mx-auto px-6 py-12">