# Submission Patterns & Guidelines

## Overview

This document outlines the patterns and best practices for working with submissions in the moderation queue system.

## Submission Types

### 1. Content Submissions (`content_submissions`)

**When to use:**
- Creating or updating parks, rides, companies, ride models
- Multi-item submissions with dependencies
- Submissions requiring moderator review before going live

**Data Flow:**
```
User Form → validateEntityData() → createSubmission() 
  → content_submissions table 
  → submission_items table (with dependencies)
  → Moderation Queue
  → Approval → process-selective-approval edge function (atomic transaction RPC)
  → Live entities created (all-or-nothing via PostgreSQL transaction)
```

**Example:**
```typescript
// Creating a park with operator dependency
const { success } = await createParkSubmission({
  name: "Cedar Point",
  park_type: "theme_park",
  operator_id: "new_operator_123", // References another item in same submission
});
```

### 2. Photo Submissions (`photo_submissions`)

**When to use:**
- User uploading photos to existing entities
- Photos require moderation but entity already exists

**Data Flow:**
```
UppyPhotoSubmissionUpload 
  → Cloudflare Direct Upload
  → photo_submissions + photo_submission_items tables
  → Moderation Queue
  → Approval → Photos linked to entity
```

**Key Requirements:**
- Must be linked to parent `content_submissions` for queue integration
- Caption and title sanitized (plain text only, no HTML)
- Maximum 10 photos per submission

### 3. Reviews (`reviews`)

**When to use:**
- User reviewing a park or ride
- Rating with optional text content

**Data Flow:**
```
ReviewForm 
  → reviews table + content_submissions (NEW)
  → Moderation Queue
  → Approval → Review goes live
```

**Sanitization:**
- All review content is plain text (HTML stripped)
- Maximum 5000 characters
- Rating validation (0.5-5.0 scale)

## When to Use Each Table

### Use `content_submissions` when:
✅ Creating new entities (parks, rides, companies)
✅ Updating existing entities
✅ Submissions have multi-item dependencies
✅ Need moderator review before data goes live

### Use Specialized Tables when:
✅ **Photos**: Entity exists, just adding media (`photo_submissions`)
✅ **Reviews**: User feedback on existing entity (`reviews` + `content_submissions`)
✅ **Technical Specs**: Belongs to specific entity (`ride_technical_specifications`)

## Validation Requirements

### All Submissions Must:
1. Pass Zod schema validation (`entityValidationSchemas.ts`)
2. Have proper slug generation (unique, URL-safe)
3. Include source URLs when applicable
4. Pass duplicate detection checks

### Entity-Specific Requirements:

**Parks:**
- Valid `park_type` enum
- Valid location data (country required)
- Opening date format validation

**Rides:**
- Must reference valid `park_id`
- Valid `ride_type` enum
- Opening date validation

**Companies:**
- Valid `company_type` enum
- Country code validation
- Founded year range check

## Dependency Resolution

### Dependency Types:
1. **Same-submission dependencies**: New park references new operator (both in queue)
2. **Existing entity dependencies**: New ride references existing park
3. **Multi-level dependencies**: Ride → Park → Operator → Owner (4 levels)

### Resolution Order:
Dependencies are resolved using topological sorting:
```
1. Load all items in submission
2. Build dependency graph
3. Sort topologically (parents before children)
4. Process in order
```

**Example:**
```
Submission contains:
- Item A: Operator (no dependencies)
- Item B: Park (depends on A)
- Item C: Ride (depends on B)

Processing order: A → B → C
```

## Best Practices

### DO:
✅ Use existing entities when possible (avoid duplicates)
✅ Provide source URLs for verifiability
✅ Write clear submission notes for moderators
✅ Validate data on client-side before submission
✅ Use type guards when working with `SubmissionItemData`

### DON'T:
❌ Store JSON blobs in SQL columns
❌ Skip validation to "speed up" submissions
❌ Create dependencies to non-existent entities
❌ Submit without source verification
❌ Bypass moderation queue (security risk)

## Adding New Submission Types

### Steps:
1. Create type definition in `src/types/moderation.ts`
2. Add type guard to `src/lib/moderation/typeGuards.ts`
3. Create validation schema in `src/lib/entityValidationSchemas.ts`
4. Add submission helper in `src/lib/entitySubmissionHelpers.ts`
5. Update `useModerationQueueManager` query to fetch new type
6. Create renderer component (optional, for complex UI)
7. Add tests for new type

### Example: Adding "Event" Submission Type

```typescript
// 1. Type definition (moderation.ts)
export interface EventItemData {
  event_id?: string;
  name: string;
  park_id: string;
  start_date: string;
  end_date: string;
}

export type SubmissionItemData = 
  | ParkItemData 
  | RideItemData
  | EventItemData; // Add here

// 2. Type guard (typeGuards.ts)
export function isEventItemData(data: SubmissionItemData): data is EventItemData {
  return 'start_date' in data && 'end_date' in data;
}

// 3. Validation (entityValidationSchemas.ts)
const eventSchema = z.object({
  name: z.string().min(1).max(200),
  park_id: z.string().uuid(),
  start_date: z.string().datetime(),
  end_date: z.string().datetime(),
});

// 4. Submission helper (entitySubmissionHelpers.ts)
export async function createEventSubmission(eventData: EventFormData) {
  // Validation, submission creation logic
}

// 5. Update queue query to include events
// (already handles all content_submissions)

// 6. Optional: Create EventSubmissionDisplay component
// 7. Add tests
```

## Migration Checklist

When migrating legacy code to this pattern:
- [ ] Remove direct database writes (use submission helpers)
- [ ] Add validation schemas
- [ ] Update to use `SubmissionItemData` types
- [ ] Add type guards where needed
- [ ] Test dependency resolution
- [ ] Verify sanitization is applied
- [ ] Update documentation

## Security Considerations

### Input Validation:
- **Server-side validation** is mandatory (Zod schemas)
- **Client-side validation** for UX only
- **Never trust user input** - always validate and sanitize

### Sanitization:
- HTML stripped from user text (use `rehype-sanitize`)
- URLs validated and optionally stripped
- File uploads validated (type, size, count)
- SQL injection prevented (Supabase parameterized queries)

### Access Control:
- Only moderators can approve/reject
- Users can only submit, not self-approve
- RLS policies enforce row-level security
- Lock system prevents concurrent modifications

## Troubleshooting

### Common Issues:

**"Dependency not found"**
→ Check if parent entity exists in database or in same submission

**"Validation failed"**
→ Check Zod schema, ensure all required fields present

**"Duplicate slug"**
→ Slug generation collided, system will auto-increment

**"Lock expired"**
→ Moderator must re-claim submission to continue

**"Permission denied"**
→ Check user role (must be moderator/admin)

## References

- See `ARCHITECTURE.md` for system design
- See `COMPONENTS.md` for UI component usage
- See `../IMPLEMENTATION_COMPLETE.md` for recent changes
