# Designers Listing Page Implementation Prompt ## Django Parity Reference **Django Implementation**: `designers/views.py` - `DesignerListView` (similar patterns to companies views) **Django Template**: `designers/templates/designers/designer_list.html` **Django Features**: Creative portfolio showcases, design specialization filtering, innovation timeline display, collaboration networks, award recognition system ## Core Implementation Requirements ### Laravel/Livewire Architecture Generate the designers listing system using ThrillWiki's custom generators: ```bash # Generate main designers listing with creative portfolio support php artisan make:thrillwiki-livewire DesignersListing --paginated --cached --with-tests # Generate creative specialization filters php artisan make:thrillwiki-livewire DesignersSpecializationFilter --reusable --with-tests # Generate portfolio showcase component php artisan make:thrillwiki-livewire DesignerPortfolioShowcase --reusable --with-tests # Generate innovation timeline component php artisan make:thrillwiki-livewire DesignerInnovationTimeline --reusable --cached # Generate collaboration network visualization php artisan make:thrillwiki-livewire DesignerCollaborationNetwork --reusable --with-tests # Generate awards and recognition display php artisan make:thrillwiki-livewire DesignerAwardsRecognition --reusable --cached # Generate design influence analysis php artisan make:thrillwiki-livewire DesignerInfluenceAnalysis --reusable --with-tests ``` ### Django Parity Features #### 1. Creative Portfolio Search Functionality **Django Implementation**: Multi-faceted search across: - Designer name (`name__icontains`) - Design specialization (`specialization__icontains`) - Notable innovations (`innovations__description__icontains`) - Career highlights (`career_highlights__icontains`) - Awards and recognition (`awards__title__icontains`) - Collaboration partners (`collaborations__partner__name__icontains`) **Laravel Implementation**: ```php public function creativePortfolioSearch($query, $specializations = []) { return Designer::query() ->when($query, function ($q) use ($query) { $terms = explode(' ', $query); foreach ($terms as $term) { $q->where(function ($subQuery) use ($term) { $subQuery->where('name', 'ilike', "%{$term}%") ->orWhere('bio', 'ilike', "%{$term}%") ->orWhere('design_philosophy', 'ilike', "%{$term}%") ->orWhere('career_highlights', 'ilike', "%{$term}%") ->orWhereHas('designed_rides', function($rideQuery) use ($term) { $rideQuery->where('name', 'ilike', "%{$term}%") ->orWhere('description', 'ilike', "%{$term}%"); }) ->orWhereHas('awards', function($awardQuery) use ($term) { $awardQuery->where('title', 'ilike', "%{$term}%") ->orWhere('description', 'ilike', "%{$term}%"); }) ->orWhereHas('innovations', function($innQuery) use ($term) { $innQuery->where('title', 'ilike', "%{$term}%") ->orWhere('description', 'ilike', "%{$term}%"); }); }); } }) ->when($specializations, function ($q) use ($specializations) { $q->where(function ($specQuery) use ($specializations) { foreach ($specializations as $spec) { $specQuery->orWhereJsonContains('specializations', $spec); } }); }) ->with([ 'designed_rides' => fn($q) => $q->with(['park', 'photos'])->limit(5), 'awards' => fn($q) => $q->orderBy('year', 'desc')->limit(3), 'innovations' => fn($q) => $q->orderBy('year', 'desc')->limit(3), 'collaborations' => fn($q) => $q->with('partner')->limit(5) ]) ->withCount(['designed_rides', 'awards', 'innovations', 'collaborations']); } ``` #### 2. Advanced Creative Filtering **Django Filters**: - Design specialization (coaster_designer, dark_ride_specialist, theming_expert) - Experience level (emerging, established, legendary) - Innovation era (classic, modern, contemporary, cutting_edge) - Career span (active_years range) - Award categories (technical, artistic, lifetime_achievement) - Collaboration type (solo_artist, team_player, cross_industry) - Geographic influence (regional, national, international) **Laravel Filters Implementation**: ```php public function applyCreativeFilters($query, $filters) { return $query ->when($filters['specializations'] ?? null, function ($q, $specializations) { $q->where(function ($specQuery) use ($specializations) { foreach ($specializations as $spec) { $specQuery->orWhereJsonContains('specializations', $spec); } }); }) ->when($filters['experience_level'] ?? null, function ($q, $level) { $experienceRanges = [ 'emerging' => [0, 5], 'established' => [6, 15], 'veteran' => [16, 25], 'legendary' => [26, PHP_INT_MAX] ]; if (isset($experienceRanges[$level])) { $q->whereRaw('EXTRACT(YEAR FROM NOW()) - career_start_year BETWEEN ? AND ?', $experienceRanges[$level]); } }) ->when($filters['innovation_era'] ?? null, function ($q, $era) { $eraRanges = [ 'classic' => [1950, 1979], 'modern' => [1980, 1999], 'contemporary' => [2000, 2009], 'cutting_edge' => [2010, date('Y')] ]; if (isset($eraRanges[$era])) { $q->whereHas('innovations', function ($innQuery) use ($eraRanges, $era) { $innQuery->whereBetween('year', $eraRanges[$era]); }); } }) ->when($filters['career_start_from'] ?? null, fn($q, $year) => $q->where('career_start_year', '>=', $year)) ->when($filters['career_start_to'] ?? null, fn($q, $year) => $q->where('career_start_year', '<=', $year)) ->when($filters['award_categories'] ?? null, function ($q, $categories) { $q->whereHas('awards', function ($awardQuery) use ($categories) { $awardQuery->whereIn('category', $categories); }); }) ->when($filters['collaboration_style'] ?? null, function ($q, $style) { switch ($style) { case 'solo_artist': $q->whereDoesntHave('collaborations'); break; case 'team_player': $q->whereHas('collaborations', fn($colQ) => $colQ->where('type', 'team')); break; case 'cross_industry': $q->whereHas('collaborations', fn($colQ) => $colQ->where('type', 'cross_industry')); break; } }) ->when($filters['geographic_influence'] ?? null, function ($q, $influence) { switch ($influence) { case 'regional': $q->whereHas('designed_rides', function ($rideQ) { $rideQ->whereHas('park.location', function ($locQ) { $locQ->havingRaw('COUNT(DISTINCT country) = 1'); }); }); break; case 'international': $q->whereHas('designed_rides', function ($rideQ) { $rideQ->whereHas('park.location', function ($locQ) { $locQ->havingRaw('COUNT(DISTINCT country) > 3'); }); }); break; } }); } ``` #### 3. Innovation Timeline and Portfolio Display **Creative Metrics**: - Notable ride designs and their impact - Innovation timeline with breakthrough moments - Awards and industry recognition - Collaboration network and partnerships - Design philosophy and artistic influence - Career milestones and achievements ### Screen-Agnostic Design Implementation #### Mobile Layout (320px - 767px) - **Designer Cards**: Artist-focused cards with signature designs - **Portfolio Highlights**: Visual showcase of most notable works - **Innovation Badges**: Visual indicators of breakthrough innovations - **Timeline Snapshots**: Condensed career timeline view **Mobile Component Structure**: ```blade
@foreach($designers as $designer) @endforeach
{{ $designers->links('pagination.mobile') }}
``` #### Tablet Layout (768px - 1023px) - **Portfolio Gallery**: Visual grid of signature designs - **Innovation Timeline**: Interactive career progression - **Collaboration Network**: Visual relationship mapping - **Awards Showcase**: Comprehensive recognition display **Tablet Component Structure**: ```blade

{{ $designers->total() }} Visionary Designers

@if($view === 'grid')
@foreach($designers as $designer) @endforeach
@elseif($view === 'timeline')
@foreach($designers as $designer) @endforeach
@else @endif
{{ $designers->links() }}
``` #### Desktop Layout (1024px - 1919px) - **Comprehensive Portfolio Views**: Detailed design showcases - **Interactive Innovation Timeline**: Full career progression with milestones - **Collaboration Network Visualization**: Complex relationship mapping - **Creative Influence Analysis**: Industry impact visualization **Desktop Component Structure**: ```blade

{{ $designers->total() }} Creative Visionaries

@if($view === 'portfolio')
@foreach($designers as $designer) @endforeach
{{ $designers->links('pagination.desktop') }}
@elseif($view === 'timeline')
@foreach($designers as $designer) @endforeach
@elseif($view === 'network')
@else
@endif
``` #### Large Screen Layout (1920px+) - **Creative Studio Interface**: Comprehensive design analysis - **Multi-Panel Innovation Views**: Simultaneous portfolio and timeline analysis - **Advanced Visualization**: Creative influence networks and innovation patterns - **Immersive Portfolio Experience**: Full-screen design showcases ### Performance Optimization Strategy #### Creative Portfolio Caching ```php public function mount() { $this->creativeStats = Cache::remember( 'designers.creative.stats', now()->addHours(8), fn() => $this->calculateCreativeStatistics() ); $this->innovationTrends = Cache::remember( 'designers.innovation.trends', now()->addHours(24), fn() => $this->loadInnovationTrends() ); } public function getDesignersProperty() { $cacheKey = "designers.listing." . md5(serialize([ 'search' => $this->search, 'filters' => $this->filters, 'specialization_filter' => $this->specializationFilter, 'sort' => $this->sort, 'page' => $this->page ])); return Cache::remember($cacheKey, now()->addMinutes(45), function() { return $this->creativePortfolioSearch($this->search, $this->specializationFilter) ->applyCreativeFilters($this->filters) ->orderBy($this->sort['column'], $this->sort['direction']) ->paginate(16); }); } ``` #### Portfolio Media Optimization ```php // Optimized query for portfolio and innovation data public function optimizedPortfolioQuery() { return Designer::select([ 'designers.*', DB::raw('COALESCE(rides_count.count, 0) as designed_rides_count'), DB::raw('COALESCE(awards_count.count, 0) as awards_count'), DB::raw('COALESCE(innovations_count.count, 0) as innovations_count'), DB::raw('CASE WHEN EXTRACT(YEAR FROM NOW()) - career_start_year > 25 THEN "legendary" WHEN EXTRACT(YEAR FROM NOW()) - career_start_year > 15 THEN "veteran" WHEN EXTRACT(YEAR FROM NOW()) - career_start_year > 5 THEN "established" ELSE "emerging" END as experience_level_category') ]) ->leftJoin(DB::raw('(SELECT designer_id, COUNT(*) as count FROM rides GROUP BY designer_id) as rides_count'), 'designers.id', '=', 'rides_count.designer_id') ->leftJoin(DB::raw('(SELECT designer_id, COUNT(*) as count FROM designer_awards GROUP BY designer_id) as awards_count'), 'designers.id', '=', 'awards_count.designer_id') ->leftJoin(DB::raw('(SELECT designer_id, COUNT(*) as count FROM designer_innovations GROUP BY designer_id) as innovations_count'), 'designers.id', '=', 'innovations_count.designer_id') ->with([ 'designed_rides:id,designer_id,name,ride_type,opening_date', 'awards:id,designer_id,title,year,category', 'innovations:id,designer_id,title,year,description', 'collaborations' => fn($q) => $q->with('partner:id,name,type') ]); } ``` ### Component Reuse Strategy #### Shared Components - **`DesignersSpecializationFilter`**: Multi-specialization filtering with visual indicators - **`DesignerPortfolioShowcase`**: Comprehensive portfolio display with media - **`DesignerInnovationTimeline`**: Interactive career progression visualization - **`DesignerCreativeMetrics`**: Portfolio statistics and creative impact metrics #### Context Variations - **`CoasterDesignersListing`**: Coaster designers with ride performance metrics - **`ThemingExpertsListing`**: Theming specialists with environmental design focus - **`DarkRideDesignersListing`**: Dark ride specialists with storytelling emphasis - **`EmergingDesignersListing`**: New talent showcase with potential indicators ### Testing Requirements #### Feature Tests ```php /** @test */ public function can_filter_designers_by_specialization() { $coasterDesigner = Designer::factory()->create([ 'name' => 'John Wardley', 'specializations' => ['coaster_designer', 'theming_expert'] ]); $coasterDesigner->designed_rides()->create(['name' => 'The Smiler', 'ride_type' => 'roller-coaster']); $darkRideDesigner = Designer::factory()->create([ 'name' => 'Tony Baxter', 'specializations' => ['dark_ride_specialist', 'imagineer'] ]); $darkRideDesigner->designed_rides()->create(['name' => 'Indiana Jones Adventure', 'ride_type' => 'dark-ride']); Livewire::test(DesignersListing::class) ->set('specializationFilter', ['coaster_designer']) ->assertSee($coasterDesigner->name) ->assertDontSee($darkRideDesigner->name); } /** @test */ public function calculates_experience_level_correctly() { $legendary = Designer::factory()->create(['career_start_year' => 1985]); $veteran = Designer::factory()->create(['career_start_year' => 2000]); $established = Designer::factory()->create(['career_start_year' => 2010]); $emerging = Designer::factory()->create(['career_start_year' => 2020]); $component = Livewire::test(DesignersListing::class); $designers = $component->get('designers'); $this->assertEquals('legendary', $designers->where('id', $legendary->id)->first()->experience_level_category); $this->assertEquals('veteran', $designers->where('id', $veteran->id)->first()->experience_level_category); } /** @test */ public function maintains_django_parity_performance_with_portfolio_data() { Designer::factory()->count(40)->create(); $start = microtime(true); Livewire::test(DesignersListing::class); $end = microtime(true); $this->assertLessThan(0.5, $end - $start); // < 500ms with portfolio data } ``` #### Creative Portfolio Tests ```php /** @test */ public function displays_portfolio_metrics_accurately() { $designer = Designer::factory()->create(); $designer->designed_rides()->createMany(8, ['name' => 'Test Ride']); $designer->awards()->createMany(3, ['title' => 'Test Award']); $designer->innovations()->createMany(2, ['title' => 'Test Innovation']); $component = Livewire::test(DesignersListing::class); $portfolioData = $component->get('designers')->first(); $this->assertEquals(8, $portfolioData->designed_rides_count); $this->assertEquals(3, $portfolioData->awards_count); $this->assertEquals(2, $portfolioData->innovations_count); } /** @test */ public function handles_collaboration_network_visualization() { $designer1 = Designer::factory()->create(['name' => 'Designer One']); $designer2 = Designer::factory()->create(['name' => 'Designer Two']); $designer1->collaborations()->create([ 'partner_id' => $designer2->id, 'type' => 'team', 'project_name' => 'Joint Project' ]); $component = Livewire::test(DesignersListing::class); $collaborationData = $component->get('designers')->first()->collaborations; $this->assertCount(1, $collaborationData); $this->assertEquals('Joint Project', $collaborationData->first()->project_name); } ``` ### Performance Targets #### Universal Performance Standards with Creative Content - **Initial Load**: < 500ms (including portfolio thumbnails) - **Portfolio Rendering**: < 300ms for 20 designers - **Innovation Timeline**: < 200ms for complex career data - **Collaboration Network**: < 1 second for network visualization - **Creative Statistics**: < 150ms (cached) #### Creative Content Caching Strategy - **Innovation Trends**: 24 hours (industry trends stable) - **Creative Statistics**: 8 hours (portfolio metrics change) - **Portfolio Thumbnails**: 48 hours (visual content stable) - **Designer Profiles**: 12 hours (career data relatively stable) ### Success Criteria Checklist #### Django Parity Verification - [ ] Creative portfolio search matches Django behavior exactly - [ ] Specialization filtering provides same results as Django - [ ] Innovation timeline displays identically to Django - [ ] Awards and recognition match Django structure - [ ] Collaboration networks visualize like Django implementation #### Screen-Agnostic Compliance - [ ] Mobile layout optimized for creative content consumption - [ ] Tablet layout provides effective portfolio browsing - [ ] Desktop layout maximizes creative visualization - [ ] Large screen layout provides immersive portfolio experience - [ ] All layouts handle rich media content gracefully #### Performance Benchmarks - [ ] Initial load under 500ms including portfolio media - [ ] Portfolio rendering under 300ms - [ ] Innovation timeline under 200ms - [ ] Creative statistics under 150ms (cached) - [ ] Portfolio caching reduces server load by 65% #### Creative Feature Completeness - [ ] Specialization filtering works across all design disciplines - [ ] Portfolio showcases provide comprehensive creative overviews - [ ] Innovation timelines visualize career progression accurately - [ ] Collaboration networks display meaningful relationships - [ ] Awards and recognition systems provide proper attribution This prompt ensures complete Django parity while providing comprehensive creative portfolio capabilities that showcase designer talent and innovation while maintaining ThrillWiki's screen-agnostic design principles.