Frontend
Components
Forms and Form Components

Forms and Form Components

Overview

The application includes several form components for creating and editing entities like conferences, events, speakers, and quests. All forms follow consistent patterns for validation, error handling, and user feedback.

Form Components

ConferenceForm (src/components/ConferenceForm.tsx)

Form for creating and editing conferences.

Fields:

  • Basic info: name, slug, tagline, description
  • Dates: start date, end date, timezone
  • Location: city, country, venue name, address, coordinates
  • Virtual: is virtual, platform, URL
  • Organizer: name, logo, website, email, phone
  • Social: Twitter, LinkedIn, Instagram, Facebook, YouTube, Telegram, Discord
  • Registration: registration URL, ticket URL, pricing
  • Settings: status, featured, public, requires approval
  • Theme: theme color, secondary color
  • SEO: meta title, description, keywords, OG image

Features:

  • Image upload for logos and banners
  • Date picker for dates
  • Coordinate input for location
  • Rich text editor for description
  • Validation for required fields

EventForm (src/components/EventForm.tsx)

Form for creating and editing events.

Fields:

  • Basic: title, slug, subtitle, description
  • Timing: date, start time, end time, timezone, time description
  • Location: location name, address, coordinates, city
  • Media: image, stream URL, recording URL
  • Organizer: organizer name, logo
  • Links: calendar link, registration URL, ticket URL, event URL
  • Settings: status, format, capacity, featured, paid, category
  • Speakers: speaker selection (multi-select)
  • Tags: tag selection

Features:

  • Image upload
  • Speaker multi-select dropdown
  • Date and time pickers
  • Coordinate input
  • Validation

SpeakerForm (src/components/SpeakerForm.tsx)

Form for creating and editing speakers.

Fields:

  • Basic: first name, last name, email, phone, bio, title, organization
  • Media: photo URL
  • Links: website, LinkedIn, Twitter, GitHub, Instagram, Facebook, YouTube
  • Location: location, country, city
  • Details: languages, expertise, topics, experience, education, certifications
  • Availability: availability, travel willing, virtual willing, fee range
  • Settings: verified, active, featured

Features:

  • Image upload for photo
  • Multi-select for languages, expertise, topics
  • Rich text editor for bio
  • Validation

PushNotificationForm (src/components/PushNotificationForm.tsx)

Form for sending push notifications.

Fields:

  • Title
  • Body/Message
  • Target: all users or specific users
  • User IDs (if specific)
  • Topic (if using topics)
  • Image URL (optional)
  • Link (optional)

Features:

  • User selection
  • Preview functionality
  • Validation

Quest Forms

Quest forms are handled through the quest detail components:

  • Quest Description: Rich text editor
  • Quest Tasks: Dynamic task list with various task types
  • Quest Reward: Reward configuration
  • Quest Sponsor: Sponsor information

Form Patterns

Controlled Components

All forms use controlled components with React state:

const [formData, setFormData] = useState({
  title: "",
  description: "",
  // ... other fields
});
 
const handleChange = (field: string, value: any) => {
  setFormData(prev => ({
    ...prev,
    [field]: value
  }));
};

Form Validation

Forms use client-side validation:

const validate = () => {
  const errors: Record<string, string> = {};
  
  if (!formData.title) {
    errors.title = "Title is required";
  }
  
  if (!formData.date) {
    errors.date = "Date is required";
  }
  
  return errors;
};

Error Handling

Forms display errors and show toast notifications:

try {
  await apiClient.createEvent(formData);
  toast.success("Event created successfully!");
  onSuccess?.();
} catch (error) {
  toast.error("Failed to create event. Please try again.");
  console.error(error);
}

Loading States

Forms show loading states during submission:

const [loading, setLoading] = useState(false);
 
const handleSubmit = async (e: React.FormEvent) => {
  e.preventDefault();
  setLoading(true);
  
  try {
    // ... submit logic
  } finally {
    setLoading(false);
  }
};

Image Upload Component

ImageUpload (src/components/ImageUpload.tsx)

Reusable component for image uploads.

Features:

  • Drag and drop support
  • File selection via button
  • Image preview
  • Upload progress
  • Error handling
  • Image URL display

Usage:

<ImageUpload
  value={imageUrl}
  onChange={setImageUrl}
  onUpload={handleImageUpload}
  label="Upload Image"
/>

Props:

  • value: Current image URL
  • onChange: Callback when URL changes
  • onUpload: Upload handler function
  • label: Label text
  • accept: Accepted file types
  • maxSize: Maximum file size

Video Upload Component

VideoUpload (src/components/VideoUpload.tsx)

Component for video uploads.

Features:

  • File selection
  • Upload progress
  • Video preview
  • Error handling

Usage: Similar to ImageUpload component.

Form Best Practices

1. User Feedback

  • Show loading states during submission
  • Display success/error messages
  • Provide clear validation errors
  • Use toast notifications for feedback

2. Validation

  • Validate on submit
  • Show inline errors
  • Highlight invalid fields
  • Prevent submission if invalid

3. Accessibility

  • Use proper labels
  • Associate errors with fields
  • Support keyboard navigation
  • Provide ARIA attributes

4. Performance

  • Debounce search inputs
  • Lazy load large forms
  • Optimize image uploads
  • Minimize re-renders

5. Data Handling

  • Sanitize inputs
  • Validate data types
  • Handle edge cases
  • Provide default values

Common Form Patterns

Multi-Step Forms

For complex forms, use a stepper component:

<Stepper>
  <Step title="Basic Info" />
  <Step title="Details" />
  <Step title="Review" />
</Stepper>

Dynamic Fields

For forms with dynamic fields (like quest tasks):

const [tasks, setTasks] = useState<Task[]>([]);
 
const addTask = () => {
  setTasks([...tasks, { id: uuid(), ...defaultTask }]);
};
 
const removeTask = (id: string) => {
  setTasks(tasks.filter(t => t.id !== id));
};

Conditional Fields

Show/hide fields based on other field values:

{formData.is_virtual && (
  <div>
    <Label>Virtual Platform</Label>
    <Input {...register("virtual_platform")} />
  </div>
)}

Form Libraries

The application doesn't use a form library like React Hook Form or Formik, but implements custom form handling. Consider using a form library for:

  • Complex validation
  • Better performance
  • Less boilerplate
  • Better TypeScript support

Potential libraries:

  • React Hook Form
  • Formik
  • React Final Form