Files
picpeak/docs/feature-optional-event-fields.md
T
Paul Nothaft e0204aeeee Add planning document for optional event contact fields
Addresses GitHub issue #60 - making customer name, customer email,
and admin email fields optional when creating events.

This feature adds three new admin settings:
- event_require_customer_name (default: true)
- event_require_customer_email (default: true)
- event_require_admin_email (default: true)

Implementation includes:
- Database migration for new app_settings entries
- Backend conditional validation in event creation
- Frontend settings UI with toggle switches
- Dynamic form validation based on settings
- Warning messages for email-related settings
- Graceful handling of empty contact fields

Maintains backward compatibility with default behavior unchanged.
2026-01-01 23:52:07 +01:00

18 KiB

Feature: Optional Event Contact Fields

Overview

This feature adds a settings option to configure whether client/customer contact information (name, email) and admin email are required fields when creating new events. This addresses the needs of users who don't use the email/SMTP functionality and find these mandatory fields unnecessary.

GitHub Issue: #60


Problem Statement

Currently, when creating a new event, the following fields are mandatory:

  • Customer Name
  • Customer Email
  • Admin Email

For users who:

  • Don't use SMTP/email functionality
  • Share galleries via manual link distribution
  • Self-host for personal use without client management

These required fields create unnecessary friction and force users to enter placeholder data.


User Story

As an administrator, I want to configure whether client contact information is required when creating events, so that I can streamline event creation when I don't need email functionality.


Feature Requirements

1. New Settings Options

Add three new settings to the Admin Settings page under a new section "Event Creation":

Setting Label Type Default Description
event_require_customer_name Require customer name Toggle true When enabled, customer name is required for new events
event_require_customer_email Require customer email Toggle true When enabled, customer email is required for new events
event_require_admin_email Require admin email Toggle true When enabled, admin email is required for new events

2. Settings UI Location

Path: Admin Panel → Settings → Event Creation (new section)

┌─────────────────────────────────────────────────────────────┐
│ Settings                                                     │
├─────────────────────────────────────────────────────────────┤
│ ▼ General                                                    │
│ ▼ Gallery Display                                            │
│ ▼ Storage                                                    │
│ ▼ Event Creation                        ← NEW SECTION        │
│   ┌─────────────────────────────────────────────────────┐   │
│   │ Required Fields                                      │   │
│   │                                                      │   │
│   │ Configure which contact fields are required when    │   │
│   │ creating new events.                                │   │
│   │                                                      │   │
│   │ [✓] Require customer name                           │   │
│   │     Customer name must be provided for new events   │   │
│   │                                                      │   │
│   │ [✓] Require customer email                          │   │
│   │     Customer email must be provided for new events  │   │
│   │     ⚠️ Required for sending gallery invitations     │   │
│   │                                                      │   │
│   │ [✓] Require admin email                             │   │
│   │     Admin email must be provided for new events     │   │
│   │     ⚠️ Required for receiving event notifications   │   │
│   └─────────────────────────────────────────────────────┘   │
│ ▼ Security                                                   │
│ ▼ Email/SMTP                                                 │
└─────────────────────────────────────────────────────────────┘

3. Event Creation Form Updates

The event creation form (/admin/events/new) should:

  1. Fetch settings on load to determine field requirements
  2. Conditionally apply validation based on settings
  3. Update field labels to show optional indicator when not required
  4. Remove asterisk (*) from non-required fields

Field Display Logic

Setting Value Field Label Validation Placeholder
true (required) "Customer Name *" Required "Enter customer name"
false (optional) "Customer Name (optional)" Optional "Enter customer name (optional)"

4. Warning Messages

When disabling email-related required fields, show informational warnings:

When disabling "Require customer email":

Note: Without a customer email, you won't be able to send gallery invitation emails automatically. You'll need to share gallery links manually.

When disabling "Require admin email":

Note: Without an admin email, you won't receive event notifications such as expiration reminders or guest feedback alerts.

5. Backward Compatibility

  • Existing events with empty contact fields remain valid
  • Default values maintain current behavior (true = required)
  • Settings changes only affect new event creation

Technical Specification

6. Database Changes

6.1 Settings Table Entries

Add new rows to app_settings table:

INSERT INTO app_settings (key, value, category, description) VALUES
('event_require_customer_name', 'true', 'events', 'Require customer name when creating events'),
('event_require_customer_email', 'true', 'events', 'Require customer email when creating events'),
('event_require_admin_email', 'true', 'events', 'Require admin email when creating events');

6.2 Migration File

File: /backend/migrations/core/YYYYMMDDHHMMSS_add_optional_event_fields_settings.js

exports.up = function(knex) {
  return knex('app_settings').insert([
    {
      key: 'event_require_customer_name',
      value: 'true',
      category: 'events',
      description: 'Require customer name when creating events'
    },
    {
      key: 'event_require_customer_email',
      value: 'true',
      category: 'events',
      description: 'Require customer email when creating events'
    },
    {
      key: 'event_require_admin_email',
      value: 'true',
      category: 'events',
      description: 'Require admin email when creating events'
    }
  ]);
};

exports.down = function(knex) {
  return knex('app_settings')
    .whereIn('key', [
      'event_require_customer_name',
      'event_require_customer_email',
      'event_require_admin_email'
    ])
    .del();
};

7. API Changes

7.1 Settings Endpoint (Existing)

The existing settings endpoints should already handle these new settings:

GET /api/admin/settings - Returns all settings including new ones PUT /api/admin/settings - Updates settings including new ones

7.2 Public Settings Endpoint

GET /api/public/settings - Should include event field requirements for frontend validation

Add to public settings response:

{
  "event_require_customer_name": true,
  "event_require_customer_email": true,
  "event_require_admin_email": true
}

7.3 Event Creation Validation Update

File: /backend/src/routes/adminEvents.js

Update the event creation endpoint to conditionally validate fields:

// Before (current)
if (!customer_name) {
  return res.status(400).json({ error: 'Customer name is required' });
}

// After (with settings check)
const settings = await getSettings();
if (settings.event_require_customer_name && !customer_name) {
  return res.status(400).json({ error: 'Customer name is required' });
}

8. Backend Implementation

8.1 Update Event Validation

File: /backend/src/routes/adminEvents.js

// POST /api/admin/events
router.post('/', adminAuth, async (req, res) => {
  try {
    const {
      event_name,
      event_type,
      event_date,
      customer_name,
      customer_email,
      admin_email,
      // ... other fields
    } = req.body;

    // Get settings for validation
    const settings = await db('app_settings')
      .whereIn('key', [
        'event_require_customer_name',
        'event_require_customer_email',
        'event_require_admin_email'
      ])
      .select('key', 'value');

    const settingsMap = settings.reduce((acc, s) => {
      acc[s.key] = s.value === 'true';
      return acc;
    }, {});

    // Conditional validation
    const errors = [];

    if (!event_name) {
      errors.push('Event name is required');
    }

    if (settingsMap.event_require_customer_name && !customer_name) {
      errors.push('Customer name is required');
    }

    if (settingsMap.event_require_customer_email && !customer_email) {
      errors.push('Customer email is required');
    }

    if (settingsMap.event_require_admin_email && !admin_email) {
      errors.push('Admin email is required');
    }

    if (errors.length > 0) {
      return res.status(400).json({ errors });
    }

    // Continue with event creation...
  } catch (error) {
    // Error handling...
  }
});

8.2 Add Settings to Public Endpoint

File: /backend/src/routes/publicSettings.js

// Add to public settings response
const eventFieldSettings = await db('app_settings')
  .whereIn('key', [
    'event_require_customer_name',
    'event_require_customer_email',
    'event_require_admin_email'
  ])
  .select('key', 'value');

// Include in response
response.eventFieldRequirements = eventFieldSettings.reduce((acc, s) => {
  acc[s.key] = s.value === 'true';
  return acc;
}, {});

9. Frontend Implementation

9.1 Settings Page Update

File: /frontend/src/components/admin/Settings.tsx (or similar)

Add new section for Event Creation settings:

// New section component
const EventCreationSettings: React.FC = () => {
  const { settings, updateSetting } = useSettings();

  return (
    <SettingsSection title="Event Creation" icon={<CalendarIcon />}>
      <SettingsGroup title="Required Fields">
        <p className="text-sm text-gray-500 mb-4">
          Configure which contact fields are required when creating new events.
        </p>

        <ToggleSetting
          label="Require customer name"
          description="Customer name must be provided for new events"
          checked={settings.event_require_customer_name}
          onChange={(value) => updateSetting('event_require_customer_name', value)}
        />

        <ToggleSetting
          label="Require customer email"
          description="Customer email must be provided for new events"
          checked={settings.event_require_customer_email}
          onChange={(value) => updateSetting('event_require_customer_email', value)}
          warning="Required for sending gallery invitations"
        />

        <ToggleSetting
          label="Require admin email"
          description="Admin email must be provided for new events"
          checked={settings.event_require_admin_email}
          onChange={(value) => updateSetting('event_require_admin_email', value)}
          warning="Required for receiving event notifications"
        />
      </SettingsGroup>
    </SettingsSection>
  );
};

9.2 Event Creation Form Update

File: /frontend/src/components/admin/EventForm.tsx (or similar)

interface EventFormProps {
  // ... existing props
}

const EventForm: React.FC<EventFormProps> = () => {
  const { settings } = usePublicSettings();

  const isCustomerNameRequired = settings?.event_require_customer_name ?? true;
  const isCustomerEmailRequired = settings?.event_require_customer_email ?? true;
  const isAdminEmailRequired = settings?.event_require_admin_email ?? true;

  // Form validation schema (using Zod or Yup)
  const validationSchema = useMemo(() => {
    return z.object({
      event_name: z.string().min(1, 'Event name is required'),
      customer_name: isCustomerNameRequired
        ? z.string().min(1, 'Customer name is required')
        : z.string().optional(),
      customer_email: isCustomerEmailRequired
        ? z.string().email('Valid email required')
        : z.string().email().optional().or(z.literal('')),
      admin_email: isAdminEmailRequired
        ? z.string().email('Valid email required')
        : z.string().email().optional().or(z.literal('')),
      // ... other fields
    });
  }, [isCustomerNameRequired, isCustomerEmailRequired, isAdminEmailRequired]);

  return (
    <form>
      {/* Customer Name Field */}
      <FormField
        label={isCustomerNameRequired ? 'Customer Name' : 'Customer Name (optional)'}
        required={isCustomerNameRequired}
      >
        <Input
          name="customer_name"
          placeholder={isCustomerNameRequired
            ? 'Enter customer name'
            : 'Enter customer name (optional)'
          }
        />
      </FormField>

      {/* Customer Email Field */}
      <FormField
        label={isCustomerEmailRequired ? 'Customer Email' : 'Customer Email (optional)'}
        required={isCustomerEmailRequired}
      >
        <Input
          name="customer_email"
          type="email"
          placeholder={isCustomerEmailRequired
            ? 'Enter customer email'
            : 'Enter customer email (optional)'
          }
        />
      </FormField>

      {/* Admin Email Field */}
      <FormField
        label={isAdminEmailRequired ? 'Admin Email' : 'Admin Email (optional)'}
        required={isAdminEmailRequired}
      >
        <Input
          name="admin_email"
          type="email"
          placeholder={isAdminEmailRequired
            ? 'Enter admin email'
            : 'Enter admin email (optional)'
          }
        />
      </FormField>

      {/* ... rest of form */}
    </form>
  );
};

9.3 Update Types

File: /frontend/src/types/settings.ts

interface PublicSettings {
  // ... existing settings
  event_require_customer_name: boolean;
  event_require_customer_email: boolean;
  event_require_admin_email: boolean;
}

10. Email Functionality Impact

When contact fields are optional and left empty:

Field Empty Impact
Customer Email Cannot send invitation email, "Send Email" button disabled
Admin Email No notifications sent, warning shown in event details
Customer Name Email salutation uses generic greeting

10.1 UI Adjustments for Empty Fields

Event Details Page:

  • If no customer email: Hide/disable "Send Invitation Email" button
  • If no admin email: Show info message "No admin email configured for notifications"

Event Creation Success:

  • If customer email provided: "Event created. Send invitation email?"
  • If no customer email: "Event created. Share the gallery link manually."

Implementation Checklist

Phase 1: Backend

  • Create database migration for new settings
  • Run migration to add default settings
  • Update event creation endpoint with conditional validation
  • Add new settings to public settings endpoint
  • Update event update endpoint with same validation logic
  • Write unit tests for conditional validation

Phase 2: Frontend - Settings

  • Add "Event Creation" section to Settings page
  • Create toggle components for each setting
  • Add warning messages for email-related settings
  • Test settings save/load functionality

Phase 3: Frontend - Event Form

  • Update EventForm to fetch settings
  • Implement conditional validation schema
  • Update field labels based on requirements
  • Update placeholder text
  • Test form validation with various settings combinations

Phase 4: UI Polish

  • Update event details page for empty contact fields
  • Disable email buttons when no email provided
  • Add informational messages where appropriate
  • Update any tooltips or help text

Phase 5: Testing

  • Test with all settings enabled (default behavior)
  • Test with all settings disabled
  • Test with mixed settings
  • Test event editing with changed settings
  • End-to-end testing

Test Scenarios

# Settings Action Expected Result
1 All required (default) Create event without customer name Validation error
2 All required Create event with all fields Success
3 Name optional Create event without customer name Success
4 Email optional Create event without customer email Success, email button disabled
5 All optional Create event with only event name/date Success
6 Mixed Edit settings, create event Respects new settings

Acceptance Criteria

  1. Three new toggle settings available in Admin Settings
  2. Settings persist after save and page refresh
  3. Event creation form respects settings for field requirements
  4. Field labels update to show "(optional)" when not required
  5. Backend validates according to settings
  6. Warning messages shown when disabling email-related fields
  7. Email functionality gracefully handles empty contact fields
  8. Default behavior unchanged (all fields required)
  9. Existing events unaffected by settings changes

Security Considerations

  1. Settings changes require admin authentication
  2. Public settings endpoint only exposes necessary field requirements
  3. No sensitive data exposed through settings

Backend

  • /backend/src/routes/adminEvents.js - Event creation/update
  • /backend/src/routes/adminSettings.js - Settings management
  • /backend/src/routes/publicSettings.js - Public settings API
  • /backend/migrations/core/ - Database migrations

Frontend

  • /frontend/src/components/admin/Settings.tsx - Settings page
  • /frontend/src/components/admin/EventForm.tsx - Event creation form
  • /frontend/src/components/admin/EventDetails.tsx - Event detail page
  • /frontend/src/services/settingsService.ts - Settings API service
  • /frontend/src/hooks/useSettings.ts - Settings hook

Future Enhancements

  1. Field-level defaults: Set default values for optional fields
  2. Conditional fields: Show/hide fields based on other selections
  3. Custom required fields: Allow adding custom required fields
  4. Per-event-type settings: Different requirements for wedding vs corporate