mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 06:51:10 -05:00
629 lines
25 KiB
Markdown
629 lines
25 KiB
Markdown
# Reviews Listing Page Implementation Prompt
|
|
|
|
## Django Parity Reference
|
|
**Django Implementation**: `reviews/views.py` - `ReviewListView` (similar patterns to other listing views)
|
|
**Django Template**: `reviews/templates/reviews/review_list.html`
|
|
**Django Features**: Social interaction display, sentiment analysis, review verification, context-aware filtering, real-time engagement metrics
|
|
|
|
## Core Implementation Requirements
|
|
|
|
### Laravel/Livewire Architecture
|
|
Generate the reviews listing system using ThrillWiki's custom generators:
|
|
|
|
```bash
|
|
# Generate main reviews listing with social interaction support
|
|
php artisan make:thrillwiki-livewire ReviewsListing --paginated --cached --with-tests
|
|
|
|
# Generate social interaction components
|
|
php artisan make:thrillwiki-livewire ReviewSocialInteractions --reusable --with-tests
|
|
|
|
# Generate sentiment analysis display
|
|
php artisan make:thrillwiki-livewire ReviewSentimentAnalysis --reusable --cached
|
|
|
|
# Generate review verification system
|
|
php artisan make:thrillwiki-livewire ReviewVerificationBadges --reusable --with-tests
|
|
|
|
# Generate context-aware filters
|
|
php artisan make:thrillwiki-livewire ReviewsContextFilters --reusable --cached
|
|
|
|
# Generate real-time engagement metrics
|
|
php artisan make:thrillwiki-livewire ReviewEngagementMetrics --reusable --with-tests
|
|
|
|
# Generate review quality indicators
|
|
php artisan make:thrillwiki-livewire ReviewQualityIndicators --reusable --cached
|
|
|
|
# Generate user credibility system
|
|
php artisan make:thrillwiki-livewire UserCredibilityBadges --reusable --with-tests
|
|
```
|
|
|
|
### Django Parity Features
|
|
|
|
#### 1. Social Review Search Functionality
|
|
**Django Implementation**: Multi-faceted search across:
|
|
- Review content (`content__icontains`)
|
|
- Reviewer username (`user__username__icontains`)
|
|
- Reviewable entity (`reviewable__name__icontains`)
|
|
- Review tags (`tags__name__icontains`)
|
|
- Experience context (`experience_context__icontains`)
|
|
- Visit verification status (`verified_visit`)
|
|
|
|
**Laravel Implementation**:
|
|
```php
|
|
public function socialReviewSearch($query, $context = 'all')
|
|
{
|
|
return Review::query()
|
|
->when($query, function ($q) use ($query) {
|
|
$terms = explode(' ', $query);
|
|
foreach ($terms as $term) {
|
|
$q->where(function ($subQuery) use ($term) {
|
|
$subQuery->where('content', 'ilike', "%{$term}%")
|
|
->orWhere('title', 'ilike', "%{$term}%")
|
|
->orWhere('experience_context', 'ilike', "%{$term}%")
|
|
->orWhereHas('user', function($userQuery) use ($term) {
|
|
$userQuery->where('username', 'ilike', "%{$term}%")
|
|
->orWhere('display_name', 'ilike', "%{$term}%");
|
|
})
|
|
->orWhereHas('reviewable', function($entityQuery) use ($term) {
|
|
$entityQuery->where('name', 'ilike', "%{$term}%");
|
|
})
|
|
->orWhereHas('tags', function($tagQuery) use ($term) {
|
|
$tagQuery->where('name', 'ilike', "%{$term}%");
|
|
});
|
|
});
|
|
}
|
|
})
|
|
->when($context !== 'all', function ($q) use ($context) {
|
|
$q->where('reviewable_type', $this->getModelClass($context));
|
|
})
|
|
->with([
|
|
'user' => fn($q) => $q->with(['profile', 'credibilityBadges']),
|
|
'reviewable',
|
|
'likes' => fn($q) => $q->with('user:id,username'),
|
|
'comments' => fn($q) => $q->with('user:id,username')->limit(3),
|
|
'tags',
|
|
'verificationBadges'
|
|
])
|
|
->withCount(['likes', 'dislikes', 'comments', 'shares'])
|
|
->addSelect([
|
|
'engagement_score' => DB::raw('(likes_count * 2 + comments_count * 3 + shares_count * 4)')
|
|
]);
|
|
}
|
|
```
|
|
|
|
#### 2. Advanced Social Filtering
|
|
**Django Filters**:
|
|
- Review rating (1-5 stars)
|
|
- Verification status (verified, unverified, disputed)
|
|
- Sentiment analysis (positive, neutral, negative)
|
|
- Social engagement level (high, medium, low)
|
|
- Review recency (last_day, last_week, last_month, last_year)
|
|
- User credibility level (expert, trusted, verified, new)
|
|
- Review context (solo_visit, group_visit, family_visit, enthusiast_visit)
|
|
- Review completeness (photos, detailed, brief)
|
|
|
|
**Laravel Filters Implementation**:
|
|
```php
|
|
public function applySocialFilters($query, $filters)
|
|
{
|
|
return $query
|
|
->when($filters['rating_range'] ?? null, function ($q, $range) {
|
|
[$min, $max] = explode('-', $range);
|
|
$q->whereBetween('rating', [$min, $max]);
|
|
})
|
|
->when($filters['verification_status'] ?? null, function ($q, $status) {
|
|
switch ($status) {
|
|
case 'verified':
|
|
$q->where('verified_visit', true);
|
|
break;
|
|
case 'unverified':
|
|
$q->where('verified_visit', false);
|
|
break;
|
|
case 'disputed':
|
|
$q->where('verification_disputed', true);
|
|
break;
|
|
}
|
|
})
|
|
->when($filters['sentiment'] ?? null, function ($q, $sentiment) {
|
|
$sentimentRanges = [
|
|
'positive' => [0.6, 1.0],
|
|
'neutral' => [0.4, 0.6],
|
|
'negative' => [0.0, 0.4]
|
|
];
|
|
if (isset($sentimentRanges[$sentiment])) {
|
|
$q->whereBetween('sentiment_score', $sentimentRanges[$sentiment]);
|
|
}
|
|
})
|
|
->when($filters['engagement_level'] ?? null, function ($q, $level) {
|
|
$engagementThresholds = [
|
|
'high' => 20,
|
|
'medium' => 5,
|
|
'low' => 0
|
|
];
|
|
if (isset($engagementThresholds[$level])) {
|
|
$q->havingRaw('(likes_count + comments_count + shares_count) >= ?',
|
|
[$engagementThresholds[$level]]);
|
|
}
|
|
})
|
|
->when($filters['recency'] ?? null, function ($q, $recency) {
|
|
$timeRanges = [
|
|
'last_day' => now()->subDay(),
|
|
'last_week' => now()->subWeek(),
|
|
'last_month' => now()->subMonth(),
|
|
'last_year' => now()->subYear()
|
|
];
|
|
if (isset($timeRanges[$recency])) {
|
|
$q->where('created_at', '>=', $timeRanges[$recency]);
|
|
}
|
|
})
|
|
->when($filters['user_credibility'] ?? null, function ($q, $credibility) {
|
|
$q->whereHas('user', function ($userQuery) use ($credibility) {
|
|
switch ($credibility) {
|
|
case 'expert':
|
|
$userQuery->whereHas('credibilityBadges', fn($badge) =>
|
|
$badge->where('type', 'expert'));
|
|
break;
|
|
case 'trusted':
|
|
$userQuery->where('trust_score', '>=', 80);
|
|
break;
|
|
case 'verified':
|
|
$userQuery->whereNotNull('email_verified_at');
|
|
break;
|
|
case 'new':
|
|
$userQuery->where('created_at', '>=', now()->subMonths(3));
|
|
break;
|
|
}
|
|
});
|
|
})
|
|
->when($filters['review_context'] ?? null, function ($q, $context) {
|
|
$q->where('visit_context', $context);
|
|
})
|
|
->when($filters['completeness'] ?? null, function ($q, $completeness) {
|
|
switch ($completeness) {
|
|
case 'photos':
|
|
$q->whereHas('photos');
|
|
break;
|
|
case 'detailed':
|
|
$q->whereRaw('LENGTH(content) > 500');
|
|
break;
|
|
case 'brief':
|
|
$q->whereRaw('LENGTH(content) <= 200');
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
```
|
|
|
|
#### 3. Real-Time Social Engagement Display
|
|
**Social Metrics**:
|
|
- Like/dislike counts with user attribution
|
|
- Comment threads with nested replies
|
|
- Share counts across platforms
|
|
- User credibility and verification badges
|
|
- Sentiment analysis visualization
|
|
- Engagement trend tracking
|
|
|
|
### Screen-Agnostic Design Implementation
|
|
|
|
#### Mobile Layout (320px - 767px)
|
|
- **Social Review Cards**: Compact cards with engagement metrics
|
|
- **Touch Interactions**: Swipe-to-like, pull-to-refresh, tap interactions
|
|
- **Social Actions**: Prominent like/comment/share buttons
|
|
- **User Attribution**: Clear reviewer identification with badges
|
|
|
|
**Mobile Component Structure**:
|
|
```blade
|
|
<div class="reviews-mobile-layout">
|
|
<!-- Social Search Bar -->
|
|
<div class="sticky top-0 bg-white dark:bg-gray-900 z-20 p-4">
|
|
<livewire:reviews-social-search />
|
|
<div class="flex items-center mt-2 space-x-2">
|
|
<button wire:click="filterByContext('park')"
|
|
class="flex items-center space-x-1 px-3 py-1 {{ $activeContext === 'park' ? 'bg-blue-500 text-white' : 'bg-blue-100 dark:bg-blue-900' }} rounded-full">
|
|
<span class="text-sm">Parks</span>
|
|
</button>
|
|
<button wire:click="filterByContext('ride')"
|
|
class="flex items-center space-x-1 px-3 py-1 {{ $activeContext === 'ride' ? 'bg-green-500 text-white' : 'bg-green-100 dark:bg-green-900' }} rounded-full">
|
|
<span class="text-sm">Rides</span>
|
|
</button>
|
|
<button wire:click="toggleVerifiedOnly"
|
|
class="flex items-center space-x-1 px-2 py-1 {{ $verifiedOnly ? 'bg-orange-500 text-white' : 'bg-orange-100 dark:bg-orange-900' }} rounded-full">
|
|
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<span class="text-xs">Verified</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Community Engagement Banner -->
|
|
<div class="bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 text-white p-4 m-4 rounded-lg">
|
|
<livewire:reviews-community-stats :compact="true" />
|
|
</div>
|
|
|
|
<!-- Quick Filters -->
|
|
<div class="horizontal-scroll p-4 pb-2">
|
|
<livewire:reviews-quick-filters />
|
|
</div>
|
|
|
|
<!-- Review Cards -->
|
|
<div class="space-y-4 p-4">
|
|
@foreach($reviews as $review)
|
|
<livewire:review-mobile-card :review="$review" :show-social="true" :key="$review->id" />
|
|
@endforeach
|
|
</div>
|
|
|
|
<!-- Mobile Pagination -->
|
|
<div class="sticky bottom-0 bg-white dark:bg-gray-900 p-4">
|
|
{{ $reviews->links('pagination.mobile') }}
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
#### Tablet Layout (768px - 1023px)
|
|
- **Social Stream Layout**: Two-column review stream with engagement sidebar
|
|
- **Interactive Comments**: Expandable comment threads
|
|
- **Multi-Touch Gestures**: Pinch-to-zoom on photos, swipe between reviews
|
|
- **Social Activity Feed**: Real-time updates on review interactions
|
|
|
|
**Tablet Component Structure**:
|
|
```blade
|
|
<div class="reviews-tablet-layout flex h-screen">
|
|
<!-- Social Filter Sidebar -->
|
|
<div class="w-80 bg-gray-50 dark:bg-gray-800 overflow-y-auto">
|
|
<div class="p-6">
|
|
<livewire:reviews-social-search :advanced="true" />
|
|
<div class="mt-6">
|
|
<livewire:reviews-context-filters :expanded="true" />
|
|
</div>
|
|
<div class="mt-6">
|
|
<livewire:reviews-social-filters :show-engagement="true" />
|
|
</div>
|
|
<div class="mt-6">
|
|
<livewire:reviews-community-stats :detailed="true" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Content Area -->
|
|
<div class="flex-1 flex flex-col">
|
|
<!-- Social 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">{{ $reviews->total() }} Community Reviews</h2>
|
|
<livewire:reviews-engagement-overview />
|
|
</div>
|
|
<div class="flex items-center space-x-2">
|
|
<livewire:reviews-sort-selector />
|
|
<livewire:reviews-view-toggle />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content Stream -->
|
|
<div class="flex-1 overflow-y-auto p-6">
|
|
@if($view === 'stream')
|
|
<div class="space-y-6">
|
|
@foreach($reviews as $review)
|
|
<livewire:review-tablet-card :review="$review" :interactive="true" :key="$review->id" />
|
|
@endforeach
|
|
</div>
|
|
@elseif($view === 'sentiment')
|
|
<livewire:reviews-sentiment-analysis :reviews="$reviews" />
|
|
@else
|
|
<livewire:reviews-engagement-dashboard :reviews="$reviews" />
|
|
@endif
|
|
|
|
<div class="mt-6">
|
|
{{ $reviews->links() }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
#### Desktop Layout (1024px - 1919px)
|
|
- **Three-Pane Social Layout**: Filters + reviews + activity feed
|
|
- **Advanced Social Features**: Real-time notifications, user following
|
|
- **Rich Interaction**: Hover states, contextual menus, drag-and-drop
|
|
- **Community Moderation**: Flagging, reporting, and moderation tools
|
|
|
|
**Desktop Component Structure**:
|
|
```blade
|
|
<div class="reviews-desktop-layout flex h-screen">
|
|
<!-- Advanced Social Filters -->
|
|
<div class="w-80 bg-gray-50 dark:bg-gray-800 overflow-y-auto">
|
|
<div class="p-6">
|
|
<livewire:reviews-social-search :advanced="true" :autocomplete="true" />
|
|
<div class="mt-6">
|
|
<livewire:reviews-context-filters :advanced="true" :show-statistics="true" />
|
|
</div>
|
|
<div class="mt-6">
|
|
<livewire:reviews-social-filters :advanced="true" :show-engagement="true" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Content -->
|
|
<div class="flex-1 flex flex-col">
|
|
<!-- Social 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">{{ $reviews->total() }} Community Reviews</h1>
|
|
<livewire:reviews-social-summary />
|
|
</div>
|
|
<div class="flex items-center space-x-4">
|
|
<livewire:reviews-sort-selector :advanced="true" />
|
|
<livewire:reviews-view-selector />
|
|
<livewire:reviews-moderation-tools />
|
|
</div>
|
|
</div>
|
|
<livewire:reviews-advanced-search />
|
|
</div>
|
|
|
|
<!-- Content Area -->
|
|
<div class="flex-1 overflow-y-auto">
|
|
@if($view === 'feed')
|
|
<div class="p-6 space-y-6">
|
|
@foreach($reviews as $review)
|
|
<livewire:review-desktop-card :review="$review" :comprehensive="true" :key="$review->id" />
|
|
@endforeach
|
|
<div class="mt-8">
|
|
{{ $reviews->links('pagination.desktop') }}
|
|
</div>
|
|
</div>
|
|
@elseif($view === 'sentiment')
|
|
<div class="p-6">
|
|
<livewire:reviews-sentiment-dashboard :reviews="$reviews" :interactive="true" />
|
|
</div>
|
|
@elseif($view === 'moderation')
|
|
<div class="p-6">
|
|
<livewire:reviews-moderation-dashboard :reviews="$reviews" />
|
|
</div>
|
|
@else
|
|
<div class="p-6">
|
|
<livewire:reviews-social-analytics :reviews="$reviews" />
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Social Activity Panel -->
|
|
<div class="w-80 bg-gray-50 dark:bg-gray-800 overflow-y-auto">
|
|
<div class="p-6">
|
|
<livewire:reviews-social-activity />
|
|
<div class="mt-6">
|
|
<livewire:reviews-trending-topics />
|
|
</div>
|
|
<div class="mt-6">
|
|
<livewire:reviews-featured-reviewers />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
#### Large Screen Layout (1920px+)
|
|
- **Dashboard-Style Social Interface**: Comprehensive community analytics
|
|
- **Multi-Panel Views**: Simultaneous review streams and analytics
|
|
- **Advanced Visualizations**: Sentiment analysis charts and engagement networks
|
|
- **Community Management**: Advanced moderation and user management tools
|
|
|
|
### Performance Optimization Strategy
|
|
|
|
#### Social Engagement Caching
|
|
```php
|
|
public function mount()
|
|
{
|
|
$this->socialStats = Cache::remember(
|
|
'reviews.social.stats',
|
|
now()->addMinutes(15),
|
|
fn() => $this->calculateSocialStatistics()
|
|
);
|
|
|
|
$this->trendingTopics = Cache::remember(
|
|
'reviews.trending.topics',
|
|
now()->addHours(1),
|
|
fn() => $this->loadTrendingTopics()
|
|
);
|
|
}
|
|
|
|
public function getReviewsProperty()
|
|
{
|
|
$cacheKey = "reviews.listing." . md5(serialize([
|
|
'search' => $this->search,
|
|
'filters' => $this->filters,
|
|
'context_filter' => $this->contextFilter,
|
|
'sort' => $this->sort,
|
|
'page' => $this->page,
|
|
'user_id' => auth()->id() // For personalized content
|
|
]));
|
|
|
|
return Cache::remember($cacheKey, now()->addMinutes(10), function() {
|
|
return $this->socialReviewSearch($this->search, $this->contextFilter)
|
|
->applySocialFilters($this->filters)
|
|
->orderBy($this->sort['column'], $this->sort['direction'])
|
|
->paginate(12);
|
|
});
|
|
}
|
|
```
|
|
|
|
#### Real-Time Social Features
|
|
```php
|
|
// Optimized query for social engagement data
|
|
public function optimizedSocialQuery()
|
|
{
|
|
return Review::select([
|
|
'reviews.*',
|
|
DB::raw('COALESCE(likes_count.count, 0) as likes_count'),
|
|
DB::raw('COALESCE(comments_count.count, 0) as comments_count'),
|
|
DB::raw('COALESCE(shares_count.count, 0) as shares_count'),
|
|
DB::raw('(COALESCE(likes_count.count, 0) * 2 +
|
|
COALESCE(comments_count.count, 0) * 3 +
|
|
COALESCE(shares_count.count, 0) * 4) as engagement_score'),
|
|
DB::raw('CASE
|
|
WHEN sentiment_score >= 0.6 THEN "positive"
|
|
WHEN sentiment_score >= 0.4 THEN "neutral"
|
|
ELSE "negative"
|
|
END as sentiment_category')
|
|
])
|
|
->leftJoin(DB::raw('(SELECT review_id, COUNT(*) as count FROM review_likes GROUP BY review_id) as likes_count'),
|
|
'reviews.id', '=', 'likes_count.review_id')
|
|
->leftJoin(DB::raw('(SELECT review_id, COUNT(*) as count FROM review_comments GROUP BY review_id) as comments_count'),
|
|
'reviews.id', '=', 'comments_count.review_id')
|
|
->leftJoin(DB::raw('(SELECT review_id, COUNT(*) as count FROM review_shares GROUP BY review_id) as shares_count'),
|
|
'reviews.id', '=', 'shares_count.review_id')
|
|
->with([
|
|
'user:id,username,display_name,avatar_url',
|
|
'user.credibilityBadges:id,user_id,type,title',
|
|
'reviewable:id,name,type',
|
|
'verificationBadges:id,review_id,type,verified_at',
|
|
'recentLikes' => fn($q) => $q->with('user:id,username')->limit(5),
|
|
'topComments' => fn($q) => $q->with('user:id,username')->orderBy('likes_count', 'desc')->limit(3)
|
|
]);
|
|
}
|
|
```
|
|
|
|
### Component Reuse Strategy
|
|
|
|
#### Shared Components
|
|
- **`ReviewSocialInteractions`**: Like/comment/share functionality across all review contexts
|
|
- **`ReviewVerificationBadges`**: Trust and verification indicators for authentic reviews
|
|
- **`ReviewEngagementMetrics`**: Real-time engagement tracking and display
|
|
- **`UserCredibilityBadges`**: User reputation and expertise indicators
|
|
|
|
#### Context Variations
|
|
- **`ParkReviewsListing`**: Park-specific reviews with location context
|
|
- **`RideReviewsListing`**: Ride-specific reviews with experience context
|
|
- **`UserReviewsListing`**: User profile reviews with credibility focus
|
|
- **`FeaturedReviewsListing`**: High-engagement reviews with community highlights
|
|
|
|
### Testing Requirements
|
|
|
|
#### Feature Tests
|
|
```php
|
|
/** @test */
|
|
public function can_filter_reviews_by_social_engagement()
|
|
{
|
|
$highEngagement = Review::factory()->create(['content' => 'Amazing experience!']);
|
|
$highEngagement->likes()->createMany(15, ['user_id' => User::factory()]);
|
|
$highEngagement->comments()->createMany(8, ['user_id' => User::factory()]);
|
|
|
|
$lowEngagement = Review::factory()->create(['content' => 'Okay ride']);
|
|
$lowEngagement->likes()->create(['user_id' => User::factory()]);
|
|
|
|
Livewire::test(ReviewsListing::class)
|
|
->set('filters.engagement_level', 'high')
|
|
->assertSee($highEngagement->content)
|
|
->assertDontSee($lowEngagement->content);
|
|
}
|
|
|
|
/** @test */
|
|
public function displays_user_credibility_correctly()
|
|
{
|
|
$expertUser = User::factory()->create(['username' => 'expert_reviewer']);
|
|
$expertUser->credibilityBadges()->create(['type' => 'expert', 'title' => 'Theme Park Expert']);
|
|
|
|
$expertReview = Review::factory()->create([
|
|
'user_id' => $expertUser->id,
|
|
'content' => 'Professional analysis'
|
|
]);
|
|
|
|
Livewire::test(ReviewsListing::class)
|
|
->assertSee('Theme Park Expert')
|
|
->assertSee($expertReview->content);
|
|
}
|
|
|
|
/** @test */
|
|
public function maintains_django_parity_performance_with_social_data()
|
|
{
|
|
Review::factory()->count(30)->create();
|
|
|
|
$start = microtime(true);
|
|
Livewire::test(ReviewsListing::class);
|
|
$end = microtime(true);
|
|
|
|
$this->assertLessThan(0.5, $end - $start); // < 500ms with social data
|
|
}
|
|
```
|
|
|
|
#### Social Interaction Tests
|
|
```php
|
|
/** @test */
|
|
public function calculates_engagement_scores_accurately()
|
|
{
|
|
$review = Review::factory()->create();
|
|
$review->likes()->createMany(10, ['user_id' => User::factory()]);
|
|
$review->comments()->createMany(5, ['user_id' => User::factory()]);
|
|
$review->shares()->createMany(2, ['user_id' => User::factory()]);
|
|
|
|
$component = Livewire::test(ReviewsListing::class);
|
|
$reviewData = $component->get('reviews')->first();
|
|
|
|
// Engagement score = (likes * 2) + (comments * 3) + (shares * 4)
|
|
$expectedScore = (10 * 2) + (5 * 3) + (2 * 4); // 43
|
|
$this->assertEquals($expectedScore, $reviewData->engagement_score);
|
|
}
|
|
|
|
/** @test */
|
|
public function handles_real_time_social_updates()
|
|
{
|
|
$review = Review::factory()->create();
|
|
|
|
$component = Livewire::test(ReviewsListing::class);
|
|
|
|
// Simulate real-time like
|
|
$review->likes()->create(['user_id' => User::factory()->create()]);
|
|
|
|
$component->call('refreshEngagement', $review->id)
|
|
->assertSee('1 like');
|
|
}
|
|
```
|
|
|
|
### Performance Targets
|
|
|
|
#### Universal Performance Standards with Social Features
|
|
- **Initial Load**: < 500ms (including engagement metrics)
|
|
- **Social Interaction Response**: < 200ms for like/comment actions
|
|
- **Real-time Updates**: < 100ms for engagement refresh
|
|
- **Sentiment Analysis**: < 150ms for sentiment visualization
|
|
- **Community Statistics**: < 100ms (cached)
|
|
|
|
#### Social Content Caching Strategy
|
|
- **Engagement Metrics**: 10 minutes (frequently changing)
|
|
- **Trending Topics**: 1 hour (community trends)
|
|
- **User Credibility**: 6 hours (reputation changes slowly)
|
|
- **Social Statistics**: 15 minutes (community activity)
|
|
|
|
### Success Criteria Checklist
|
|
|
|
#### Django Parity Verification
|
|
- [ ] Social review search matches Django behavior exactly
|
|
- [ ] Engagement metrics calculated identically to Django
|
|
- [ ] Verification systems work like Django implementation
|
|
- [ ] Sentiment analysis provides same results as Django
|
|
- [ ] Community features match Django social functionality
|
|
|
|
#### Screen-Agnostic Compliance
|
|
- [ ] Mobile layout optimized for social interaction
|
|
- [ ] Tablet layout provides effective community browsing
|
|
- [ ] Desktop layout maximizes social engagement features
|
|
- [ ] Large screen layout provides comprehensive community management
|
|
- [ ] All layouts handle real-time social updates gracefully
|
|
|
|
#### Performance Benchmarks
|
|
- [ ] Initial load under 500ms including social data
|
|
- [ ] Social interactions under 200ms response time
|
|
- [ ] Real-time updates under 100ms
|
|
- [ ] Community statistics under 100ms (cached)
|
|
- [ ] Social caching reduces server load by 70%
|
|
|
|
#### Social Feature Completeness
|
|
- [ ] Engagement metrics display accurately across all contexts
|
|
- [ ] User credibility systems provide meaningful trust indicators
|
|
- [ ] Verification badges work for authentic experience validation
|
|
- [ ] Community moderation tools function effectively
|
|
- [ ] Real-time social updates work seamlessly across devices
|
|
|
|
This prompt ensures complete Django parity while providing comprehensive social review capabilities that foster authentic community engagement while maintaining ThrillWiki's screen-agnostic design principles. |