A lot of things.

This commit is contained in:
2026-06-08 16:25:52 +02:00
parent 6f6d6b9b84
commit f529f74823
94 changed files with 9178 additions and 107 deletions

View File

@@ -0,0 +1,89 @@
@extends('layouts.modcp')
@section('modcp-content')
<div class="modcp-page-title">
Authors
<span class="modcp-count">{{ $items->total() }}</span>
</div>
<x-mod-c-p-search placeholder="Search an author..."/>
<div class="modcp-add-form">
<form action="{{ route('modcp.authors.store') }}" method="POST">
@csrf
<div class="modcp-add-form-inner">
<input type="text" name="name" class="form-input"
placeholder="Author name..." required>
<div style="width:20%">
<livewire:xf-user-selector />
</div>
<input type="text" name="website" class="form-input"
placeholder="Website">
<button type="submit" class="btn primary">
<i data-lucide="plus" size="14"></i> Add
</button>
</div>
</form>
</div>
<div class="modcp-list">
@forelse($items as $author)
<div class="modcp-list-item" x-data="{ editing: false }">
<div class="modcp-list-item-info" x-show="!editing">
<span class="modcp-list-item-title">{{ $author->name }}</span>
<span class="modcp-list-item-meta">
<span class="badge">{{ $author->website ?? '—' }}</span>
@if(($xfUser = $author->user()) !== null )
<span class="badge">
<x-xf-username-link :user="$xfUser" />
</span>
@endif
· {{ $author->entries_count }} {{ Str::plural('entry', $author->entries_count) }}
</span>
</div>
<form action="{{ route('modcp.authors.update', $author) }}" method="POST"
class="modcp-list-item-edit modcp-list-item-edit--game"
x-show="editing" x-cloak>
@csrf @method('PATCH')
<input type="text" name="name" class="form-input"
placeholder="Author name..." value="{{ $author->name }}" required>
<div style="width:20%">
<livewire:xf-user-selector :initial-user-id="$author->user_id" />
</div>
<input type="text" name="website" class="form-input"
placeholder="Website" value="{{ $author->website }}">
<button type="submit" class="btn primary">
<i data-lucide="check" size="13"></i>
</button>
<button type="button" class="btn" @click="editing = false">
<i data-lucide="x" size="13"></i>
</button>
</form>
<div class="modcp-list-item-actions" x-show="!editing">
<button type="button" class="btn" @click="editing = true">
<i data-lucide="pen" size="13"></i>
</button>
<form action="{{ route('modcp.authors.destroy', $author) }}" method="POST"
style="display:inline"
onsubmit="return confirm('Delete {{ addslashes($author->name) }}?')">
@csrf @method('DELETE')
<button type="submit" class="btn danger"
{{ $author->entries_count > 0 ? 'disabled title=Has entries' : '' }}>
<i data-lucide="trash-2" size="13"></i>
</button>
</form>
</div>
</div>
@empty
<div class="modcp-empty"><p>No authors yet.</p></div>
@endforelse
</div>
{{ $items->links() }}
@endsection

View File

@@ -0,0 +1,61 @@
@extends('layouts.modcp')
@section('page-title', 'Deleted entries - ' . config('app.name') )
@section('modcp-content')
<div class="modcp-page-title">
<i data-lucide="trash-2" size="20"></i>
Deleted entries
<span class="modcp-count">{{ $entries->total() }}</span>
</div>
@if($entries->isEmpty())
<div class="modcp-empty">
<i data-lucide="check-circle" size="36"></i>
<p>No deleted entries.</p>
</div>
@else
<div class="modcp-list">
@foreach($entries as $entry)
<div class="modcp-list-item modcp-list-item--deleted">
<div class="modcp-list-item-cover">
@if($entry->main_image)
<img src="{{ Storage::url($entry->main_image) }}" alt="">
@else
<i data-lucide="image" size="20"></i>
@endif
</div>
<div class="modcp-list-item-info">
<span class="modcp-list-item-title">{{ $entry->complete_title ?? $entry->title }}</span>
<span class="modcp-list-item-meta">
<span class="badge {{ $entry->type }}">{{ $entry->type }}</span>
@php $daysLeft = max(0, 7 - (int) now()->diffInDays($entry->deleted_at)) @endphp
<span style="color: var(--error)">
Deleted {{ $entry->deleted_at->diffForHumans() }}
@if($daysLeft > 0) · purged in {{ $daysLeft }}d @endif
</span>
</span>
</div>
<div class="modcp-list-item-actions">
<form action="{{ route('modcp.restore', $entry->id) }}" method="POST" style="display:inline">
@csrf @method('PATCH')
<button type="submit" class="btn success">
<i data-lucide="rotate-ccw" size="13"></i> Restore
</button>
</form>
<form action="{{ route('modcp.destroy', $entry->id) }}" method="POST" style="display:inline"
@submit="if (!confirm('Permanently delete this entry?')) $event.preventDefault()">
@csrf @method('DELETE')
<button type="submit" class="btn danger">
<i data-lucide="trash-2" size="13"></i> Purge
</button>
</form>
</div>
</div>
@endforeach
</div>
{{ $entries->links() }}
@endif
@endsection

View File

@@ -0,0 +1,52 @@
@extends('layouts.modcp')
@section('page-title', $pageTitle . ' - ' . config('app.name') )
@section('modcp-content')
<div class="modcp-page-title">
{{ $pageTitle }}
<span class="modcp-count">{{ $entries->count() }}</span>
</div>
@if($entries->isEmpty())
<div class="modcp-empty">
<i data-lucide="check-circle" size="36"></i>
<p>No {{ $state }} entries.</p>
</div>
@else
<div class="modcp-list">
@foreach($entries as $entry)
<div class="modcp-list-item">
<div class="modcp-list-item-cover">
@if($entry->main_image)
<img src="{{ Storage::url($entry->main_image) }}" alt="">
@else
<i data-lucide="image" size="20"></i>
@endif
</div>
<div class="modcp-list-item-info">
<span class="modcp-list-item-title">{{ $entry->complete_title }}</span>
<span class="modcp-list-item-meta">
<span class="badge {{ $entry->type }}">{{ \App\Livewire\Database::ENTRY_TYPES[$entry->type] }}</span>
@if($entry->getRealPlatform())
<span class="badge">{{ $entry->getRealPlatform()->name }}</span>
@endif
Added {{ $entry->created_at->format('d M Y') }} by<x-xf-username-link :user-id="$entry->user_id" />
</span>
</div>
<div class="modcp-list-item-actions">
<a href="{{ route('entries.show', ['section' => $entry->type, 'entry' => $entry]) }}"
class="btn" target="_blank">
<i data-lucide="eye" size="13"></i> View
</a>
<a href="{{ route('submit.edit', [$entry->type, $entry->id]) }}"
class="btn">
<i data-lucide="pen" size="13"></i> Edit
</a>
</div>
</div>
@endforeach
</div>
{{ $entries->links() }}
@endif
@endsection

View File

@@ -0,0 +1,103 @@
@extends('layouts.modcp')
@section('modcp-content')
<div class="modcp-page-title">
Games
<span class="modcp-count">{{ $items->total() }}</span>
</div>
<x-mod-c-p-search placeholder="Search a game..." />
<div class="modcp-add-form">
<form action="{{ route('modcp.games.store') }}" method="POST">
@csrf
<div class="modcp-add-form-inner">
<input type="text" name="name" class="form-input"
placeholder="Game name..." required>
<select name="platform_id" class="form-select" required style="width: 20%">
<option value="" disabled selected>Platform...</option>
@foreach($platforms as $platform)
<option value="{{ $platform->id }}">{{ $platform->name }}</option>
@endforeach
</select>
<select name="genre_id" class="form-select" required style="width: 20%">
<option value="" disabled selected>Genre...</option>
@foreach($genres as $genre)
<option value="{{ $genre->id }}">{{ $genre->name }}</option>
@endforeach
</select>
<button type="submit" class="btn primary">
<i data-lucide="plus" size="14"></i> Add
</button>
</div>
</form>
</div>
<div class="modcp-list">
@forelse($items as $game)
<div class="modcp-list-item" x-data="{ editing: false }">
<div class="modcp-list-item-info" x-show="!editing">
<span class="modcp-list-item-title">{{ $game->name }}</span>
<span class="modcp-list-item-meta">
<span class="badge">{{ $game->platform->name ?? '—' }}</span>
<span class="badge">{{ $game->genre->name ?? '—' }}</span>
· {{ $game->entries_count }} {{ Str::plural('entry', $game->entries_count) }}
</span>
</div>
<form action="{{ route('modcp.games.update', $game) }}" method="POST"
class="modcp-list-item-edit modcp-list-item-edit--game"
x-show="editing" x-cloak>
@csrf @method('PATCH')
<input type="text" name="name" class="form-input"
value="{{ $game->name }}" required>
<select name="platform_id" class="form-select form-select--small" required>
@foreach($platforms as $platform)
<option value="{{ $platform->id }}"
{{ $game->platform_id == $platform->id ? 'selected' : '' }}>
{{ $platform->name }}
</option>
@endforeach
</select>
<select name="genre_id" class="form-select form-select--small" required>
@foreach($genres as $genre)
<option value="{{ $genre->id }}"
{{ $game->genre_id == $genre->id ? 'selected' : '' }}>
{{ $genre->name }}
</option>
@endforeach
</select>
<button type="submit" class="btn primary">
<i data-lucide="check" size="13"></i>
</button>
<button type="button" class="btn" @click="editing = false">
<i data-lucide="x" size="13"></i>
</button>
</form>
<div class="modcp-list-item-actions" x-show="!editing">
<button type="button" class="btn" @click="editing = true">
<i data-lucide="pen" size="13"></i>
</button>
<form action="{{ route('modcp.games.destroy', $game) }}" method="POST"
style="display:inline"
onsubmit="return confirm('Delete {{ addslashes($game->name) }}?')">
@csrf @method('DELETE')
<button type="submit" class="btn danger"
{{ $game->entries_count > 0 ? 'disabled title=Has entries' : '' }}>
<i data-lucide="trash-2" size="13"></i>
</button>
</form>
</div>
</div>
@empty
<div class="modcp-empty"><p>No games yet.</p></div>
@endforelse
</div>
{{ $items->links() }}
@endsection

View File

@@ -0,0 +1,91 @@
@extends('layouts.modcp')
@section('page-title', "Dashboard - " . config('app.name') )
@section('modcp-content')
<div class="modcp-page-title">
Dashboard
</div>
<div class="modcp-stats">
<a href="{{ route('queue.index') }}" class="modcp-stat-card modcp-stat-card--orange">
<div class="modcp-stat-icon"><i data-lucide="clipboard-list" size="22"></i></div>
<div class="modcp-stat-info">
<span class="modcp-stat-value">{{ $stats['pending'] }}</span>
<span class="modcp-stat-label">In queue</span>
</div>
</a>
<a href="{{ route('modcp.locked') }}" class="modcp-stat-card">
<div class="modcp-stat-icon"><i data-lucide="lock" size="22"></i></div>
<div class="modcp-stat-info">
<span class="modcp-stat-value">{{ $stats['locked'] }}</span>
<span class="modcp-stat-label">Locked</span>
</div>
</a>
@can('is-admin')
<a href="{{ route('modcp.draft') }}" class="modcp-stat-card">
<div class="modcp-stat-icon"><i data-lucide="scissors" size="22"></i></div>
<div class="modcp-stat-info">
<span class="modcp-stat-value">{{ $stats['draft'] }}</span>
<span class="modcp-stat-label">Draft</span>
</div>
</a>
<a href="{{ route('modcp.hidden') }}" class="modcp-stat-card">
<div class="modcp-stat-icon"><i data-lucide="eye-off" size="22"></i></div>
<div class="modcp-stat-info">
<span class="modcp-stat-value">{{ $stats['hidden'] }}</span>
<span class="modcp-stat-label">Hidden</span>
</div>
</a>
<a href="{{ route('modcp.deleted') }}" class="modcp-stat-card modcp-stat-card--danger">
<div class="modcp-stat-icon"><i data-lucide="trash-2" size="22"></i></div>
<div class="modcp-stat-info">
<span class="modcp-stat-value">{{ $stats['deleted'] }}</span>
<span class="modcp-stat-label">Deleted</span>
</div>
</a>
@endcan
<div class="modcp-stat-card modcp-stat-card--muted">
<div class="modcp-stat-icon"><i data-lucide="database" size="22"></i></div>
<div class="modcp-stat-info">
<span class="modcp-stat-value">{{ $stats['total'] }}</span>
<span class="modcp-stat-label">Total entries</span>
</div>
</div>
</div>
@if($recentDeleted->isNotEmpty())
<div class="modcp-section-title" style="margin-top: 25px;">Recently deleted</div>
<div class="modcp-list">
@foreach($recentDeleted as $entry)
<div class="modcp-list-item">
<div class="modcp-list-item-info">
<span class="modcp-list-item-title">{{ $entry->complete_title ?? $entry->title }}</span>
<span class="modcp-list-item-meta">
<span class="badge {{ $entry->type }}">{{ $entry->type }}</span>
Deleted {{ $entry->deleted_at->diffForHumans() }}
</span>
</div>
<div class="modcp-list-item-actions">
<form action="{{ route('modcp.restore', $entry->id) }}" method="POST" style="display:inline">
@csrf @method('PATCH')
<button type="submit" class="btn success">
<i data-lucide="rotate-ccw" size="13"></i> Restore
</button>
</form>
<form action="{{ route('modcp.destroy', $entry->id) }}" method="POST" style="display:inline"
onsubmit="return confirm('Permanently delete?')">
@csrf @method('DELETE')
<button type="submit" class="btn danger">
<i data-lucide="trash-2" size="13"></i> Purge
</button>
</form>
</div>
</div>
@endforeach
<a href="{{ route('modcp.deleted') }}" class="modcp-list-see-all">
See all deleted entries
</a>
</div>
@endif
@endsection

View File

@@ -0,0 +1,76 @@
@extends('layouts.modcp')
@section('page-title', $title . ' - ' . config('app.name'))
@section('modcp-content')
<div class="modcp-page-title">
{{ $title }}
<span class="modcp-count">{{ $items->total() }}</span>
</div>
<x-mod-c-p-search placeholder="Search a {{ $singular }}..." />
<div class="modcp-add-form">
<form action="{{ route($storeRoute) }}" method="POST" class="modcp-add-form-inner">
@csrf
<input type="text" name="name" class="form-input" placeholder="Add new {{ strtolower($singular) }}..." required>
@if(isset($extraFields))
@foreach($extraFields as $field)
<input type="text" name="{{ $field['name'] }}" class="form-input" placeholder="{{ $field['placeholder'] }}">
@endforeach
@endif
<button type="submit" class="btn primary">
<i data-lucide="plus" size="14"></i> Add
</button>
</form>
</div>
<div class="modcp-list">
@forelse($items as $item)
<div class="modcp-list-item" x-data="{ editing: false }">
<div class="modcp-list-item-info" x-show="!editing">
<span class="modcp-list-item-title">{{ $item->name }}</span>
<span class="modcp-list-item-meta">
slug: {{ $item->slug }}
@isset($item->entries_count)
· {{ $item->entries_count }} {{ Str::plural('entry', $item->entries_count) }}
@endisset
</span>
</div>
<form action="{{ route($updateRoute, $item) }}" method="POST"
class="modcp-list-item-edit" x-show="editing" x-cloak>
@csrf @method('PATCH')
<input type="text" name="name" class="form-input" value="{{ $item->name }}">
<button type="submit" class="btn primary">
<i data-lucide="check" size="13"></i>
</button>
<button type="button" class="btn" @click="editing = false">
<i data-lucide="x" size="13"></i>
</button>
</form>
<div class="modcp-list-item-actions" x-show="!editing">
<button type="button" class="btn" @click="editing = true">
<i data-lucide="pen" size="13"></i>
</button>
<form action="{{ route($destroyRoute, $item) }}" method="POST" style="display:inline"
onsubmit="return confirm('Delete {{ $item->name }}?')">
@csrf @method('DELETE')
<button type="submit" class="btn danger">
<i data-lucide="trash-2" size="13"></i>
</button>
</form>
</div>
</div>
@empty
<div class="modcp-empty">
<p>No {{ strtolower($title) }} yet.</p>
</div>
@endforelse
</div>
{{ $items->links() }}
@endsection