# LOAF Membership Platform - Frontend React 19-based frontend application for the LOAF (LGBT Organization and Friends) membership management platform. ## Table of Contents - [Setup & Installation](#setup--installation) - [Architecture & Code Structure](#architecture--code-structure) - [Design System](#design-system) - [Deployment Guide](#deployment-guide) - [Troubleshooting](#troubleshooting) --- ## Setup & Installation ### Prerequisites - **Node.js**: 18.0 or higher - **Yarn**: 1.22+ (or npm 8+) - **Backend API**: Running on http://localhost:8000 ### 1. Install Dependencies ```bash cd frontend # Using Yarn (recommended) yarn install # Or using npm npm install ``` **Key Dependencies:** - `react@19.0.0` - UI library - `react-router-dom@7.5.1` - Routing - `axios@1.8.4` - HTTP client - `react-hook-form@7.56.2` - Form handling - `zod@3.24.4` - Schema validation - `@radix-ui/*` - UI components (45+ components) - `tailwindcss@3.4.17` - CSS framework - `lucide-react@0.507.0` - Icons - `sonner@1.7.4` - Toast notifications ### 2. Environment Configuration Create `.env` file in the frontend directory: ```bash # Backend API URL REACT_APP_BACKEND_URL=http://localhost:8000 # Optional: Analytics, Sentry, etc. # REACT_APP_SENTRY_DSN=your-sentry-dsn # REACT_APP_GA_TRACKING_ID=UA-XXXXXXXXX-X ``` **Important:** - All environment variables must start with `REACT_APP_` - Restart development server after changing `.env` ### 3. Start Development Server ```bash # Start development server yarn start # Or with npm npm start ``` **Development server will be available at:** - Frontend: http://localhost:3000 - Auto-reloads on file changes ### 4. Build for Production ```bash # Create production build yarn build # Or with npm npm build ``` Build output will be in `/build` directory. ### 5. Run Tests ```bash # Run tests in watch mode yarn test # Run tests with coverage yarn test --coverage # Or with npm npm test ``` --- ## Architecture & Code Structure ### Project Structure ``` frontend/ ├── public/ # Static assets │ ├── loaf-logo.png # LOAF logo for admin sidebar │ ├── hero-loaf.png # Landing page hero image │ └── index.html # HTML template ├── src/ │ ├── pages/ # Page components (20+ pages) │ │ ├── Landing.js # Public landing page │ │ ├── Register.js # 4-step registration (388 lines) │ │ ├── Login.js # Authentication │ │ ├── Dashboard.js # Member dashboard │ │ ├── Profile.js # User profile with photo upload │ │ ├── Events.js # Event listing │ │ ├── EventDetails.js # Event details + RSVP │ │ └── admin/ # Admin pages │ │ ├── AdminDashboard.js │ │ ├── AdminUsers.js │ │ ├── AdminValidations.js # Approve/reject workflow │ │ ├── AdminEvents.js │ │ ├── AdminSubscriptions.js # With CSV export │ │ └── AdminDonations.js # Donation tracking │ ├── components/ # Reusable components │ │ ├── Navbar.js # Main navigation │ │ ├── AdminSidebar.js # Admin sidebar with logo │ │ ├── RejectionDialog.js # Rejection workflow dialog │ │ └── ui/ # 45+ Radix UI components │ │ ├── button.js │ │ ├── dialog.js │ │ ├── input.js │ │ ├── select.js │ │ └── ... (40+ more) │ ├── context/ │ │ └── AuthContext.js # Global auth state │ ├── hooks/ │ │ └── use-toast.js # Toast notification hook │ ├── utils/ │ │ └── api.js # Axios instance with JWT interceptor │ ├── App.js # Main routing setup │ ├── index.js # React entry point │ └── index.css # Global styles + Tailwind ├── craco.config.js # Craco configuration ├── tailwind.config.js # Tailwind CSS configuration ├── package.json # Dependencies └── .env # Environment variables (not in git) ``` ### Core Technologies | Technology | Purpose | Version | |------------|---------|---------| | React | UI library | 19.0.0 | | React Router | Client-side routing | 7.5.1 | | Axios | HTTP requests | 1.8.4 | | React Hook Form | Form handling | 7.56.2 | | Zod | Schema validation | 3.24.4 | | Tailwind CSS | CSS framework | 3.4.17 | | Radix UI | Component library | Latest | | Lucide React | Icons | 0.507.0 | | Sonner | Toast notifications | 1.7.4 | ### Key Features #### Authentication System **Global Auth Context** (`src/context/AuthContext.js`): - JWT token storage in localStorage - Automatic token injection via Axios interceptor - User state management - Protected route wrapper **Usage:** ```jsx import { useAuth } from '../context/AuthContext'; function MyComponent() { const { user, login, logout, isAuthenticated } = useAuth(); // user contains: id, email, first_name, last_name, role, status } ``` #### Protected Routes **PrivateRoute Wrapper:** ```jsx } /> // Admin-only route } /> ``` #### API Integration **Axios Instance** (`src/utils/api.js`): - Automatic JWT token injection - Request/response interceptors - Error handling - Base URL configuration **Usage:** ```jsx import api from '../utils/api'; // GET request const response = await api.get('/members/profile'); // POST request with data const response = await api.post('/admin/users/123/reject', { reason: 'Incomplete application' }); // File upload const formData = new FormData(); formData.append('file', file); const response = await api.post('/members/profile/upload-photo', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); ``` #### Form Handling **React Hook Form + Zod Pattern:** ```jsx import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; const schema = z.object({ email: z.string().email('Invalid email address'), password: z.string().min(8, 'Password must be at least 8 characters') }); function LoginForm() { const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(schema) }); const onSubmit = async (data) => { try { await api.post('/auth/login', data); toast.success('Login successful!'); } catch (error) { toast.error(error.response?.data?.detail || 'Login failed'); } }; return (
{errors.email && {errors.email.message}} {/* ... */}
); } ``` #### Toast Notifications **Using Sonner:** ```jsx import { toast } from 'sonner'; // Success toast.success('Profile updated successfully!'); // Error toast.error('Failed to upload photo'); // Custom toast('Processing...', { description: 'Please wait while we process your request' }); ``` ### Page Components #### Public Pages **Landing.js** - Hero section with LOAF branding - Feature highlights - Call-to-action buttons **Register.js** (388 lines) - 4-step registration wizard: 1. Basic Info (email, password, name) 2. Personal Details (phone, address, DOB) 3. Partner Information (optional) 4. Lead Sources & Referral - Form validation with Zod - Progress indicator - Email verification trigger **Login.js** - Email/password authentication - JWT token storage - Remember me functionality - Redirect to dashboard on success #### Member Pages **Dashboard.js** - Welcome message with user name - Upcoming events preview - Membership status card - Quick action buttons **Profile.js** - Profile photo upload with Avatar component - File validation (image types, 50MB max) - Personal information editing - Partner information - Save changes with API update **Events.js** - Event listing with filters - Search functionality - Upcoming/past events toggle - Event cards with cover images **EventDetails.js** - Full event information - RSVP form (Yes/No/Maybe) - Attendance confirmation - Google Maps integration (optional) #### Admin Pages **AdminDashboard.js** - Statistics overview - Pending validations count - Recent activity feed - Quick links to management pages **AdminUsers.js** - User listing with search/filters - Status badges - Bulk operations - CSV export **AdminValidations.js** - Pending user applications - Approve button - **Reject button with RejectionDialog** - Validation workflow management **AdminSubscriptions.js** - Subscription listing - Status filters (active, cancelled, expired) - **CSV export dropdown** (Export All / Export Current View) - Edit subscription dialog **AdminDonations.js** (400+ lines) - 4 stats cards: Total, Member, Public, Total Amount - Filters: type, status, date range, search - Responsive table with mobile cards - **CSV export functionality** **AdminEvents.js** - Event management interface - Create/edit events - Publish/unpublish toggle - Cover image upload - RSVP tracking - Attendance marking ### Component Library (Radix UI) **45+ UI Components** in `src/components/ui/`: **Form Components:** - Button, Input, Textarea, Checkbox, Radio - Select, Label, Form **Layout Components:** - Card, Dialog, Sheet (Drawer), Popover - Dropdown Menu, Tabs, Accordion **Feedback Components:** - Alert, Badge, Toast (Sonner) - Progress, Skeleton, Spinner **Navigation:** - Navigation Menu, Breadcrumb, Pagination **Usage Example:** ```jsx import { Button } from './components/ui/button'; import { Dialog, DialogContent, DialogTitle } from './components/ui/dialog'; import { Select, SelectTrigger, SelectContent, SelectItem } from './components/ui/select'; ``` ### Admin Sidebar Features **Logo Integration:** - LOAF logo in header - Shows logo + "Admin" text when expanded - Logo only when collapsed - Smooth transition animations **Navigation Groups:** - **Dashboard** (standalone) - **MEMBERSHIP** - Staff, Members, Validations - **FINANCIALS** - Plans, Subscriptions, Donations - **EVENTS & MEDIA** - Events, Gallery - **DOCUMENTATION** - Newsletters, Financial Reports, Bylaws - **Permissions** (Superadmin only) --- ## Design System ### Color Palette **LOAF Brand Colors:** ```css --primary: #422268 /* Deep Purple - Primary brand */ --secondary: #664fa3 /* Light Purple - Secondary elements */ --accent: #ff9e77 /* Coral - Accents and highlights */ --muted: #ddd8eb /* Light Purple Gray - Borders */ --background: #f9f5ff /* Very Light Purple - Backgrounds */ --foreground: #422268 /* Text color */ ``` **Usage in Tailwind:** ```jsx

Accent Text

Secondary Text

``` ### Typography **Font Families:** - **Headings**: 'Inter', sans-serif - **Body**: 'Nunito Sans', sans-serif - **Code**: 'Fira Code', monospace (if needed) **Font Sizes:** ```css text-xs → 0.75rem (12px) text-sm → 0.875rem (14px) text-base → 1rem (16px) text-lg → 1.125rem (18px) text-xl → 1.25rem (20px) text-2xl → 1.5rem (24px) text-3xl → 1.875rem (30px) ``` **Usage:** ```jsx

Page Title

Body text

``` ### Spacing System **Tailwind Spacing Scale:** ```css p-2 → 0.5rem (8px) p-4 → 1rem (16px) p-6 → 1.5rem (24px) p-8 → 2rem (32px) gap-2, gap-4, gap-6, gap-8 (same scale for flex/grid gaps) ``` ### Component Styling Patterns **Cards:** ```jsx {/* Content */} ``` **Buttons:** ```jsx // Primary // Secondary // Destructive ``` **Form Inputs:** ```jsx