feat: Add streamers to champion show view

- Added loading of streamers data in the champion show view.
- Updated ChampionController to load streamers for display.
This commit is contained in:
Rico van Zelst
2024-03-23 02:48:08 +01:00
parent b46128ec26
commit e6dcfacb31
10 changed files with 127 additions and 126 deletions

2
.gitignore vendored
View File

@@ -19,3 +19,5 @@ yarn-error.log
/.vscode
_ide_helper.php
.phpstorm.meta.php
_ide_helper_models.php

View File

@@ -24,22 +24,6 @@ class ChampionController extends Controller
return view('champions.index', ['champions' => $champions, 'roles' => $roles]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(StoreChampionRequest $request)
{
//
}
/**
* Display the specified resource.
*/
@@ -47,41 +31,21 @@ class ChampionController extends Controller
{
$threeDaysInSeconds = 60 * 60 * 24 * 3;
$sixMonthsInSeconds = 60 * 60 * 24 * 30 * 6;
$tenMinutesInSeconds = 60 * 10;
$champion = Cache::remember('championShowCache'.$champion->slug, $threeDaysInSeconds, static fn () => $champion->load('skins', 'lanes'));
$champion = Cache::remember('championShowCache' . $champion->slug, $threeDaysInSeconds, static fn () => $champion->load('streamers', 'skins', 'lanes'));
//$streamers = Cache::remember('championStreamersCache' . $champion->slug, $tenMinutesInSeconds, static fn () => $champion->streamers);
$streamers = $champion->load('streamers')->streamers;
$splashColor = Cache::remember(
'championSplashColorCache'.$champion->slug,
'championSplashColorCache' . $champion->slug,
$sixMonthsInSeconds,
static fn () => getAverageColorFromImageUrl($champion->getChampionImageAttribute())
);
$champion->splash_color = $splashColor;
return view('champions.show', ['champion' => $champion]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Champion $champion)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateChampionRequest $request, Champion $champion)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Champion $champion)
{
//
return view('champions.show', ['champion' => $champion, 'streamers' => $streamers]);
}
}

View File

@@ -14,7 +14,7 @@ class StreamerPanelController extends Controller
public function index()
{
return view('streamerpanel.index', [
'streamers' => Streamer::all(),
'streamers' => Streamer::with('champion')->get(),
]);
}
@@ -33,8 +33,7 @@ class StreamerPanelController extends Controller
*/
public function store(Request $request)
{
$request->validate([
'champion_id' => 'required|exists:champions,id',
$request->validate(['champion_id' => 'required|exists:champions,champion_id',
'platform' => 'required|in:twitch,youtube,kick,douyu,huya',
'username' => 'required|string',
'displayname' => 'required|string',

View File

@@ -94,6 +94,11 @@ class Champion extends Model
return $this->hasOne(ChampionRoles::class, 'champion_id', 'champion_id');
}
public function streamers()
{
return $this->hasMany(Streamer::class, 'champion_id', 'champion_id');
}
public function getChampionImageAttribute($centered = true): string
{
$url = 'https://cdn.communitydragon.org/latest/champion/'.$this->champion_id.'/splash-art';

View File

@@ -4,6 +4,8 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\Champion;
class Streamer extends Model
{
@@ -11,10 +13,6 @@ class Streamer extends Model
protected $fillable = ['champion_id', 'platform', 'username', 'displayname'];
public function champion()
{
return $this->belongsTo(Champion::class);
}
public function getPlatformAttribute($value): string
{
@@ -39,4 +37,9 @@ class Streamer extends Model
'Huya' => "https://www.huya.com/{$this->username}",
};
}
public function champion(): BelongsTo
{
return $this->belongsTo(Champion::class, 'champion_id', 'champion_id');
}
}

View File

@@ -13,11 +13,16 @@ return new class extends Migration
{
Schema::create('streamers', function (Blueprint $table) {
$table->id();
$table->foreignId('champion_id')->constrained();
$table->integer('champion_id');
$table->enum('platform', ['twitch', 'youtube', 'kick', 'douyu', 'huya']);
$table->string('username');
$table->string('displayname');
$table->foreign('champion_id')->references('champion_id')->on('champions')->onDelete('cascade');
$table->timestamps();
});
}

View File

@@ -5,7 +5,7 @@
about ' . $champion->name . ', ' . $champion->title . '. ' . substr($champion->lore, 0, 50) . '...')
@section('content')
<x-champions.grid_info :champion="$champion"/>
<x-champions.grid_info :champion="$champion" :streamers="$streamers"/>
@endsection
@push('bottom_scripts')

View File

@@ -5,125 +5,136 @@
CHAMPION DETAILS</h3>
<h1
class="text-3xl font-bold text-center text-transparent uppercase sm:text-4xl bg-gradient-to-bl from-orange-300 to-orange-500 bg-clip-text">
{{$champion->name}}</h1>
{{ $champion->name }}</h1>
<h2
class="text-sm md:text-lg font-bold text-center text-transparent uppercase bg-gradient-to-bl from-orange-300 to-orange-500 bg-clip-text">
{{$champion->title}}</h2>
class="text-sm font-bold text-center text-transparent uppercase md:text-lg bg-gradient-to-bl from-orange-300 to-orange-500 bg-clip-text">
{{ $champion->title }}</h2>
<div class="container mx-auto p-4 flex items-center justify-center mt-3">
<div class="w-screen grid grid-cols-1 md-grid-cols-2 lg:grid-cols-3 gap-5">
<div class="container flex items-center justify-center p-4 mx-auto mt-3">
<div class="grid w-screen grid-cols-1 gap-5 md-grid-cols-2 lg:grid-cols-3">
<div
class="relative rounded-2xl bg-stone-800/40 border border-neutral-300/5 shadow-sm shadow-stone-800/80 lg:col-span-2">
<div class="aspect-w-16 aspect-h-9 glow-shadow absolute inset-0 rounded-2xl"
style="--splash-color: {{$champion->splash_color}}"></div>
<div class="aspect-w-16 aspect-h-9 overflow-hidden rounded-2xl relative">
<img
src="//wsrv.nl/?url={{ $champion->getChampionImageAttribute(false) }}&w=880&output=webp&q=85&il"
alt="{{$champion->name}} Splash Art"
class="w-full h-full object-cover transform scale-100 transition-transform duration-700 hover:scale-105 z-10"
>
class="relative border shadow-sm rounded-2xl bg-stone-800/40 border-neutral-300/5 shadow-stone-800/80 lg:col-span-2">
<div class="absolute inset-0 aspect-w-16 aspect-h-9 glow-shadow rounded-2xl"
style="--splash-color: {{ $champion->splash_color }}"></div>
<div class="relative overflow-hidden aspect-w-16 aspect-h-9 rounded-2xl">
<img src="//wsrv.nl/?url={{ $champion->getChampionImageAttribute(false) }}&w=880&output=webp&q=85&il"
alt="{{ $champion->name }} Splash Art"
class="z-10 object-cover w-full h-full transition-transform duration-700 transform scale-100 hover:scale-105">
</div>
</div>
<div
class="rounded-2xl border border-3 border-white/10 lg:col-start-3 shadow-md transition-all duration-700"
style="--tw-shadow-color:{{$champion->splash_color}}; --tw-shadow: var(--tw-shadow-colored); background-color: {{$champion->splash_color}};">
<div class="transition-all duration-700 border shadow-md rounded-2xl border-3 border-white/10 lg:col-start-3"
style="--tw-shadow-color:{{ $champion->splash_color }}; --tw-shadow: var(--tw-shadow-colored); background-color: {{ $champion->splash_color }};">
<h4 class="text-center text-xl font-semibold text-neutral-100 uppercase mt-3.5 shadow-sm">
{{$champion->name}} Information</h4>
{{ $champion->name }} Information</h4>
<ul class="ml-7">
<li class="text-neutral-100 hyphens-auto text-base font-medium leading-loose mt-8" lang="en">
<span class="font-bold">Full Title:</span> {{$champion->name}}, {{$champion->title}}.
<li class="mt-8 text-base font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Full Title:</span> {{ $champion->name }}, {{ $champion->title }}.
</li>
<li class="text-neutral-100 hyphens-auto text-base font-medium leading-loose" lang="en">
<span class="font-bold">Popular Positions:</span> @foreach($champion->lanes->roles as $lane)
<span
class="inline-block lowercase capitalize-first">{{$lane}} @svg(getRoleIconSvg($lane), 'w-5 h-5 inline-block')
@if(!$loop->last)
<li class="text-base font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Popular Positions:</span>
@foreach ($champion->lanes->roles as $lane)
<span class="inline-block lowercase capitalize-first">{{ $lane }} @svg(getRoleIconSvg($lane), 'w-5 h-5 inline-block')
@if (!$loop->last)
-
@endif</span>
@endif
</span>
@endforeach
</li>
<li class="text-neutral-100 hyphens-auto text-base font-medium leading-loose items-center"
<li class="items-center text-base font-medium leading-loose text-neutral-100 hyphens-auto"
lang="en">
<span class="font-bold">Blue Essence Cost:</span>
<x-icon-lcu-be-svg class="inline-block w-4"/> {{$champion->price_be}} BE
<x-icon-lcu-be-svg class="inline-block w-4" /> {{ $champion->price_be }} BE
</li>
<li class="text-neutral-100 hyphens-auto text-medium font-medium leading-loose items-center"
<li class="items-center font-medium leading-loose text-neutral-100 hyphens-auto text-medium"
lang="en">
<span class="font-bold">Riot Points Cost:</span>
<x-icon-RiotPoints class="inline-block w-4"/> {{$champion->price_rp}} RP
<x-icon-RiotPoints class="inline-block w-4" /> {{ $champion->price_rp }} RP
</li>
<li class="text-neutral-100 hyphens-auto leading-loose font-medium" lang="en">
<span class="font-bold">Roles:</span> @foreach($champion->roles as $role)
<span
class="inline-block lowercase capitalize-first">{{$role}}
@if(!$loop->last)
<li class="font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Roles:</span>
@foreach ($champion->roles as $role)
<span class="inline-block lowercase capitalize-first">{{ $role }}
@if (!$loop->last)
-
@endif</span>
@endif
</span>
@endforeach
</li>
<li class="text-neutral-100 hyphens-auto leading-loose font-medium" lang="en">
<li class="font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Attack Type:</span> <span
class="inline-block lowercase capitalize-first">{{$champion->attack_type}}</span>
class="inline-block lowercase capitalize-first">{{ $champion->attack_type }}</span>
</li>
<li class="text-neutral-100 hyphens-auto leading-loose font-medium" lang="en">
<span class="font-bold">Damage Type:</span> {{$champion->adaptive_type}}
<li class="font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Damage Type:</span> {{ $champion->adaptive_type }}
</li>
<li class="text-neutral-100 hyphens-auto leading-loose font-medium" lang="en">
<span class="font-bold">Resource Type:</span> {{$champion->resource_type}}
<li class="font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Resource Type:</span> {{ $champion->resource_type }}
</li>
<li class="text-neutral-100 hyphens-auto text-base font-medium leading-loose" lang="en">
<li class="text-base font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Champion ID:</span> <span
class="font-mono font-medium">{{$champion->champion_id}}</span>
class="font-mono font-medium">{{ $champion->champion_id }}</span>
</li>
<li class="text-neutral-100 hyphens-auto leading-loose font-medium" lang="en">
<span class="font-bold">Release Date:</span> {{$champion->release_date}}
<li class="font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Release Date:</span> {{ $champion->release_date }}
</li>
<li class="text-neutral-100 hyphens-auto leading-loose font-medium" lang="en">
<span class="font-bold">Release Patch:</span> Patch {{$champion->release_patch}}
<li class="font-medium leading-loose text-neutral-100 hyphens-auto" lang="en">
<span class="font-bold">Release Patch:</span> Patch {{ $champion->release_patch }}
</li>
</ul>
</div>
<div class="rounded-2xl border border-3 border-white/10 shadow-md shadow-stone-800/80 hover:shadow-orange-500/20 transition-all duration-700"
style="--tw-shadow-color:{{$champion->splash_color}}; --tw-shadow: var(--tw-shadow-colored); background-color: {{$champion->splash_color}};">
<div class="transition-all duration-700 border shadow-md rounded-2xl border-3 border-white/10 shadow-stone-800/80 hover:shadow-orange-500/20"
style="--tw-shadow-color:{{ $champion->splash_color }}; --tw-shadow: var(--tw-shadow-colored); background-color: {{ $champion->splash_color }};">
<div class="p-4">
<h4 class="text-center text-xl font-semibold text-neutral-100 uppercase mt-2.5 shadow-sm">
{{$champion->name}} Lore</h4>
<p class="text-neutral-100 hyphens-auto text-base mt-2.5 leading-loose" lang="en">
{{$champion->lore}}
{{ $champion->name }} Streamers</h4>
<p class="text-neutral-100/75 hyphens-auto mt-2.5 leading-loose text-center text-sm" lang="en">
A list of streamers who play {{ $champion->name }} and are atleast Diamond 2 or higher.
</p>
<div class="grid grid-cols-1 gap-4 mt-2.5 lg:grid-cols-2">
@foreach ($streamers as $streamer)
<div class="flex justify-center items -center">
<div class="flex flex-col items-center justify-center">
<a href="{{ $streamer->streamer_url }}" target="_blank" rel="noopener noreferrer"
class="text-center text-neutral-100 text-sm mt-1.5 items-center">
{{ $streamer->displayname }}
</a>
</div>
</div>
@endforeach
</div>
</div>
<div
class="rounded-2xl border border-3 border-white/10 shadow-md shadow-stone-800/80 lg:col-span-2 hover:shadow-orange-500/20 transition-all duration-700"
style="--tw-shadow-color:{{$champion->splash_color}}; --tw-shadow: var(--tw-shadow-colored); background-color: {{$champion->splash_color}};">
</div>
<div class="transition-all duration-700 border shadow-md rounded-2xl border-3 border-white/10 shadow-stone-800/80 lg:col-span-2 hover:shadow-orange-500/20"
style="--tw-shadow-color:{{ $champion->splash_color }}; --tw-shadow: var(--tw-shadow-colored); background-color: {{ $champion->splash_color }};">
<div class="p-4">
<h4 class="text-center text-xl font-semibold text-neutral-100 uppercase mt-2.5 shadow-sm">
{{$champion->name}} Skins ({{count($champion->skins)}}) </h4>
{{ $champion->name }} Skins ({{ count($champion->skins) }}) </h4>
<div id="skinsElement" class="overflow-x-scroll mt-2.5">
<div class="grid grid-flow-col grid-rows-2 w-max gap-4 mb-2.5">
@foreach($champion->skins as $key => $skin)
<div class="group flex flex-col">
<a href="/skin/{{$skin->slug}}">
<img
src="//wsrv.nl/?url={{ $skin->getSkinImageAttribute() }}&w=450&output=webp&q=70&il"
alt="{{$champion->name}} {{$skin->name}} Splash Art"
@if($key < 6) loading="eager" @else loading="lazy" @endif
@foreach ($champion->skins as $key => $skin)
<div class="flex flex-col group">
<a href="/skin/{{ $skin->slug }}">
<img src="//wsrv.nl/?url={{ $skin->getSkinImageAttribute() }}&w=450&output=webp&q=70&il"
alt="{{ $champion->name }} {{ $skin->name }} Splash Art"
@if ($key < 6) loading="eager" @else loading="lazy" @endif
class="inline-block h-36 object-cover rounded-2xl shadow-md border border-3 border-white/10 hover:shadow-orange-500/20 transition-all duration-700 mr-2.5">
</a>
<div>
<p class="align-bottom text-center text-neutral-100 text-sm mt-1.5 items-center">
<a href="/skin/{{$skin->slug}}"
<p
class="align-bottom text-center text-neutral-100 text-sm mt-1.5 items-center">
<a href="/skin/{{ $skin->slug }}"
class="hover:text-orange-400 group-hover:text-orange-400">
{{$skin->skin_name}}
<x-iconsax-bul-arrow-right class="inline-block w-5"/>
{{ $skin->skin_name }}
<x-iconsax-bul-arrow-right class="inline-block w-5" />
</a>
</p>
</div>
@@ -133,6 +144,17 @@
</div>
</div>
</div>
<div class="transition-all duration-700 border shadow-md lg:col-span-3 rounded-2xl border-3 border-white/10 shadow-stone-800/80 hover:shadow-orange-500/20"
style="--tw-shadow-color:{{ $champion->splash_color }}; --tw-shadow: var(--tw-shadow-colored); background-color: {{ $champion->splash_color }};">
<div class="p-4">
<h4 class="text-center text-xl font-semibold text-neutral-100 uppercase mt-2.5 shadow-sm">
{{ $champion->name }} Lore</h4>
<p class="text-neutral-100 hyphens-auto text-base mt-2.5 leading-loose w-9/12 mx-auto"
lang="en">
{{ $champion->lore }}
</p>
</div>
</div>
</div>
</div>
</section>

View File

@@ -3,9 +3,10 @@
<div class="flex flex-col space-y-4">
<div class="flex flex-col space-y-2">
<label for="champion_id" class="text-lg font-semibold text-orange-400">Champion</label>
<select name="champion_id" id="champion_id" class="w-full p-2 text-white rounded-md bg-stone-800">
<select name="champion_id" required id="champion_id" class="w-full p-2 text-white rounded-md bg-stone-800">
<option value="">Select a champion</option>
@foreach ($champions as $champion)
<option value="{{ $champion->id }}">{{ $champion->name }}</option>
<option value="{{ $champion->champion_id }}">{{ $champion->name }}</option>
@endforeach
</select>
</div>
@@ -21,7 +22,8 @@
</div>
<div class="flex flex-col space-y-2">
<label for="username" class="text-lg font-semibold text-orange-400">Username</label>
<input type="text" name="username" id="username" class="w-full p-2 text-white rounded-md bg-stone-800" />
<input type="text" name="username" id="username"
class="w-full p-2 text-white rounded-md bg-stone-800" />
</div>
<div class="flex flex-col space-y-2">
<label for="displayname" class="text-lg font-semibold text-orange-400">Display Name</label>

View File

@@ -2,7 +2,6 @@
<script src="https://cdn.jsdelivr.net/npm/gridjs/dist/gridjs.umd.js"></script>
<link href="https://cdn.jsdelivr.net/npm/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
@endpush
<div class="w-10/12 mx-auto">
<div id="streamers-wrapper"></div>
</div>