- Added rides index view with search and filter options. - Created rides show view to display ride details. - Implemented API routes for rides. - Developed authentication routes for user registration, login, and email verification. - Created tests for authentication, email verification, password reset, and user profile management. - Added feature tests for rides and operators, including creation, updating, deletion, and searching. - Implemented soft deletes and caching for rides and operators. - Enhanced manufacturer and operator model tests for various functionalities.
10 KiB
ThrillWiki System Patterns
Documentation of architectural patterns, design decisions, and development strategies
Last Updated: June 13, 2025 9:02 PM EST
🏗️ Architectural Patterns
Model Design Pattern
Pattern: Smart Model with Trait Integration
Purpose: Consistent model behavior across entities with automatic trait assignment
// Base pattern for ThrillWiki models
class Entity extends Model
{
use HasFactory, SoftDeletes;
use HasSlugHistory; // For main entities (Park, Ride, Operator, Designer)
use HasLocation; // For location-based entities (Park, Operator, ParkArea)
use HasStatistics; // For statistical entities (Park, Ride, User)
use HasCaching; // For performance-critical entities
}
Implementation: Automated through custom generators with intelligent trait selection
Relationship Management Pattern
Pattern: Consistent Entity Relationships
Purpose: Standardized relationship structure across the application
// Core ThrillWiki relationship patterns
Park: areas (hasMany), rides (hasMany), operator (belongsTo)
Ride: park (belongsTo), designer (belongsTo), manufacturer (belongsTo Manufacturer)
Operator: parks (hasMany)
Manufacturer: rides (hasMany)
Designer: rides (hasMany)
Review: user (belongsTo), reviewable (morphTo)
API Resource Pattern
Pattern: Consistent API Response Structure
Purpose: Uniform API responses with performance optimization
// Standard API resource structure
class EntityResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
// Conditional relationships
'relationships' => $this->whenLoaded('relationship'),
];
}
}
🚀 Development Acceleration Patterns
Custom Generator Pattern
Pattern: Template-Based Code Generation
Purpose: 98-99% faster development through automated scaffolding
Components:
- Model Generator: Smart trait integration, relationship management
- CRUD Generator: Complete CRUD with views, controllers, routes
- Livewire Generator: Dynamic components with performance optimization
Usage Example:
# Generate complete entity in seconds
php artisan make:thrillwiki-model Designer --migration --factory --with-relationships --cached --api-resource --with-tests
php artisan make:thrillwiki-crud Designer --api --with-tests
Performance Optimization Pattern
Pattern: Built-in Performance by Default
Purpose: Automatic optimization without manual configuration
Strategies:
- Query Optimization: Eager loading, query scopes
- Caching Integration: Model caching, view caching
- Database Indexing: Automatic index creation in migrations
- Pagination: Built-in pagination for list views
Testing Integration Pattern
Pattern: Comprehensive Test Generation
Purpose: Quality assurance through automated test creation
// Auto-generated test structure
class EntityTest extends TestCase
{
public function test_can_create_entity()
public function test_can_read_entity()
public function test_can_update_entity()
public function test_can_delete_entity()
public function test_relationships_work()
}
🎨 UI/UX Patterns
Tailwind CSS Pattern
Pattern: Consistent Design System
Purpose: Uniform styling with dark mode support
<!-- Standard component structure -->
<div class="bg-white dark:bg-gray-800 shadow rounded-lg p-6">
<h2 class="text-lg font-medium text-gray-900 dark:text-white">
Entity Name
</h2>
<div class="mt-4 space-y-4">
<!-- Content -->
</div>
</div>
Livewire Component Pattern
Pattern: Reactive Component Architecture
Purpose: Dynamic UI with minimal JavaScript
// Standard Livewire component structure
class EntityComponent extends Component
{
public $entity;
public $filters = [];
protected $queryString = ['filters'];
public function render()
{
return view('livewire.entity-component', [
'entities' => $this->getEntitiesProperty()
]);
}
public function getEntitiesProperty()
{
return Entity::query()
->when($this->filters, fn($q) => $this->applyFilters($q))
->paginate(15);
}
}
Form Validation Pattern
Pattern: Consistent Form Request Validation
Purpose: Standardized validation with clear error messages
// Standard form request structure
class EntityRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'slug' => 'required|string|unique:entities,slug,' . $this->route('entity')?->id,
'description' => 'nullable|string',
];
}
public function messages(): array
{
return [
'name.required' => 'The entity name is required.',
'slug.unique' => 'This slug is already taken.',
];
}
}
🔧 Database Patterns
Migration Pattern
Pattern: Structured Database Changes
Purpose: Consistent database schema evolution
// Standard migration structure
class CreateEntityTable extends Migration
{
public function up()
{
Schema::create('entities', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->text('description')->nullable();
// Standard foreign keys
$table->foreignId('user_id')->constrained()->onDelete('cascade');
// Standard fields
$table->timestamps();
$table->softDeletes();
// Indexes
$table->index(['name', 'created_at']);
});
}
}
Seeder Pattern
Pattern: Consistent Data Seeding
Purpose: Reliable test data and initial setup
// Standard seeder structure
class EntitySeeder extends Seeder
{
public function run()
{
// Create test entities
Entity::factory(10)->create();
// Create specific entities for testing
Entity::create([
'name' => 'Test Entity',
'slug' => 'test-entity',
'description' => 'Entity for testing purposes',
]);
}
}
🔐 Security Patterns
Authorization Pattern
Pattern: Policy-Based Authorization
Purpose: Granular permission control
// Standard policy structure
class EntityPolicy
{
public function viewAny(User $user): bool
{
return $user->hasPermission('view_entities');
}
public function view(User $user, Entity $entity): bool
{
return $user->hasPermission('view_entity') || $user->id === $entity->user_id;
}
public function create(User $user): bool
{
return $user->hasPermission('create_entity');
}
}
Permission Pattern
Pattern: Role-Based Permission System
Purpose: Flexible access control
// Permission seeding pattern
$permissions = [
'view_entities',
'create_entity',
'edit_entity',
'delete_entity',
];
foreach ($permissions as $permission) {
Permission::create(['name' => $permission]);
}
📱 Responsive Design Patterns
Mobile-First Pattern
Pattern: Progressive Enhancement
Purpose: Optimal experience across devices
<!-- Mobile-first responsive design -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="p-4 bg-white rounded-lg shadow">
<!-- Mobile-optimized content -->
</div>
</div>
Navigation Pattern
Pattern: Consistent Navigation Structure
Purpose: Intuitive user experience
<!-- Standard navigation pattern -->
<nav class="bg-white dark:bg-gray-800 shadow">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Navigation content -->
</div>
</nav>
🧪 Testing Patterns
Feature Test Pattern
Pattern: Comprehensive Feature Testing
Purpose: End-to-end functionality verification
// Standard feature test structure
class EntityFeatureTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_create_entity()
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/entities', [
'name' => 'Test Entity',
'description' => 'Test description',
]);
$response->assertRedirect();
$this->assertDatabaseHas('entities', ['name' => 'Test Entity']);
}
}
Unit Test Pattern
Pattern: Model and Service Testing
Purpose: Isolated component verification
// Standard unit test structure
class EntityTest extends TestCase
{
public function test_entity_has_slug_attribute()
{
$entity = Entity::factory()->make(['name' => 'Test Entity']);
$this->assertEquals('test-entity', $entity->slug);
}
}
🔄 Django Parity Patterns
Field Mapping Pattern
Pattern: Django-to-Laravel Field Equivalence
Purpose: Maintain data structure consistency
// Django field mapping
'CharField' => 'string',
'TextField' => 'text',
'IntegerField' => 'integer',
'BooleanField' => 'boolean',
'DateTimeField' => 'timestamp',
'ForeignKey' => 'foreignId',
Relationship Mapping Pattern
Pattern: Django-to-Laravel Relationship Equivalence
Purpose: Preserve relationship logic
// Django relationship mapping
'ForeignKey' => 'belongsTo',
'OneToOneField' => 'hasOne',
'ManyToManyField' => 'belongsToMany',
'GenericForeignKey' => 'morphTo',
Maintained by: Roo Architect Mode
Purpose: System pattern documentation and architectural guidance
Usage: Reference for consistent development practices across ThrillWiki