From 68ee22c1245dcfda4e608ebedd5b4a8cac2e0336 Mon Sep 17 00:00:00 2001 From: Koncept Kit <63216427+konceptkit@users.noreply.github.com> Date: Sun, 1 Feb 2026 19:53:45 +0700 Subject: [PATCH] Changes --- src/App.js | 2 + src/components/SettingsSidebar.js | 3 +- .../registration/DynamicFormField.js | 411 ++++++ .../registration/DynamicRegistrationForm.js | 482 +++++++ src/pages/Register.js | 383 +++--- src/pages/admin/AdminRegistrationBuilder.js | 1156 +++++++++++++++++ 6 files changed, 2260 insertions(+), 177 deletions(-) create mode 100644 src/components/registration/DynamicFormField.js create mode 100644 src/components/registration/DynamicRegistrationForm.js create mode 100644 src/pages/admin/AdminRegistrationBuilder.js diff --git a/src/App.js b/src/App.js index f7219db..e8ffa65 100644 --- a/src/App.js +++ b/src/App.js @@ -47,6 +47,7 @@ import AdminGallery from './pages/admin/AdminGallery'; import AdminNewsletters from './pages/admin/AdminNewsletters'; import AdminFinancials from './pages/admin/AdminFinancials'; import AdminBylaws from './pages/admin/AdminBylaws'; +import AdminRegistrationBuilder from './pages/admin/AdminRegistrationBuilder'; import History from './pages/History'; import MissionValues from './pages/MissionValues'; import BoardOfDirectors from './pages/BoardOfDirectors'; @@ -304,6 +305,7 @@ function App() { } /> } /> } /> + } /> {/* 404 - Catch all undefined routes */} diff --git a/src/components/SettingsSidebar.js b/src/components/SettingsSidebar.js index d08c781..39d1fff 100644 --- a/src/components/SettingsSidebar.js +++ b/src/components/SettingsSidebar.js @@ -1,12 +1,13 @@ import React from 'react'; import { NavLink, useLocation } from 'react-router-dom'; -import { CreditCard, Shield, Star, Palette } from 'lucide-react'; +import { CreditCard, Shield, Star, Palette, FileEdit } from 'lucide-react'; const settingsItems = [ { label: 'Stripe', path: '/admin/settings/stripe', icon: CreditCard }, { label: 'Permissions', path: '/admin/settings/permissions', icon: Shield }, { label: 'Member Tiers', path: '/admin/settings/member-tiers', icon: Star }, { label: 'Theme', path: '/admin/settings/theme', icon: Palette }, + { label: 'Registration Form', path: '/admin/settings/registration', icon: FileEdit }, ]; const SettingsTabs = () => { diff --git a/src/components/registration/DynamicFormField.js b/src/components/registration/DynamicFormField.js new file mode 100644 index 0000000..1f416d7 --- /dev/null +++ b/src/components/registration/DynamicFormField.js @@ -0,0 +1,411 @@ +import React from 'react'; +import { Label } from '../ui/label'; +import { Input } from '../ui/input'; +import { Textarea } from '../ui/textarea'; +import { Checkbox } from '../ui/checkbox'; +import { RadioGroup, RadioGroupItem } from '../ui/radio-group'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '../ui/select'; + +/** + * DynamicFormField - Renders form fields based on schema configuration + * + * Supports field types: + * - text, email, phone, password: Input fields + * - date: Date picker input + * - textarea: Multi-line text input + * - checkbox: Single checkbox + * - radio: Radio button group + * - dropdown: Select dropdown + * - multiselect: Checkbox group for multiple selections + * - address_group: Group of address-related fields + * - file_upload: File upload input + */ +const DynamicFormField = ({ + field, + value, + onChange, + errors = [], + formData = {}, +}) => { + const { + id, + type, + label, + required, + placeholder, + options = [], + rows = 4, + validation = {}, + } = field; + + const hasError = errors.length > 0; + const errorMessage = errors[0]; + + // Common input className + const inputClassName = `h-14 rounded-xl border-2 ${ + hasError + ? 'border-red-500 focus:border-red-500' + : 'border-[var(--neutral-800)] focus:border-brand-purple' + }`; + + // Handle change for different field types + const handleInputChange = (e) => { + const { value: newValue, type: inputType, checked } = e.target; + if (inputType === 'checkbox') { + onChange(id, checked); + } else { + onChange(id, newValue); + } + }; + + const handleSelectChange = (newValue) => { + onChange(id, newValue); + }; + + const handleCheckboxChange = (checked) => { + onChange(id, checked); + }; + + const handleMultiselectChange = (optionValue) => { + const currentValues = Array.isArray(value) ? value : []; + const newValues = currentValues.includes(optionValue) + ? currentValues.filter((v) => v !== optionValue) + : [...currentValues, optionValue]; + onChange(id, newValues); + }; + + // Render error message + const renderError = () => { + if (!hasError) return null; + return ( +

{errorMessage}

+ ); + }; + + // Render label + const renderLabel = () => ( + + ); + + // Render based on field type + switch (type) { + case 'text': + case 'email': + case 'phone': + return ( +
+ {renderLabel()} + + {renderError()} +
+ ); + + case 'password': + return ( +
+ {renderLabel()} + + {renderError()} +
+ ); + + case 'date': + return ( +
+ {renderLabel()} + + {renderError()} +
+ ); + + case 'textarea': + return ( +
+ {renderLabel()} +