Compare commits

..

6 Commits

14 changed files with 237 additions and 7 deletions

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
class CommentsController extends Controller
{
/**
* Display Comments Page.
*/
public function index(): \Illuminate\View\View
{
return view('admin.comments.index');
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
use App\Models\Hentai;
use App\Models\PopularMonthly;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use App\Http\Controllers\Controller;
@@ -46,6 +47,8 @@ class HentaiApiController extends Controller
// Cache for 60 minutes
$data = Cache::remember('api_monthly_views', now()->addMinutes(60), function () {
return PopularMonthly::selectRaw('DATE(created_at) as date, COUNT(*) as count')
->whereDate('created_at', '<', Carbon::today())
->whereDate('created_at', '>=', Carbon::today()->subDays(28))
->groupBy('date')
->orderBy('date', 'asc')
->get();

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\DB;
class AdminCommentSearch extends Component
{
use WithPagination;
public $search = '';
public $userSearch = '';
public function updatingSearch(): void
{
$this->resetPage();
}
public function updatingUserSearch(): void
{
$this->resetPage();
}
public function render()
{
$comments = DB::table('comments')
->join('users', 'comments.commenter_id', '=', 'users.id')
->select('comments.*', 'users.username')
->when($this->search !== '', fn ($query) => $query->where('comment', 'LIKE', "%$this->search%"))
->when($this->userSearch !== '', fn ($query) => $query->where('username', 'LIKE', "%$this->userSearch%"))
->paginate(12);
return view('livewire.admin-comment-search', [
'comments' => $comments
]);
}
}

View File

@@ -8,6 +8,8 @@ use Livewire\Component;
use Livewire\WithPagination;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\DB;
class AdminUserSearch extends Component
{
use WithPagination;
@@ -24,6 +26,18 @@ class AdminUserSearch extends Component
#[Url(history: true)]
public $banned = [];
public function deleteUserComments(int $userID)
{
$user = User::where('id', $userID)
->firstOrFail();
DB::table('comments')
->where('commenter_id', '=', $user->id)
->delete();
cache()->flush();
}
public function render()
{
$users = User::when($this->filtered !== [], fn ($query) => $query->where('id', '>=', 10000))

View File

@@ -34,7 +34,7 @@ window.axios.get('/v1/monthly-views').then(function (response) {
plugins: {
title: {
display: true,
text: 'Views the last 30 days',
text: 'Views the last 28 days',
font: {
size: 18
}

View File

@@ -20,3 +20,45 @@ if(localStorage.theme) {
// Default Dark Theme
localStorage.theme = 'dark';
}
// Ability to disable blur effects for slower devices
const LOCAL_STORAGE_KEY = 'blur';
const blurCheckbox = document.querySelector("input[type='checkbox']#toggleBlur");
function setCSSFilter(selector, value) {
document.querySelectorAll(selector).forEach(el => {
el.style.backdropFilter = value
});
}
function applyBlur(enabled) {
if (!enabled) {
setCSSFilter('.backdrop-blur, .backdrop-blur-sm, .backdrop-blur-lg', 'none');
return;
}
setCSSFilter('.backdrop-blur-lg', 'blur(16px)');
setCSSFilter('.backdrop-blur', 'blur(8px)');
setCSSFilter('.backdrop-blur-sm', 'blur(4px)');
}
function initBlurToggle() {
const storedValue = localStorage.getItem(LOCAL_STORAGE_KEY);
const enabled = storedValue === null ? true : storedValue === 'true';
// initialize UI and DOM
applyBlur(enabled);
if (blurCheckbox) blurCheckbox.checked = enabled;
// add event listener
if (blurCheckbox) {
blurCheckbox.addEventListener('click', (e) => {
console.log("Received Event");
const isEnabled = e.target.checked;
applyBlur(isEnabled);
localStorage.setItem(LOCAL_STORAGE_KEY, isEnabled ? 'true' : 'false');
});
}
}
initBlurToggle();

View File

@@ -0,0 +1,5 @@
@extends('admin.layout')
@section('content')
@livewire('admin-comment-search')
@endsection

View File

@@ -19,6 +19,12 @@
<span class="ms-3">Users</span>
</a>
</li>
<li>
<a href="{{ route('admin.comments.index') }}" class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-pink-700/40 group @if(Route::is('admin.comments.index')) bg-pink-700/40 @endif">
<i class="fa-solid fa-comment"></i>
<span class="ms-3">Comments</span>
</a>
</li>
<li>
<a href="{{ route('admin.contact.index') }}" class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-pink-700/40 group @if(Route::is('admin.contact.index')) bg-pink-700/40 @endif">
<i class="fa-solid fa-message"></i>

View File

@@ -59,11 +59,16 @@
</div>
</div>
</x-dropdown-link>
{{-- Expiremental --}}
<x-dropdown-link>
@include('partials.blurswitcher')
</x-dropdown-link>
</x-slot>
</x-dropdown>
</div>
<div class="flex items-center invisible sm:visible">
<div class="items-center hidden md:flex">
@livewire('nav-live-search')
<div class="hidden lg:block pl-4">
<div class="flex flex-col items-center bg-gray-50/20 dark:bg-neutral-900/40 rounded-md">

View File

@@ -0,0 +1,57 @@
<div>
<div class="relative pt-5 text-gray-900 dark:text-white xl:max-w-[95%] 2xl:max-w-[90%]" wire:keydown.right.window="nextPage" wire:keydown.left.window="previousPage">
<div class="flex items-center justify-center">
<div class="relative overflow-x-auto rounded-lg w-3/6">
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-white">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-pink-700 dark:text-neutral-200 ">
<tr>
<th scope="col" class="px-6 py-3 text-center">
User
<input
wire:model.live.debounce.600ms="userSearch"
type="search"
id="live-search"
class="w-32 h-7 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900"
placeholder="Search..."
>
</th>
<th scope="col" class="px-6 py-3">
Comment
<input
wire:model.live.debounce.600ms="search"
type="search"
id="live-search"
class="ml-2 w-32 h-7 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900"
placeholder="Search..."
>
</th>
<th scope="col" class="px-6 py-3">
Actions
</th>
</tr>
</thead>
<tbody>
@foreach($comments as $comment)
<tr wire:key="comment-{{ $comment->id }}" class="bg-white border-t dark:bg-neutral-800 dark:border-pink-700">
<td class="px-6 py-4">
<a href="{{ route('user.index', ['username' => $comment->username]) }}">{{ $comment->username }}</a>
</td>
<th scope="row" class="px-6 py-4 font-medium text-gray-900 dark:text-white max-w-lg">
{{ $comment->comment }}
</th>
<td class="px-6 py-4">
<a href="{{ route('comments.destroy', $comment->id) }}" onclick="event.preventDefault();document.getElementById('comment-delete-form-{{ $comment->id }}').submit();" class="inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 mt-2">@lang('comments::comments.delete')</a>
<form id="comment-delete-form-{{ $comment->id }}" action="{{ route('comments.destroy', $comment->id) }}" method="POST" style="display: none;">
@method('DELETE')
@csrf
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
{{ $comments->links('pagination::tailwind') }}
</div>
</div>

View File

@@ -74,15 +74,18 @@
<td class="px-6 py-4">
{{ $user->updated_at->format('Y-m-d') }}
</td>
<td class="px-6 py-4">
<td class="px-6 py-4 flex flex-col gap-1">
<form method="POST" action="{{ route('admin.user.update') }}">
@csrf
<input type="hidden" value="{{ $user->id }}" name="id">
<input type="hidden" value="{{ $user->is_banned ? 'unban' : 'ban' }}" name="action">
<button type="submit" class="inline-block rounded bg-rose-600 pl-[4px] pr-[4px] p-[1px] text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
<button type="submit" class="inline-block w-full rounded bg-rose-600 pl-[4px] pr-[4px] p-[1px] text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
{{ $user->is_banned ? 'Unban' : 'Ban' }}
</button>
</form>
<button wire:click="deleteUserComments('{{ $user->id }}')" class="inline-block w-full rounded bg-red-600 pl-[4px] pr-[4px] p-[1px] text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
Delete comments
</button>
</td>
</tr>
@endforeach

View File

@@ -75,8 +75,8 @@
>
<span class="absolute right-0 top-0 bg-white/90 dark:bg-neutral-800/80 dark:text-white text-xs font-semibold rounded-tr rounded-bl-xl px-2 py-1">{{ $episode->getResolution() }}</span>
<div class="absolute left-0 bottom-0 bg-white/90 dark:bg-neutral-800/80 dark:text-white text-xs rounded-tr-xl px-2 py-1 font-medium">
<i class="fa-regular fa-eye mr-1"></i> {{ $episode->view_count }}
<i class="fa-regular fa-heart ml-2"></i> {{ count($episode->likes) }}
<i class="fa-regular fa-eye mr-1"></i> {{ $episode->viewCountFormatted() }}
<i class="fa-regular fa-heart ml-2"></i> {{ $episode->likeCount() }}
</div>
</div>
<div class="p-3">

View File

@@ -0,0 +1,36 @@
<div class="grid grid-cols-2">
<p class="cursor-default">{{ __('Blur effects') }}</p>
<div class="flex items-center">
<div class="absolute right-6">
<label for="toggleBlur" class="flex items-center cursor-pointer">
<!-- toggle -->
<div class="relative">
<!-- input -->
<input id="toggleBlur" type="checkbox" class="sr-only" checked />
<!-- line -->
<div class="w-10 h-4 bg-rose-600 dark:bg-gray-400 rounded-full shadow-inner">
</div>
<!-- dot -->
<div
class="dot absolute w-6 h-6 bg-white dark:bg-neutral-950 rounded-full shadow -left-1 -top-1 transition">
<div class="items-center ml-[4px] w-6 h-6 font-medium flex">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-blur">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M12 21a9.01 9.01 0 0 0 2.32 -.302a9 9 0 0 0 1.74 -16.733a9 9 0 1 0 -4.06 17.035z" />
<path d="M12 3v17" />
<path d="M12 12h9" />
<path d="M12 9h8" />
<path d="M12 6h6" />
<path d="M12 18h6" />
<path d="M12 15h8" />
</svg>
</div>
</div>
</div>
</label>
</div>
</div>
</div>

View File

@@ -102,6 +102,9 @@ Route::group(['middleware' => ['auth', 'auth.admin']], function () {
Route::get('/admin/users', [App\Http\Controllers\Admin\UserController::class, 'index'])->name('admin.user.index');
Route::post('/admin/users', [App\Http\Controllers\Admin\UserController::class, 'update'])->name('admin.user.update');
// Comments
Route::get('/admin/comments', [App\Http\Controllers\Admin\CommentsController::class, 'index'])->name('admin.comments.index');
// Contact page overview
Route::get('/admin/contact', [App\Http\Controllers\Admin\ContactController::class, 'index'])->name('admin.contact.index');
Route::delete('/admin/contact/{contact_id}', [App\Http\Controllers\Admin\ContactController::class, 'delete'])->name('admin.contact.delete');