mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 10:11:13 -05:00
Update remaining documentation files to remove references to the old approval flow and feature flags.
262 lines
7.1 KiB
Markdown
262 lines
7.1 KiB
Markdown
# 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
|