167 lines
7.9 KiB
PHP
167 lines
7.9 KiB
PHP
@extends('layouts.portal')
|
|
|
|
@section('portal-content')
|
|
<section class="section">
|
|
<div class="section-heading">
|
|
<span class="eyebrow">Инвайты</span>
|
|
<h2>Управление инвайт-кодами</h2>
|
|
<p>Без действующего инвайт-кода регистрация нового аккаунта недоступна.</p>
|
|
</div>
|
|
|
|
<div class="portal-grid">
|
|
<article class="content-card">
|
|
<h3>Создать инвайт-коды</h3>
|
|
|
|
<dl class="stats-list stats-list--compact">
|
|
<div>
|
|
<dt>Всего</dt>
|
|
<dd>{{ $inviteStats['total'] }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Доступно</dt>
|
|
<dd>{{ $inviteStats['available'] }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Использовано</dt>
|
|
<dd>{{ $inviteStats['redeemed'] }}</dd>
|
|
</div>
|
|
</dl>
|
|
|
|
<form class="inline-form" method="POST" action="{{ route('admin.invite-codes.store') }}">
|
|
@csrf
|
|
|
|
<label class="form-field">
|
|
<span>Количество</span>
|
|
<input class="form-control @error('quantity') is-invalid @enderror" type="number" min="1" max="50" name="quantity" value="{{ old('quantity', 1) }}" required>
|
|
@error('quantity')<span class="form-error">{{ $message }}</span>@enderror
|
|
</label>
|
|
|
|
<button class="button button--gold" type="submit">Создать коды</button>
|
|
</form>
|
|
</article>
|
|
|
|
<article class="content-card">
|
|
<h3>Последние инвайт-коды</h3>
|
|
|
|
@if ($inviteCodes->isNotEmpty())
|
|
<div class="character-list">
|
|
@foreach ($inviteCodes as $invite)
|
|
<div class="character-row">
|
|
<div>
|
|
<strong>{{ $invite->code }}</strong>
|
|
<span>
|
|
Создал: {{ $invite->created_by_username ?: '—' }}
|
|
@if ($invite->created_at)
|
|
· {{ $invite->created_at->format('d.m.Y H:i') }}
|
|
@endif
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<strong>{{ $invite->redeemed_at ? 'Использован' : 'Свободен' }}</strong>
|
|
<span>
|
|
{{ $invite->redeemed_by_username ?: 'ещё не использован' }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<div class="empty-inline">Инвайт-коды ещё не создавались.</div>
|
|
@endif
|
|
</article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="section">
|
|
<div class="section-heading">
|
|
<span class="eyebrow">Админка</span>
|
|
<h2>Аккаунты и персонажи</h2>
|
|
<p>Здесь видны все игровые аккаунты, их персонажи и текущий уровень доступа.</p>
|
|
</div>
|
|
|
|
<form class="search-form" method="GET" action="{{ route('admin.accounts.index') }}">
|
|
<input class="form-control" type="search" name="search" value="{{ $search }}" placeholder="Поиск по логину или email">
|
|
<button class="button button--gold" type="submit">Найти</button>
|
|
@if ($search !== '')
|
|
<a class="button button--ghost" href="{{ route('admin.accounts.index') }}">Сбросить</a>
|
|
@endif
|
|
</form>
|
|
</section>
|
|
|
|
<section class="section">
|
|
<div class="account-list">
|
|
@forelse ($accounts as $account)
|
|
<article class="content-card account-card">
|
|
<div class="account-card__header">
|
|
<div>
|
|
<h3>{{ $account['username'] }}</h3>
|
|
<p>ID #{{ $account['id'] }} · {{ $account['email'] !== '' ? $account['email'] : 'email не указан' }}</p>
|
|
</div>
|
|
|
|
<span class="tag">{{ $account['access_label'] }}</span>
|
|
</div>
|
|
|
|
<dl class="stats-list stats-list--compact">
|
|
<div>
|
|
<dt>Регистрация</dt>
|
|
<dd>{{ $account['joined_at'] }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Последний вход</dt>
|
|
<dd>{{ $account['last_login_at'] }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Статус</dt>
|
|
<dd>{{ $account['locked'] ? 'Заблокирован' : 'Активен' }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Персонажей</dt>
|
|
<dd>{{ $account['characters']->count() }}</dd>
|
|
</div>
|
|
</dl>
|
|
|
|
<form class="inline-form" method="POST" action="{{ route('admin.accounts.access.update', $account['id']) }}">
|
|
@csrf
|
|
@method('PATCH')
|
|
|
|
<label class="form-field">
|
|
<span>Уровень доступа</span>
|
|
<select class="form-control @error('gmlevel') is-invalid @enderror" name="gmlevel">
|
|
@foreach ($accessLevels as $level => $label)
|
|
<option value="{{ $level }}" @selected($account['gm_level'] === $level)>{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</label>
|
|
|
|
<button class="button button--gold" type="submit">Сохранить</button>
|
|
</form>
|
|
|
|
@if ($account['characters']->isNotEmpty())
|
|
<div class="character-list">
|
|
@foreach ($account['characters'] as $character)
|
|
<div class="character-row">
|
|
<div>
|
|
<strong>{{ $character['name'] }}</strong>
|
|
<span>{{ $character['race'] }} · {{ $character['class'] }}</span>
|
|
</div>
|
|
<div>
|
|
<strong>{{ $character['level'] }} ур.</strong>
|
|
<span>{{ $character['online'] ? 'Онлайн' : 'Оффлайн' }}</span>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@else
|
|
<div class="empty-inline">На аккаунте пока нет персонажей.</div>
|
|
@endif
|
|
</article>
|
|
@empty
|
|
<article class="content-card empty-state">
|
|
<h3>Аккаунты не найдены</h3>
|
|
<p>Измени поисковый запрос или попробуй позже.</p>
|
|
</article>
|
|
@endforelse
|
|
</div>
|
|
</section>
|
|
@endsection
|