mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-22 19:51:09 -05:00
Add comprehensive implementation prompts for Reviews and Rides listing pages with Django parity, Laravel/Livewire architecture, and screen-agnostic design principles
This commit is contained in:
624
memory-bank/prompts/DesignersListingPagePrompt.md
Normal file
624
memory-bank/prompts/DesignersListingPagePrompt.md
Normal file
@@ -0,0 +1,624 @@
|
||||
# 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
|
||||
<div class="designers-mobile-layout">
|
||||
<!-- Creative Search Bar -->
|
||||
<div class="sticky top-0 bg-white dark:bg-gray-900 z-20 p-4">
|
||||
<livewire:designers-creative-search />
|
||||
<div class="flex items-center mt-2 space-x-2">
|
||||
<button wire:click="filterBySpecialization('coaster_designer')"
|
||||
class="flex items-center space-x-1 px-3 py-1 {{ $activeSpec === 'coaster_designer' ? 'bg-red-500 text-white' : 'bg-red-100 dark:bg-red-900' }} rounded-full">
|
||||
<span class="text-sm">Coasters</span>
|
||||
</button>
|
||||
<button wire:click="filterBySpecialization('dark_ride_specialist')"
|
||||
class="flex items-center space-x-1 px-3 py-1 {{ $activeSpec === 'dark_ride_specialist' ? 'bg-purple-500 text-white' : 'bg-purple-100 dark:bg-purple-900' }} rounded-full">
|
||||
<span class="text-sm">Dark Rides</span>
|
||||
</button>
|
||||
<button wire:click="filterBySpecialization('theming_expert')"
|
||||
class="flex items-center space-x-1 px-3 py-1 {{ $activeSpec === 'theming_expert' ? 'bg-green-500 text-white' : 'bg-green-100 dark:bg-green-900' }} rounded-full">
|
||||
<span class="text-sm">Theming</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Creative Inspiration Banner -->
|
||||
<div class="bg-gradient-to-r from-purple-500 via-pink-500 to-red-500 text-white p-4 m-4 rounded-lg">
|
||||
<livewire:designers-inspiration-stats :compact="true" />
|
||||
</div>
|
||||
|
||||
<!-- Quick Filters -->
|
||||
<div class="horizontal-scroll p-4 pb-2">
|
||||
<livewire:designers-quick-filters />
|
||||
</div>
|
||||
|
||||
<!-- Designer Cards -->
|
||||
<div class="space-y-4 p-4">
|
||||
@foreach($designers as $designer)
|
||||
<livewire:designer-mobile-card :designer="$designer" :show-portfolio="true" :key="$designer->id" />
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Mobile Pagination -->
|
||||
<div class="sticky bottom-0 bg-white dark:bg-gray-900 p-4">
|
||||
{{ $designers->links('pagination.mobile') }}
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 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
|
||||
<div class="designers-tablet-layout flex h-screen">
|
||||
<!-- Creative Filter Sidebar -->
|
||||
<div class="w-80 bg-gray-50 dark:bg-gray-800 overflow-y-auto">
|
||||
<div class="p-6">
|
||||
<livewire:designers-creative-search :advanced="true" />
|
||||
<div class="mt-6">
|
||||
<livewire:designers-specialization-filter :expanded="true" />
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<livewire:designers-creative-filters :show-awards="true" />
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<livewire:designers-inspiration-stats :detailed="true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<div class="flex-1 flex flex-col">
|
||||
<!-- Creative Header -->
|
||||
<div class="bg-white dark:bg-gray-900 p-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-4">
|
||||
<h2 class="text-xl font-semibold">{{ $designers->total() }} Visionary Designers</h2>
|
||||
<livewire:designers-industry-overview />
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<livewire:designers-sort-selector />
|
||||
<livewire:designers-view-toggle />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content Display -->
|
||||
<div class="flex-1 overflow-y-auto p-6">
|
||||
@if($view === 'grid')
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
@foreach($designers as $designer)
|
||||
<livewire:designer-tablet-card :designer="$designer" :portfolio="true" :key="$designer->id" />
|
||||
@endforeach
|
||||
</div>
|
||||
@elseif($view === 'timeline')
|
||||
<div class="space-y-8">
|
||||
@foreach($designers as $designer)
|
||||
<livewire:designer-timeline-showcase :designer="$designer" :key="$designer->id" />
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<livewire:designers-innovation-analysis :designers="$designers" />
|
||||
@endif
|
||||
|
||||
<div class="mt-6">
|
||||
{{ $designers->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 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
|
||||
<div class="designers-desktop-layout flex h-screen">
|
||||
<!-- Advanced Creative Filters -->
|
||||
<div class="w-80 bg-gray-50 dark:bg-gray-800 overflow-y-auto">
|
||||
<div class="p-6">
|
||||
<livewire:designers-creative-search :advanced="true" :autocomplete="true" />
|
||||
<div class="mt-6">
|
||||
<livewire:designers-specialization-filter :advanced="true" :show-statistics="true" />
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<livewire:designers-creative-filters :advanced="true" :show-awards="true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="flex-1 flex flex-col">
|
||||
<!-- Creative Dashboard Header -->
|
||||
<div class="bg-white dark:bg-gray-900 p-6 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div class="flex items-center space-x-6">
|
||||
<h1 class="text-2xl font-bold">{{ $designers->total() }} Creative Visionaries</h1>
|
||||
<livewire:designers-creative-summary />
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<livewire:designers-sort-selector :advanced="true" />
|
||||
<livewire:designers-view-selector />
|
||||
<livewire:designers-export-options />
|
||||
</div>
|
||||
</div>
|
||||
<livewire:designers-advanced-search />
|
||||
</div>
|
||||
|
||||
<!-- Content Area -->
|
||||
<div class="flex-1 overflow-y-auto">
|
||||
@if($view === 'portfolio')
|
||||
<div class="p-6">
|
||||
<div class="grid grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
@foreach($designers as $designer)
|
||||
<livewire:designer-desktop-card :designer="$designer" :comprehensive="true" :key="$designer->id" />
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="mt-8">
|
||||
{{ $designers->links('pagination.desktop') }}
|
||||
</div>
|
||||
</div>
|
||||
@elseif($view === 'timeline')
|
||||
<div class="p-6 space-y-8">
|
||||
@foreach($designers as $designer)
|
||||
<livewire:designer-innovation-timeline :designer="$designer" :detailed="true" :key="$designer->id" />
|
||||
@endforeach
|
||||
</div>
|
||||
@elseif($view === 'network')
|
||||
<div class="p-6">
|
||||
<livewire:designer-collaboration-network :designers="$designers" :interactive="true" />
|
||||
</div>
|
||||
@else
|
||||
<div class="p-6">
|
||||
<livewire:designers-creative-dashboard :designers="$designers" />
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Creative Insights Panel -->
|
||||
<div class="w-80 bg-gray-50 dark:bg-gray-800 overflow-y-auto">
|
||||
<div class="p-6">
|
||||
<livewire:designers-creative-insights />
|
||||
<div class="mt-6">
|
||||
<livewire:designers-innovation-trends />
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<livewire:designers-featured-works />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 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.
|
||||
Reference in New Issue
Block a user