Mod Page Tabs (#3)

This commit is contained in:
Refringe 2024-07-23 22:00:46 -04:00 committed by GitHub
commit 664837f512
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 115 additions and 40 deletions

View File

@ -6,6 +6,7 @@ use App\Http\Requests\ModRequest;
use App\Http\Resources\ModResource; use App\Http\Resources\ModResource;
use App\Models\Mod; use App\Models\Mod;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\Log;
class ModController extends Controller class ModController extends Controller
{ {
@ -29,7 +30,12 @@ class ModController extends Controller
{ {
$mod = Mod::select() $mod = Mod::select()
->withTotalDownloads() ->withTotalDownloads()
->with(['latestSptVersion', 'users:id,name']) ->with([
'versions',
'latestSptVersion',
'users:id,name',
'license:id,name,link'
])
->with('license:id,name,link') ->with('license:id,name,link')
->find($modId); ->find($modId);

View File

@ -43,7 +43,7 @@ class Mod extends Model
public function versions(): HasMany public function versions(): HasMany
{ {
return $this->hasMany(ModVersion::class); return $this->hasMany(ModVersion::class)->orderByDesc('version');
} }
/** /**

View File

@ -23,8 +23,8 @@ class ModVersionFactory extends Factory
'virus_total_link' => fake()->url(), 'virus_total_link' => fake()->url(),
'downloads' => fake()->randomNumber(), 'downloads' => fake()->randomNumber(),
'disabled' => fake()->boolean(), 'disabled' => fake()->boolean(),
'created_at' => Carbon::now(), 'created_at' => Carbon::now()->subDays(rand(0, 365))->subHours(rand(0, 23)),
'updated_at' => Carbon::now(), 'updated_at' => Carbon::now()->subDays(rand(0, 365))->subHours(rand(0, 23)),
]; ];
} }
} }

View File

@ -8,6 +8,8 @@
<div class="grid grid-cols-1 lg:grid-cols-3 max-w-7xl mx-auto pb-6 px-4 gap-6 sm:px-6 lg:px-8"> <div class="grid grid-cols-1 lg:grid-cols-3 max-w-7xl mx-auto pb-6 px-4 gap-6 sm:px-6 lg:px-8">
<div class="lg:col-span-2 flex flex-col gap-6"> <div class="lg:col-span-2 flex flex-col gap-6">
{{-- mod info card --}}
<div class="p-4 sm:p-6 text-center sm:text-left bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl"> <div class="p-4 sm:p-6 text-center sm:text-left bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl">
<div class="flex flex-col sm:flex-row gap-4 sm:gap-6"> <div class="flex flex-col sm:flex-row gap-4 sm:gap-6">
<div class="grow-0 shrink-0 flex justify-center items-center"> <div class="grow-0 shrink-0 flex justify-center items-center">
@ -19,57 +21,124 @@
@endif @endif
</div> </div>
<div class="grow flex flex-col justify-center items-center sm:items-start text-gray-800 dark:text-gray-200"> <div class="grow flex flex-col justify-center items-center sm:items-start text-gray-800 dark:text-gray-200">
<div class="flex justify-between items-center space-x-3">
<h2 class="pb-1 sm:p-0 text-3xl font-bold text-gray-900 dark:text-white"> <h2 class="pb-1 sm:p-0 text-3xl font-bold text-gray-900 dark:text-white">
{{ $mod->name }} {{ $mod->name }}
<span class="font-light text-nowrap text-gray-700 dark:text-gray-400"> <span class="font-light text-nowrap text-gray-700 dark:text-gray-400">
{{ $mod->latestSptVersion->version }} {{ $mod->latestSptVersion->version }}
</span> </span>
</h2> </h2>
<span class="badge-version {{ $mod->latestSptVersion->sptVersion->color_class }} inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-nowrap">
{{ $mod->latestSptVersion->sptVersion->version }}
</span>
</div>
<p>{{ __('Created by') }} {{ $mod->users->pluck('name')->implode(', ') }}</p> <p>{{ __('Created by') }} {{ $mod->users->pluck('name')->implode(', ') }}</p>
<p>{{ $mod->latestSptVersion->sptVersion->version }} {{ __('Compatible') }}</p> <p>{{ $mod->latestSptVersion->sptVersion->version }} {{ __('Compatible') }}</p>
<p>{{ $mod->total_downloads }} {{ __('Downloads') }}</p> <p>{{ Number::format($mod->total_downloads) }} {{ __('Downloads') }}</p>
</div> </div>
</div> </div>
</div> </div>
{{-- tabs --}}
<div x-data="{ selectedTab: window.location.hash ? window.location.hash.substring(1) : 'description' }"
x-init="$watch('selectedTab', (tab) => {window.location.hash = tab})"
class="lg:col-span-2 flex flex-col gap-6">
<div> <div>
{{-- dropdown select, for small screens --}}
<div class="sm:hidden"> <div class="sm:hidden">
<label for="tabs" class="sr-only">Select a tab</label> <label for="tabs" class="sr-only">Select a tab</label>
{{-- Use an "onChange" listener to redirect the user to the selected tab URL. --}} <select id="tabs" name="tabs" x-model="selectedTab"
<select id="tabs" name="tabs" class="block w-full rounded-md dark:text-white bg-gray-100 dark:bg-gray-950 border-gray-300 dark:border-gray-700 focus:border-grey-500 dark:focus:border-grey-600 focus:ring-grey-500 dark:focus:ring-grey-600"> class="block w-full rounded-md dark:text-white bg-gray-100 dark:bg-gray-950 border-gray-300 dark:border-gray-700 focus:border-grey-500 dark:focus:border-grey-600 focus:ring-grey-500 dark:focus:ring-grey-600">
<option selected>Description</option> <option value="description">{{ __('Description') }}</option>
<option>Versions</option> <option value="versions">{{ __('Versions') }}</option>
<option>Comments</option> <option value="comments">{{ __('Comments') }}</option>
</select> </select>
</div> </div>
{{-- tab buttons --}}
<div class="hidden sm:block"> <div class="hidden sm:block">
<nav class="isolate flex divide-x divide-gray-200 dark:divide-gray-800 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl" aria-label="Tabs"> <nav
<a href="#description" class="tab rounded-l-xl group relative min-w-0 flex-1 overflow-hidden py-4 px-4 text-center text-sm font-medium text-gray-900 dark:text-white bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-black dark:hover:text-white focus:z-10" aria-current="page"> class="isolate flex divide-x divide-gray-200 dark:divide-gray-800 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl"
aria-label="Tabs">
<button @click="selectedTab = 'description'"
class="tab rounded-l-xl group relative min-w-0 flex-1 overflow-hidden py-4 px-4 text-center text-sm font-medium text-gray-900 dark:text-white bg-white dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-black dark:hover:text-white focus:z-10"
aria-current="page">
<span>Description</span> <span>Description</span>
<span aria-hidden="true" class="bg-gray-500 absolute inset-x-0 bottom-0 h-0.5"></span> </a> <span aria-hidden="true" :class="selectedTab === 'description' ? 'bg-gray-500 absolute inset-x-0 bottom-0 h-0.5' : 'bottom-0 h-0.5'"></span>
<a href="#versions" class="tab group relative min-w-0 flex-1 overflow-hidden py-4 px-4 text-center text-sm font-medium text-gray-900 dark:text-white bg-white dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-black dark:hover:text-white focus:z-10"> </button>
<button @click="selectedTab = 'versions'"
class="tab group relative min-w-0 flex-1 overflow-hidden py-4 px-4 text-center text-sm font-medium text-gray-900 dark:text-white bg-white dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-black dark:hover:text-white focus:z-10">
<span>Versions</span> <span>Versions</span>
<span aria-hidden="true" class="bg-transparent absolute inset-x-0 bottom-0 h-0.5"></span> <span aria-hidden="true" :class="selectedTab === 'versions' ? 'bg-gray-500 absolute inset-x-0 bottom-0 h-0.5' : 'bottom-0 h-0.5'"></span>
</a> </button>
<a href="#comments" class="tab rounded-r-xl group relative min-w-0 flex-1 overflow-hidden py-4 px-4 text-center text-sm font-medium text-gray-900 dark:text-white bg-white dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-black dark:hover:text-white focus:z-10"> <button @click="selectedTab = 'comments'"
class="tab rounded-r-xl group relative min-w-0 flex-1 overflow-hidden py-4 px-4 text-center text-sm font-medium text-gray-900 dark:text-white bg-white dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-black dark:hover:text-white focus:z-10">
<span>Comments</span> <span>Comments</span>
<span aria-hidden="true" class="bg-transparent absolute inset-x-0 bottom-0 h-0.5"></span> <span aria-hidden="true" :class="selectedTab === 'comments' ? 'bg-gray-500 absolute inset-x-0 bottom-0 h-0.5' : 'bottom-0 h-0.5'"></span>
</a> </button>
</nav> </nav>
</div> </div>
</div> </div>
<div id="description" class="user-markdown p-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl"> {{-- tab panels --}}
{{-- description --}}
<div x-show="selectedTab === 'description'"
class="user-markdown p-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl">
{{-- The description below is safe to write directly because it has been run though HTMLPurifier during the import process. --}} {{-- The description below is safe to write directly because it has been run though HTMLPurifier during the import process. --}}
<p>{!! Str::markdown($mod->description) !!}</p> <p>{!! Str::markdown($mod->description) !!}</p>
</div> </div>
{{-- versions --}}
<div x-show="selectedTab === 'versions'"
class="user-markdown p-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl">
@foreach($mod->versions as $version)
@if(!$version->disabled)
<div class="p-4 sm:p-6 bg-white dark:bg-gray-800 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl mb-2">
<div class="border-b-2 border-gray-700">
<div class="p-4">
<div class="flex items-center justify-between">
<a class="text-2xl" href="{{ $version->link }}">
Version {{$version->version}}
</a>
<p class="text-gray-700">{{ Number::forhumans($version->downloads) }} Downloads</p>
</div>
<div class="flex items-center justify-between">
<span class="badge-version {{ $version->sptVersion->color_class }} inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-nowrap">
{{ $version->sptVersion->version }}
</span>
<a href="{{ $version->virus_total_link }}">{{__('Virus Total Results')}}</a>
</div>
<div class="flex items-center justify-between text-gray-400">
<span>Created {{ \Carbon\Carbon::parse($version->created_at)->format("M d, h:m a") }}</span>
<span>Last Updated {{ \Carbon\Carbon::parse($version->updated_at)->format("M d, h:m a") }}</span>
</div>
</div>
</div>
<div class="p-4">
<p>{{$version->description}}</p>
</div>
</div>
@endif
@endforeach
</div>
{{-- Comments --}}
<div x-show="selectedTab === 'comments'"
class="user-markdown p-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl">
<p>The comments go here</p>
</div>
</div>
</div> </div>
{{-- right side panel area --}}
<div class="col-span-1 flex flex-col gap-6"> <div class="col-span-1 flex flex-col gap-6">
{{-- main download button --}}
<a href="{{ $mod->latestSptVersion->link }}" class="block"> <a href="{{ $mod->latestSptVersion->link }}" class="block">
<button type="button" class="w-full">{{ __('Download Latest Version') }} ({{ $mod->latestSptVersion->version }})</button> <button class="text-lg hover:bg-cyan-400 dark:hover:bg-cyan-600 shadow-md dark:shadow-gray-950 drop-shadow-2xl bg-cyan-500 dark:bg-cyan-700 rounded-xl w-full h-20">{{ __('Download for Latest SPT Version') }} ({{ $mod->latestSptVersion->version }})</button>
</a> </a>
{{-- mod details --}}
<div class="p-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl"> <div class="p-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl">
<h2 class="text-2xl font-bold text-gray-900 dark:text-gray-100">{{ __('Details') }}</h2> <h2 class="text-2xl font-bold text-gray-900 dark:text-gray-100">{{ __('Details') }}</h2>
<ul role="list" class="divide-y divide-gray-200 dark:divide-gray-800 text-gray-900 dark:text-gray-100"> <ul role="list" class="divide-y divide-gray-200 dark:divide-gray-800 text-gray-900 dark:text-gray-100">