Add Champion model, form validation, and components for StreamerPanel.

- Added Champion model to StreamerPanelController.
- Implemented form validation for champion_id, platform, username, and displayname in create and update methods.
- Created StreamerCreateForm and StreamersTable components for better organization.
This commit is contained in:
Rico van Zelst
2024-03-22 02:35:44 +01:00
parent c665d3f70f
commit b46128ec26
11 changed files with 212 additions and 12 deletions

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Streamer; use App\Models\Streamer;
use App\Models\Champion;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class StreamerPanelController extends Controller class StreamerPanelController extends Controller
@@ -22,7 +23,9 @@ class StreamerPanelController extends Controller
*/ */
public function create() public function create()
{ {
// return view('streamerpanel.streamer-create', [
'champions' => Champion::all(),
]);
} }
/** /**
@@ -30,7 +33,16 @@ class StreamerPanelController extends Controller
*/ */
public function store(Request $request) public function store(Request $request)
{ {
// $request->validate([
'champion_id' => 'required|exists:champions,id',
'platform' => 'required|in:twitch,youtube,kick,douyu,huya',
'username' => 'required|string',
'displayname' => 'required|string',
]);
Streamer::create($request->all());
return redirect()->route('streamerpanel.index');
} }
/** /**
@@ -38,7 +50,10 @@ class StreamerPanelController extends Controller
*/ */
public function edit(Streamer $streamer) public function edit(Streamer $streamer)
{ {
// return view('streamerpanel.streamer-edit', [
'streamer' => $streamer,
'champions' => Champion::all(),
]);
} }
/** /**
@@ -46,7 +61,16 @@ class StreamerPanelController extends Controller
*/ */
public function update(Request $request, Streamer $streamer) public function update(Request $request, Streamer $streamer)
{ {
// $request->validate([
'champion_id' => 'required|exists:champions,id',
'platform' => 'required|in:twitch,youtube,kick,douyu,huya',
'username' => 'required|string',
'displayname' => 'required|string',
]);
$streamer->update($request->all());
return redirect()->route('streamerpanel.index');
} }
/** /**
@@ -54,6 +78,8 @@ class StreamerPanelController extends Controller
*/ */
public function destroy(Streamer $streamer) public function destroy(Streamer $streamer)
{ {
// $streamer->delete();
return redirect()->route('streamerpanel.index');
} }
} }

View File

@@ -0,0 +1,26 @@
<?php
namespace App\View\Components\Streamerpanel;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class StreamerCreateForm extends Component
{
/**
* Create a new component instance.
*/
public function __construct(public $champions)
{
//
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.streamerpanel.streamer-create-form');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\View\Components\Streamerpanel;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
use App\Models\Streamer;
use Illuminate\Support\Collection;
class StreamersTable extends Component
{
/**
* Create a new component instance.
*/
public function __construct(public Collection $streamers)
{
$this->streamers = $streamers;
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View
{
return view('components.streamerpanel.streamers-table');
}
}

View File

@@ -19,13 +19,15 @@
<ul <ul
class="flex flex-col items-center p-2 md:flex-row md:space-x-6 md:mt-0 md:border-0 md:bg-white dark:bg-stone-800 md:dark:bg-stone-800 dark:border-stone-700"> class="flex flex-col items-center p-2 md:flex-row md:space-x-6 md:mt-0 md:border-0 md:bg-white dark:bg-stone-800 md:dark:bg-stone-800 dark:border-stone-700">
<li> <li>
<a href="{{ route('champions.index') }}" <a href="{{ route('streamerpanel.index') }}"
class="flex py-2 pl-3 pr-2 rounded hover:bg-stone-100 md:hover:bg-transparent md:border-0 md:p-0 md:dark:hover:text-orange-400 dark:hover:bg-stone-700 dark:hover:text-white md:dark:hover:bg-transparent"> class="flex py-2 pl-3 pr-2 rounded hover:bg-stone-100 md:hover:bg-transparent md:border-0 md:p-0 md:dark:hover:text-orange-400 dark:hover:bg-stone-700 dark:hover:text-white md:dark:hover:bg-transparent
{{ request()->routeIs('streamerpanel.*') ? 'text-orange-400 font-medium' : 'text-white' }}">
Streamers</a> Streamers</a>
</li> </li>
<li> <li>
<a href="{{ route('skins.index') }}" <a href="#"
class="flex py-2 pl-3 pr-2 rounded hover:bg-stone-100 md:hover:bg-transparent md:border-0 md:hover:text-orange-500 md:p-0 md:dark:hover:text-orange-400 dark:hover:bg-stone-700 dark:hover:text-white md:dark:hover:bg-transparent "> class="flex py-2 pl-3 pr-2 rounded hover:bg-stone-100 md:hover:bg-transparent md:border-0 md:hover:text-orange-500 md:p-0 md:dark:hover:text-orange-400 dark:hover:bg-stone-700 dark:hover:text-white md:dark:hover:bg-transparent
{{ request()->routeIs('streamerrequests.*') ? 'text-orange-400 font-medium' : 'text-white' }}">
Streamer Requests</a> Streamer Requests</a>
</li> </li>
</ul> </ul>

View File

@@ -0,0 +1,11 @@
<section class="max-w-screen-xl mx-auto mt-12">
<h1
class="text-2xl font-bold text-center text-transparent uppercase sm:text-4xl bg-gradient-to-bl from-orange-300 to-orange-500 bg-clip-text">
Streamers</h1>
<div class="flex justify-center mt-4">
<a href="{{ route('streamerpanel.streamers.create') }}"
class="flex items-center justify-center px-4 py-2 text-sm font-medium text-white bg-orange-500 rounded-md hover:bg-orange-600 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2">
Add Streamer
</a>
</div>
</section>

View File

@@ -0,0 +1,35 @@
<form action="{{ route('streamerpanel.store') }}" method="POST" class="w-10/12 mx-auto ">
@csrf
<div class="flex flex-col space-y-4">
<div class="flex flex-col space-y-2">
<label for="champion_id" class="text-lg font-semibold text-orange-400">Champion</label>
<select name="champion_id" id="champion_id" class="w-full p-2 text-white rounded-md bg-stone-800">
@foreach ($champions as $champion)
<option value="{{ $champion->id }}">{{ $champion->name }}</option>
@endforeach
</select>
</div>
<div class="flex flex-col space-y-2">
<label for="platform" class="text-lg font-semibold text-orange-400">Platform</label>
<select name="platform" id="platform" class="w-full p-2 text-white rounded-md bg-stone-800">
<option value="twitch">Twitch</option>
<option value="youtube">YouTube</option>
<option value="kick">Kick</option>
<option value="douyu">Douyu</option>
<option value="huya">Huya</option>
</select>
</div>
<div class="flex flex-col space-y-2">
<label for="username" class="text-lg font-semibold text-orange-400">Username</label>
<input type="text" name="username" id="username" class="w-full p-2 text-white rounded-md bg-stone-800" />
</div>
<div class="flex flex-col space-y-2">
<label for="displayname" class="text-lg font-semibold text-orange-400">Display Name</label>
<input type="text" name="displayname" id="displayname"
class="w-full p-2 text-white rounded-md bg-stone-800" />
</div>
<div class="flex justify-end">
<button type="submit" class="px-4 py-2 mt-3 text-white bg-orange-500 rounded-md">Add Streamer</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,50 @@
@push('top_scripts')
<script src="https://cdn.jsdelivr.net/npm/gridjs/dist/gridjs.umd.js"></script>
<link href="https://cdn.jsdelivr.net/npm/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
@endpush
<div class="w-10/12 mx-auto">
<div id="streamers-wrapper"></div>
</div>
@push('bottom_scripts')
<script>
new gridjs.Grid({
columns: [
"Champion",
"Streamer Name",
{
name: "URL",
formatter: (_, row) => gridjs.html(
`<a href="${row.cells[2].data}" target="_blank">${row.cells[2].data}</a>`)
},
{
name: "Actions",
formatter: (_, row) => gridjs.html(row.cells[3].data)
}
],
data: [
@foreach ($streamers as $streamer)
["{{ $streamer->champion->name }}", "{{ $streamer->displayname }}",
"{{ $streamer->streamer_url }}", `<a href="/streamerpanel/edit/{{ $streamer->id }}">✏️</a> <a href="/streamerpanel/delete/{{ $streamer->id }}" onclick="event.preventDefault(); if (confirm('Are you sure you want to delete this streamer?')) { document.getElementById('delete-form-{{ $streamer->id }}').submit(); }"></a>
<form id="delete-form-{{ $streamer->id }}" action="/streamerpanel/delete/{{ $streamer->id }}" method="POST" style="display: none;">
@csrf
@method('DELETE')
</form>`
],
@endforeach
],
search: true,
pagination: {
limit: 20
},
language: {
'search': {
'placeholder': '🔍 Search streamers...'
}
}
}).render(document.getElementById("streamers-wrapper"));
</script>
@endpush

View File

@@ -4,5 +4,6 @@
@section('description', 'Heimerdinger.LoL: Streamer Panel for managing your streamer requests.') @section('description', 'Heimerdinger.LoL: Streamer Panel for managing your streamer requests.')
@section('content') @section('content')
hello world <x-streamerpanel.home />
<x-streamerpanel.streamerstable :streamers="$streamers" />
@endsection @endsection

View File

@@ -0,0 +1,15 @@
@extends('layouts.streamerpanel')
@section('title', 'Streamer Panel • Heimerdinger.LoL')
@section('description', 'Heimerdinger.LoL: Streamer Panel for managing your streamer requests.')
@section('content')
<section class="max-w-screen-xl mx-auto mt-12">
<h1
class="text-2xl font-bold text-center text-transparent uppercase sm:text-4xl bg-gradient-to-bl from-orange-300 to-orange-500 bg-clip-text">
Add a new Streamer</h1>
<x-streamerpanel.streamer-create-form :champions="$champions" />
</section>
@endsection

View File

@@ -18,6 +18,7 @@ use App\Models\SummonerIcon;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Spatie\Honeypot\ProtectAgainstSpam; use Spatie\Honeypot\ProtectAgainstSpam;
use Spatie\Sheets\Sheet; use Spatie\Sheets\Sheet;
use Illuminate\Http\Request;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@@ -81,4 +82,9 @@ Route::get('/resource/sitemap', static fn () => (new HTMLSitemapController())->i
Route::get(config('app.login_route'), static fn () => redirect('/pulse'))->name('login')->middleware('auth.basic'); Route::get(config('app.login_route'), static fn () => redirect('/pulse'))->name('login')->middleware('auth.basic');
// Streamer Panel // Streamer Panel
Route::get('/streamerpanel', static fn () => (new \App\Http\Controllers\StreamerPanelController())->index())->name('streamers.index')->middleware('auth.basic'); Route::get('/streamerpanel', static fn () => (new \App\Http\Controllers\StreamerPanelController())->index())->name('streamerpanel.index')->middleware('auth.basic');
Route::get('/streamerpanel/add', static fn () => (new \App\Http\Controllers\StreamerPanelController())->create())->name('streamerpanel.streamers.create')->middleware('auth.basic');
Route::post('/streamerpanel/add', static fn (Request $request) => (new \App\Http\Controllers\StreamerPanelController())->store($request))->name('streamerpanel.store')->middleware('auth.basic');
Route::get('/streamerpanel/edit/{streamer}', static fn (\App\Models\Streamer $streamer) => (new \App\Http\Controllers\StreamerPanelController())->edit($streamer))->name('streamerpanel.edit')->middleware('auth.basic');
Route::post('/streamerpanel/edit/{streamer}', static fn (Request $request, \App\Models\Streamer $streamer) => (new \App\Http\Controllers\StreamerPanelController())->update($request, $streamer))->name('streamerpanel.update')->middleware('auth.basic');
Route::delete('/streamerpanel/delete/{streamer}', static fn (\App\Models\Streamer $streamer) => (new \App\Http\Controllers\StreamerPanelController())->destroy($streamer))->name('streamerpanel.destroy')->middleware('auth.basic');