forge/resources/views/mod/show.blade.php
Refringe 9a57925c63
Mod Detail Page Thumbnail Bug
This resolves an issue where the mod detail page would attempt to show an image if one did not exist, and would show a placeholder if the image did exist.
2025-01-28 22:56:36 -05:00

230 lines
15 KiB
PHP

<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Mod Details') }}
</h2>
</x-slot>
<div class="grid grid-cols-1 lg:grid-cols-3 max-w-7xl mx-auto py-6 px-4 gap-6 sm:px-6 lg:px-8">
<div class="lg:col-span-2 flex flex-col gap-6">
{{-- Main Mod Details Card --}}
<div class="relative 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">
@if ($mod->featured)
<div class="ribbon z-10">{{ __('Featured!') }}</div>
@endif
<div class="flex flex-col sm:flex-row gap-4 sm:gap-6">
<div class="grow-0 shrink-0 flex justify-center items-center">
@if ($mod->thumbnail)
<img src="{{ $mod->thumbnailUrl }}" alt="{{ $mod->name }}" class="w-36 rounded-lg">
@else
<img src="https://placehold.co/144x144/31343C/EEE?font=source-sans-pro&text={{ urlencode($mod->name) }}" alt="{{ $mod->name }}" class="w-36 rounded-lg">
@endif
</div>
<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:pb-2 text-3xl font-bold text-gray-900 dark:text-white">
{{ $mod->name }}
<span class="font-light text-nowrap text-gray-700 dark:text-gray-400">
{{ $mod->latestVersion->version }}
</span>
</h2>
</div>
<p>
{{ __('Created by') }}
@foreach ($mod->users as $user)
<a href="{{ $user->profileUrl() }}" class="text-slate-600 dark:text-gray-200 hover:underline">{{ $user->name }}</a>{{ $loop->last ? '' : ',' }}
@endforeach
</p>
<p title="{{ __('Exactly') }} {{ $mod->downloads }}">{{ Number::downloads($mod->downloads) }} {{ __('Downloads') }}</p>
@if ($mod->latestVersion->latestSptVersion)
<p class="mt-2">
<span class="badge-version {{ $mod->latestVersion->latestSptVersion->color_class }} inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-nowrap">
{{ $mod->latestVersion->latestSptVersion->version_formatted }} {{ __('Compatible') }}
</span>
</p>
@else
<p class="mt-2">
<span class="badge-version bg-gray-100 text-gray-600 inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-nowrap">
{{ __('Unknown SPT Version') }}
</span>
</p>
@endif
</div>
</div>
{{-- Mod teaser --}}
@if ($mod->teaser)
<p class="mt-6 pt-3 border-t-2 border-gray-200 dark:border-gray-800 text-gray-800 dark:text-gray-200">{{ $mod->teaser }}</p>
@endif
</div>
{{-- Mobile Download Button --}}
<a href="{{ $mod->downloadUrl() }}" class="block lg:hidden">
<button class="text-lg font-extrabold 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 Latest Version') }} ({{ $mod->latestVersion->version }})</button>
</a>
{{-- 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>
{{-- Mobile Dropdown --}}
<div class="sm:hidden">
<label for="tabs" class="sr-only">{{ __('Select a tab') }}</label>
<select id="tabs" name="tabs" x-model="selectedTab" 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 value="description">{{ __('Description') }}</option>
<option value="versions">{{ __('Versions') }}</option>
<option value="comments">{{ __('Comments') }}</option>
</select>
</div>
{{-- Desktop Tabs --}}
<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">
<x-tab-button name="Description" />
<x-tab-button name="Versions" />
<x-tab-button name="Comments" />
</nav>
</div>
</div>
{{-- Mod 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. --}}
{!! Str::markdown($mod->description) !!}
</div>
{{-- Mod Versions --}}
<div x-show="selectedTab === 'versions'">
@foreach ($mod->versions as $version)
<div class="p-4 mb-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl">
<div class="pb-6 border-b-2 border-gray-200 dark:border-gray-800">
<div class="flex items-center justify-between">
<a class="text-2xl font-extrabold" href="{{ $version->downloadUrl() }}">
{{ __('Version') }} {{ $version->version }}
</a>
<p class="text-gray-700 dark:text-gray-300" title="{{ __('Exactly') }} {{ $version->downloads }}">{{ Number::downloads($version->downloads) }} {{ __('Downloads') }}</p>
</div>
<div class="flex items-center justify-between">
@if ($version->latestSptVersion)
<span class="badge-version {{ $version->latestSptVersion->color_class }} inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-nowrap">
{{ $version->latestSptVersion->version_formatted }}
</span>
@else
<span class="badge-version bg-gray-100 text-gray-600 inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-nowrap">
{{ __('Unknown SPT Version') }}
</span>
@endif
<a href="{{ $version->virus_total_link }}">{{__('Virus Total Results')}}</a>
</div>
<div class="flex items-center justify-between text-gray-600 dark:text-gray-400">
<span>{{ __('Created') }} {{ Carbon::dynamicFormat($version->created_at) }}</span>
<span>{{ __('Updated') }} {{ Carbon::dynamicFormat($version->updated_at) }}</span>
</div>
{{-- Display latest resolved dependencies --}}
@if ($version->latestResolvedDependencies->isNotEmpty())
<div class="text-gray-600 dark:text-gray-400">
{{ __('Dependencies:') }}
@foreach ($version->latestResolvedDependencies as $resolvedDependency)
<a href="{{ $resolvedDependency->mod->detailUrl() }}">{{ $resolvedDependency->mod->name }}&nbsp;({{ $resolvedDependency->version }})</a>@if (!$loop->last), @endif
@endforeach
</div>
@endif
</div>
<div class="py-3 user-markdown">
{{-- The description below is safe to write directly because it has been run though HTMLPurifier during the import process. --}}
{!! Str::markdown($version->description) !!}
</div>
</div>
@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>Not quite yet...</p>
</div>
</div>
</div>
{{-- Right Column --}}
<div class="col-span-1 flex flex-col gap-6">
{{-- Desktop Download Button --}}
<a href="{{ $mod->downloadUrl() }}" class="hidden lg:block">
<button class="text-lg font-extrabold 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 Latest Version') }} ({{ $mod->latestVersion->version }})</button>
</a>
{{-- Additional 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">
<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">
@if ($mod->license)
<li class="px-4 py-4 sm:px-0">
<h3>{{ __('License') }}</h3>
<p class="truncate">
<a href="{{ $mod->license->link }}" title="{{ $mod->license->name }}" target="_blank">
{{ $mod->license->name }}
</a>
</p>
</li>
@endif
@if ($mod->source_code_link)
<li class="px-4 py-4 sm:px-0">
<h3>{{ __('Source Code') }}</h3>
<p class="truncate">
<a href="{{ $mod->source_code_link }}" title="{{ $mod->source_code_link }}" target="_blank">
{{ $mod->source_code_link }}
</a>
</p>
</li>
@endif
@if ($mod->latestVersion->virus_total_link)
<li class="px-4 py-4 sm:px-0">
<h3>{{ __('Latest Version VirusTotal Result') }}</h3>
<p class="truncate">
<a href="{{ $mod->latestVersion->virus_total_link }}" title="{{ $mod->latestVersion->virus_total_link }}" target="_blank">
{{ $mod->latestVersion->virus_total_link }}
</a>
</p>
</li>
@endif
@if ($mod->latestVersion->dependencies->isNotEmpty() && $mod->latestVersion->dependencies->contains(fn($dependency) => $dependency->resolvedVersion?->mod))
<li class="px-4 py-4 sm:px-0">
<h3>{{ __('Latest Version Dependencies') }}</h3>
<p class="truncate">
@foreach ($mod->latestVersion->dependencies as $dependency)
<a href="{{ $dependency->resolvedVersion->mod->detailUrl() }}">
{{ $dependency->resolvedVersion->mod->name }}&nbsp;({{ $dependency->resolvedVersion->version }})
</a><br />
@endforeach
</p>
</li>
@endif
@if ($mod->contains_ads)
<li class="px-4 py-4 sm:px-0 flex flex-row gap-2 items-center">
<svg class="grow-0 w-[16px] h-[16px]" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
<path fill-rule="evenodd" d="M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14Zm3.844-8.791a.75.75 0 0 0-1.188-.918l-3.7 4.79-1.649-1.833a.75.75 0 1 0-1.114 1.004l2.25 2.5a.75.75 0 0 0 1.15-.043l4.25-5.5Z" clip-rule="evenodd"/>
</svg>
<h3 class="grow">
{{ __('Includes Advertising') }}
</h3>
</li>
@endif
@if ($mod->contains_ai_content)
<li class="px-4 py-4 sm:px-0 flex flex-row gap-2 items-center">
<svg class="grow-0 w-[16px] h-[16px]" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
<path fill-rule="evenodd" d="M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14Zm3.844-8.791a.75.75 0 0 0-1.188-.918l-3.7 4.79-1.649-1.833a.75.75 0 1 0-1.114 1.004l2.25 2.5a.75.75 0 0 0 1.15-.043l4.25-5.5Z" clip-rule="evenodd"/>
</svg>
<h3 class="grow">
{{ __('Includes AI Generated Content') }}
</h3>
</li>
@endif
</ul>
</div>
</div>
</div>
</x-app-layout>