mirror of
https://github.com/HtetPhone/MangaDex.git
synced 2025-02-20 11:23:19 +08:00
adding genres to the manga
This commit is contained in:
parent
c844ef2ff5
commit
e29ab0cde8
@ -2,9 +2,56 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Genre;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class GenreController extends Controller
|
class GenreController extends Controller
|
||||||
{
|
{
|
||||||
//
|
public function index()
|
||||||
|
{
|
||||||
|
$genres = Genre::latest()->paginate(10)->withQueryString();
|
||||||
|
return view('genres.index', compact('genres'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('genres.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'name' => 'required|min:1|max:255|unique:genres,name'
|
||||||
|
], [
|
||||||
|
'name.required' => 'Genre name is required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request->user()->genres()->create($request->only('name'));
|
||||||
|
return back()->with(['message' => 'New genre has been added!!']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Genre $genre)
|
||||||
|
{
|
||||||
|
return view('genres.edit',['genre' => $genre]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, Genre $genre)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'name' => 'required|min:1|max:255|unique:genres,name,'.$genre->id
|
||||||
|
],[
|
||||||
|
'name.required' => 'Genre field is required!',
|
||||||
|
'name.unique' => 'Genre already exists!'
|
||||||
|
|
||||||
|
]);
|
||||||
|
|
||||||
|
$genre->update(['name' => $request->name]);
|
||||||
|
return redirect()->route('genres.index')->with(['message' => 'Genre has been updated!']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Genre $genre)
|
||||||
|
{
|
||||||
|
$genre->delete();
|
||||||
|
return back()->with(['message' => 'Genre has been deleted']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use App\Http\Requests\StoreMangaRequest;
|
use App\Http\Requests\StoreMangaRequest;
|
||||||
use App\Http\Requests\UpdateMangaRequest;
|
use App\Http\Requests\UpdateMangaRequest;
|
||||||
|
use App\Models\Genre;
|
||||||
use Illuminate\Support\Facades\Request as FacadesRequest;
|
use Illuminate\Support\Facades\Request as FacadesRequest;
|
||||||
|
|
||||||
class MangaController extends Controller
|
class MangaController extends Controller
|
||||||
@ -32,7 +33,8 @@ class MangaController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
return view('manga.create');
|
$genres = Genre::latest('id')->get();
|
||||||
|
return view('manga.create', ['genres' => $genres]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,9 +49,14 @@ class MangaController extends Controller
|
|||||||
if ($request->hasFile('cover')) {
|
if ($request->hasFile('cover')) {
|
||||||
$formData['cover'] = $request->file('cover')->store('covers', 'public');
|
$formData['cover'] = $request->file('cover')->store('covers', 'public');
|
||||||
}
|
}
|
||||||
|
|
||||||
Manga::create($formData);
|
Manga::create($formData);
|
||||||
|
//genres
|
||||||
|
$genres = [];
|
||||||
|
foreach ($request->genres as $genre) {
|
||||||
|
$genres[] = $genre;
|
||||||
|
}
|
||||||
|
$manga = Manga::latest()->first();
|
||||||
|
$manga->genres()->attach($genres);
|
||||||
return redirect()->route('manga.index')->with(['message' => 'A New Manga is created']);
|
return redirect()->route('manga.index')->with(['message' => 'A New Manga is created']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +75,7 @@ class MangaController extends Controller
|
|||||||
public function edit(Manga $manga)
|
public function edit(Manga $manga)
|
||||||
{
|
{
|
||||||
$this->authorize('update', $manga);
|
$this->authorize('update', $manga);
|
||||||
|
// dd($manga->genres->contains('id','1'));
|
||||||
return view('manga.edit', compact('manga'));
|
return view('manga.edit', compact('manga'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,8 +92,15 @@ class MangaController extends Controller
|
|||||||
if ($request->hasFile('cover')) {
|
if ($request->hasFile('cover')) {
|
||||||
$formData['cover'] = $request->file('cover')->store('covers', 'public');
|
$formData['cover'] = $request->file('cover')->store('covers', 'public');
|
||||||
}
|
}
|
||||||
|
|
||||||
$manga->update($formData);
|
$manga->update($formData);
|
||||||
|
//adding data to medium table for many to many rs
|
||||||
|
if ($request->genres) {
|
||||||
|
$genres = [];
|
||||||
|
foreach ($request->genres as $genre) {
|
||||||
|
$genres[] = $genre;
|
||||||
|
}
|
||||||
|
$manga->genres()->sync($genres);
|
||||||
|
}
|
||||||
return redirect()->back()->with(['message' => 'Manga has been updated!']);
|
return redirect()->back()->with(['message' => 'Manga has been updated!']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,5 +114,4 @@ class MangaController extends Controller
|
|||||||
$manga->delete();
|
$manga->delete();
|
||||||
return redirect()->back()->with(['message' => 'Manga has been deleted!']);
|
return redirect()->back()->with(['message' => 'Manga has been deleted!']);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,35 +29,21 @@ class PageController extends Controller
|
|||||||
$chapters = $manga->chapters()
|
$chapters = $manga->chapters()
|
||||||
->latest('chapter_no')
|
->latest('chapter_no')
|
||||||
->paginate(10);
|
->paginate(10);
|
||||||
$firstChapter = $manga->chapters()
|
|
||||||
->orderBy('chapter_no', 'asc')->first();
|
|
||||||
$lastChapter = $manga->chapters()
|
|
||||||
->latest('chapter_no')
|
|
||||||
->first();
|
|
||||||
$hotMangas = Manga::with(['chapters'])
|
$hotMangas = Manga::with(['chapters'])
|
||||||
->latest('id')->limit('3')->get();
|
->latest('id')->limit('3')->get();
|
||||||
return view('manga',[
|
return view('manga',[
|
||||||
'manga' => $manga,
|
'manga' => $manga,
|
||||||
'hotMangas' => $hotMangas,
|
|
||||||
'chapters' => $chapters,
|
'chapters' => $chapters,
|
||||||
'firstChapter' => $firstChapter,
|
'hotMangas' => $hotMangas,
|
||||||
'lastChapter' => $lastChapter
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function chapter(Manga $manga,Chapter $chapter)
|
public function chapter(Manga $manga,Chapter $chapter)
|
||||||
{
|
{
|
||||||
$firstChapter = $manga->chapters()
|
|
||||||
->orderBy('chapter_no', 'asc')
|
|
||||||
->first();
|
|
||||||
$lastChapter = $manga->chapters()
|
|
||||||
->latest('chapter_no')
|
|
||||||
->first();
|
|
||||||
return view('chapter_page', [
|
return view('chapter_page', [
|
||||||
'chapter' => $chapter,
|
|
||||||
'manga' => $manga,
|
'manga' => $manga,
|
||||||
'firstChapter' => $firstChapter,
|
'chapter' => $chapter,
|
||||||
'lastChapter' => $lastChapter
|
'comments' => $chapter->comments()->latest('id')->get()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class AdminAccess
|
|||||||
{
|
{
|
||||||
//prevent normal users form accessing admin dashboard
|
//prevent normal users form accessing admin dashboard
|
||||||
if(Auth::user()) {
|
if(Auth::user()) {
|
||||||
if(Auth::user()->role == "user") {
|
if(Auth::user()->role === "user") {
|
||||||
return redirect()->route('page.index')->with(['message' => 'You are not an admin!!']);
|
return redirect()->route('page.index')->with(['message' => 'You are not an admin!!']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@ class StoreMangaRequest extends FormRequest
|
|||||||
return [
|
return [
|
||||||
'title' => 'required|min:3|max:100',
|
'title' => 'required|min:3|max:100',
|
||||||
'summary' => 'required|min:3',
|
'summary' => 'required|min:3',
|
||||||
'cover' => 'file|required|mimes:png,jpg'
|
'cover' => 'file|required|mimes:png,jpg',
|
||||||
|
'genres' => 'required'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ class StoreMangaRequest extends FormRequest
|
|||||||
public function messages()
|
public function messages()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'cover.required' => 'Please Select Cover Image'
|
'cover.required' => 'Please Select Cover Image',
|
||||||
|
'genres.required' => 'A single genre is requied at least'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@ class UpdateMangaRequest extends FormRequest
|
|||||||
return [
|
return [
|
||||||
'title' => 'required|min:3',
|
'title' => 'required|min:3',
|
||||||
'summary' => 'required|min:3|max:2000',
|
'summary' => 'required|min:3|max:2000',
|
||||||
'cover' => 'file|required|mimes:png,jpg'
|
'cover' => 'file|mimes:png,jpg',
|
||||||
|
'genres' => 'required'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ class UpdateMangaRequest extends FormRequest
|
|||||||
public function messages()
|
public function messages()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'cover.required' => 'Please Select Cover Image'
|
'cover.required' => 'Please Select Cover Image',
|
||||||
|
'genres.required' => 'A single genre is requied at least'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,4 +8,12 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
class Genre extends Model
|
class Genre extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = ['name', 'user_id'];
|
||||||
|
|
||||||
|
public function manga()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Manga::class);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ class Manga extends Model
|
|||||||
|
|
||||||
protected $fillable = ['title', 'slug', 'summary', 'excerpt', 'cover', 'author_id'];
|
protected $fillable = ['title', 'slug', 'summary', 'excerpt', 'cover', 'author_id'];
|
||||||
|
|
||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class, 'author_id');
|
return $this->belongsTo(User::class, 'author_id');
|
||||||
@ -21,4 +20,24 @@ class Manga extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(Chapter::class);
|
return $this->hasMany(Chapter::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//latest and oldest chapter
|
||||||
|
// public function latestChap()
|
||||||
|
// {
|
||||||
|
// return $this->chapters()->one()->latestOfMany();
|
||||||
|
// }
|
||||||
|
public function lastChap()
|
||||||
|
{
|
||||||
|
return $this->chapters()->one()->ofMany('chapter_no', 'max');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function firstChap()
|
||||||
|
{
|
||||||
|
return $this->chapters()->one()->ofMany('chapter_no', 'min');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function genres()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Genre::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,4 +57,9 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
return $this->hasMany(Reply::class);
|
return $this->hasMany(Reply::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function genres()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Genre::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('genre_manga', function (Blueprint $table) {
|
||||||
|
$table->foreignId('genre_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('manga_id')->constrained()->cascadeOnDelete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('genre_manga');
|
||||||
|
}
|
||||||
|
};
|
@ -1,6 +1,7 @@
|
|||||||
@props(['manga', 'chapters', 'firstChapter', 'lastChapter'])
|
@props(['manga', 'chapters'])
|
||||||
<div>
|
<div>
|
||||||
<h5 class="fw-semibold my-3 text-primary"> <i class="bi bi-award-fill"></i> {{ $manga->title }}</h5>
|
<h5 class="fw-semibold my-3 text-primary"> <i class="bi bi-award-fill"></i> {{ $manga->title }}</h5>
|
||||||
|
|
||||||
<div class="row my-3">
|
<div class="row my-3">
|
||||||
<div class="col-12 col-md-4">
|
<div class="col-12 col-md-4">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
@ -9,25 +10,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-7">
|
<div class="col-12 col-md-7">
|
||||||
<p> <span class="fw-semibold">Author</span> - {{ $manga->user->name }} </p>
|
<p> <span class="fw-semibold">Author</span> - {{ $manga->user->name }} </p>
|
||||||
<p> <span class="fw-semibold">Genre</span> - </p>
|
<p>
|
||||||
|
<span class="fw-semibold">Genre</span> -
|
||||||
|
@foreach ($manga->genres as $genre)
|
||||||
|
<span class="text-primary"> {{$genre->name}} </span> /
|
||||||
|
@endforeach
|
||||||
|
</p>
|
||||||
<p class="d-flex">
|
<p class="d-flex">
|
||||||
<a href="{{ route('page.chapter', [$manga->slug, $firstChapter->chapter_no]) }}" class="btn btn-primary me-1">Read First</a>
|
<a href="{{ route('page.chapter', [$manga, $manga->firstChap]) }}" class="btn btn-primary me-1">Read First</a>
|
||||||
<a href="{{ route('page.chapter', [$manga->slug, $lastChapter->chapter_no]) }}" class="btn btn-primary">Read Last</a>
|
<a href="{{ route('page.chapter', [$manga, $manga->lastChap]) }}" class="btn btn-primary">Read Last</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<h5 class="fw-semibold text-primary"> <i class="bi bi-award-fill"></i> Summary </h5>
|
<h5 class="fw-semibold text-primary"> <i class="bi bi-award-fill"></i> Summary </h5>
|
||||||
<hr>
|
<hr>
|
||||||
<p class="text-black-50"> {{ $manga->summary }} </p>
|
<p class="text-black-50"> {{ $manga->summary }} </p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="list-group my-3 mt-5 mx-auto">
|
<ul class="list-group my-3 mt-5 mx-auto">
|
||||||
<h5 class="w-semibold text-primary">
|
<h5 class="w-semibold text-primary">
|
||||||
<i class="bi bi-award-fill"></i> Latest Chapter Release
|
<i class="bi bi-award-fill"></i> Latest Chapter Release
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
@forelse ($chapters as $chapter)
|
@forelse ($chapters as $chapter)
|
||||||
<a href="{{ route('page.chapter', [$manga->slug, $chapter->chapter_no]) }}"
|
<a href="{{ route('page.chapter', [$manga, $chapter]) }}"
|
||||||
class="list-group-item list-group-item-action pb-0 border-0 border-bottom
|
class="list-group-item list-group-item-action pb-0 border-0 border-bottom
|
||||||
d-inline-block d-flex align-items-center justify-content-between">
|
d-inline-block d-flex align-items-center justify-content-between">
|
||||||
<p> Chapter {{ $chapter->chapter_no }} - {{ $chapter->title ?? '' }} </p>
|
<p> Chapter {{ $chapter->chapter_no }} - {{ $chapter->title ?? '' }} </p>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@props(['manga', 'chapter'])
|
@props(['manga', 'chapter'])
|
||||||
|
|
||||||
<div class="d-flex justify-content-between flex-wrap mb-2">
|
<div class="d-flex justify-content-between flex-wrap mb-2">
|
||||||
<a href="{{ route('page.chapter', [$manga->slug, $chapter->chapter_no]) }}"
|
<a href="{{ route('page.chapter', [$manga, $chapter]) }}"
|
||||||
class="text-decoration-none text-white small bg-secondary rounded-pill px-1">
|
class="text-decoration-none text-white small bg-secondary rounded-pill px-1">
|
||||||
Chapter {{ $chapter->chapter_no }}
|
Chapter {{ $chapter->chapter_no }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
@props(['mangas'])
|
@props(['mangas'])
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
<h5>Manga List</h5>
|
<h5>Manga List</h5>
|
||||||
|
<a href="{{route('manga.create')}}" class="btn btn-sm btn-dark ms-auto"><i class="bi bi-plus-circle"></i> Create Manga</a>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-striped">
|
<table class="table table-hover table-striped">
|
||||||
@ -8,7 +11,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="col">#</th>
|
<th scope="col">#</th>
|
||||||
<th scope="col" style="min-width: 20%">Title</th>
|
<th scope="col" style="min-width: 20%">Title</th>
|
||||||
<th>Author</th>
|
<th>Genre</th>
|
||||||
|
<th>Author/Creator</th>
|
||||||
<th scope="col">Total Chapters</th>
|
<th scope="col">Total Chapters</th>
|
||||||
<th scope="col">Handle</th>
|
<th scope="col">Handle</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -21,6 +25,11 @@
|
|||||||
<p class="mb-0">{{ $manga->title }}</p>
|
<p class="mb-0">{{ $manga->title }}</p>
|
||||||
<span class="small text-black-50">{{ $manga->excerpt }}</span>
|
<span class="small text-black-50">{{ $manga->excerpt }}</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
@foreach ($manga->genres as $genre)
|
||||||
|
<span class="small">{{$genre->name}} </span> /
|
||||||
|
@endforeach
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ $manga->user->name }}
|
{{ $manga->user->name }}
|
||||||
</td>
|
</td>
|
||||||
@ -52,7 +61,6 @@
|
|||||||
action="{{ route('manga.destroy', $manga->id) }}" class="d-inline-block">
|
action="{{ route('manga.destroy', $manga->id) }}" class="d-inline-block">
|
||||||
@csrf
|
@csrf
|
||||||
@method('delete')
|
@method('delete')
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
17
resources/views/genres/create.blade.php
Normal file
17
resources/views/genres/create.blade.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
<x-card-card-body>
|
||||||
|
<form method="POST" action="{{ route('genres.create') }}" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="">Genre Name</label>
|
||||||
|
<input type="text" name="name" class="form-control">
|
||||||
|
@error('name')
|
||||||
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-outline-dark">Create</button>
|
||||||
|
</form>
|
||||||
|
</x-card-card-body>
|
||||||
|
@endsection
|
20
resources/views/genres/edit.blade.php
Normal file
20
resources/views/genres/edit.blade.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
<x-card-card-body>
|
||||||
|
<h5 class="text-primary"> <i class="bi bi-pencil-square"></i> Edit Genre </h5>
|
||||||
|
<hr>
|
||||||
|
<form method="POST" action="{{ route('genres.update', $genre) }}" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="">Genre Name</label>
|
||||||
|
<input type="text" name="name" class="form-control" value="{{old('name', $genre->name)}}">
|
||||||
|
@error('name')
|
||||||
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-outline-dark">Update</button>
|
||||||
|
</form>
|
||||||
|
</x-card-card-body>
|
||||||
|
@endsection
|
61
resources/views/genres/index.blade.php
Normal file
61
resources/views/genres/index.blade.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<x-card-card-body>
|
||||||
|
<h5>Genres List</h5>
|
||||||
|
<hr>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">#</th>
|
||||||
|
<th scope="col" style="min-width: 20%">Genre Name</th>
|
||||||
|
<th scope="col">Created_at</th>
|
||||||
|
<th>Option</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@forelse ($genres as $key => $genre)
|
||||||
|
<tr>
|
||||||
|
<td> {{ $key }} </td>
|
||||||
|
<td> {{ $genre->name }} </td>
|
||||||
|
<td>
|
||||||
|
<p class="mb-0 small"> <i class="bi bi-clock-history"></i>
|
||||||
|
{{ $genre->created_at->format('H:i a') }} </p>
|
||||||
|
<p class="mb-0 small"> <i class="bi bi-calendar-check"></i>
|
||||||
|
{{ $genre->created_at->format('d-m-Y') }} </p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a href="{{route('genres.edit', $genre)}}" class="btn text-info"> <i class="bi bi-pencil-square"></i> </a>
|
||||||
|
<form method="POST" action="{{route('genres.destroy', $genre)}}" class="form-inline">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button onclick="return confirm('Are you sure to delete?')" class="btn text-danger"><i class="bi bi-trash"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<p class="text-danger fw-semibold mb-0 me-3">No genre Yet</p>
|
||||||
|
<a href="{{ route('genres.create') }}" class="btn btn-dark btn-sm">
|
||||||
|
<i class="bi bi-plus-circle"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ $genres->links() }}
|
||||||
|
</div>
|
||||||
|
</x-card-card-body>
|
||||||
|
@endsection
|
@ -93,6 +93,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@include('components.footer')
|
||||||
|
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<div class="row mt-5">
|
<div class="row mt-5">
|
||||||
<div class="col-12 col-md-9">
|
<div class="col-12 col-md-9">
|
||||||
<x-inner-manga :manga="$manga" :chapters="$chapters" :firstChapter="$firstChapter" :lastChapter="$lastChapter" />
|
<x-inner-manga :manga="$manga" :chapters="$chapters" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 col-md-3">
|
<div class="col-12 col-md-3">
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
@csrf
|
@csrf
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="">Manga Title</label>
|
<label for="">Manga Title</label>
|
||||||
<input type="text" name="title" class="form-control">
|
<input type="text" name="title" class="form-control" value="{{old('title')}}">
|
||||||
@error('title')
|
@error('title')
|
||||||
<p class="text-danger small">{{ $message }}</p>
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
@enderror
|
@enderror
|
||||||
@ -17,11 +17,24 @@
|
|||||||
<p class="text-danger small">{{ $message }}</p>
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="d-block" for="">Genres</label>
|
||||||
|
@forelse ($genres as $genre)
|
||||||
|
<span class="me-2">
|
||||||
|
<input class="" type="checkbox" name="genres[]" value="{{$genre->id}}" id="{{ $genre->id }}">
|
||||||
|
<label for="{{ $genre->id }}"> {{ $genre->name }}</label>
|
||||||
|
</span>
|
||||||
|
@empty
|
||||||
|
@endforelse
|
||||||
|
@error('genres')
|
||||||
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="">Manga Summary</label>
|
<label for="">Manga Summary</label>
|
||||||
<textarea name="summary" id="" cols="30" rows="6" class="form-control p-3"
|
<textarea name="summary" id="" cols="30" rows="6" class="form-control p-3"
|
||||||
placeholder="Write A Summary">
|
placeholder="Write A Summary">
|
||||||
|
{{old('summary')}}
|
||||||
</textarea>
|
</textarea>
|
||||||
@error('summary')
|
@error('summary')
|
||||||
<p class="text-danger small">{{ $message }}</p>
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
@ -31,3 +44,4 @@
|
|||||||
</form>
|
</form>
|
||||||
</x-card-card-body>
|
</x-card-card-body>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@ -2,12 +2,19 @@
|
|||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="px-3 mb-4">
|
<div class="px-3 mb-4">
|
||||||
<a href="{{ url()->previous() }}" class="btn btn-dark">Back</a>
|
<a href="{{ route('manga.index') }}" class="btn btn-dark"> <i class="bi bi-house"></i> Home</a>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="">
|
<div class="">
|
||||||
<h3 class="my-3"> Title : <span class="fw-semibold ">{{ $manga->title }}</span> </h3>
|
<h3 class="my-3"> Title : <span class="fw-semibold ">{{ $manga->title }}</span> </h3>
|
||||||
<hr>
|
<hr>
|
||||||
<p class="f">Cover Image :</p>
|
<p>
|
||||||
|
Genres :
|
||||||
|
@foreach ($manga->genres as $genre)
|
||||||
|
<span class="small text-primary fw-semibold"> {{$genre->name}} </span> /
|
||||||
|
@endforeach
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p class="">Cover Image :</p>
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
<img class="w-25" src="{{ asset('storage/'.$manga->cover) }}" alt="">
|
<img class="w-25" src="{{ asset('storage/'.$manga->cover) }}" alt="">
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<a href="{{ route('manga.index') }}" class="btn btn-dark"> <i class="bi bi-house-heart-fill"></i> Home</a>
|
<a href="{{ route('manga.index') }}" class="btn btn-dark"> <i class="bi bi-house-heart-fill"></i> Home</a>
|
||||||
<hr>
|
<hr>
|
||||||
|
<h5 class="fw-semibold">Editing Manga</h5>
|
||||||
|
<hr>
|
||||||
<form method="POST" action="{{ route('manga.update', $manga->id) }}" enctype="multipart/form-data">
|
<form method="POST" action="{{ route('manga.update', $manga->id) }}" enctype="multipart/form-data">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
@ -14,10 +16,28 @@
|
|||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="">Manga Cover</label>
|
<label>Genres</label>
|
||||||
<img src="{{ $manga->cover ? asset($manga->cover) : null }}" class="w-50 d-block my-3" alt="">
|
<div>
|
||||||
<input type="file" name="cover" id="" class="form-control">
|
@foreach (App\Models\Genre::all() as $genre)
|
||||||
|
<input type="checkbox" name="genres[]" id="{{ $genre->id }}" value="{{ $genre->id }}"
|
||||||
|
{{ $manga->genres->contains('id', $genre->id) ? 'checked' : '' }}>
|
||||||
|
<label for="{{ $genre->id }}"> {{ $genre->name }} </label>
|
||||||
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@error('genres')
|
||||||
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="">Manga Cover</label>
|
||||||
|
<img src="{{ asset('storage/' . $manga->cover) }}" class="img-fluid d-block my-3" alt="">
|
||||||
|
<input type="file" name="cover" id="" class="form-control">
|
||||||
|
@error('cover')
|
||||||
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="">Manga Summary</label>
|
<label for="">Manga Summary</label>
|
||||||
<textarea name="summary" id="" cols="30" rows="6" class="form-control p-3"
|
<textarea name="summary" id="" cols="30" rows="6" class="form-control p-3"
|
||||||
@ -28,8 +48,12 @@
|
|||||||
<p class="text-danger small">{{ $message }}</p>
|
<p class="text-danger small">{{ $message }}</p>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-outline-dark">Update</button>
|
<button type="submit" class="btn btn-outline-dark">Update</button>
|
||||||
</form>
|
</form>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
|
||||||
|
{{-- @section('footer')
|
||||||
|
@include('components.footer')
|
||||||
|
@endsection --}}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
<div>
|
<div>
|
||||||
<a
|
<a
|
||||||
href="{{ route('page.chapter', [$manga->slug, $chapter->chapter_no - 1 ]) }}"
|
href="{{ route('page.chapter', [$manga, $chapter->chapter_no - 1 ]) }}"
|
||||||
class="btn btn-{{$chapter->chapter_no == $firstChapter->chapter_no ? 'secondary' : 'dark' }} btn-small {"
|
class="btn btn-{{$chapter->chapter_no == $manga->firstChap->chapter_no ? 'secondary' : 'dark' }} btn-small {"
|
||||||
style="pointer-events: {{ $chapter->chapter_no == $firstChapter->chapter_no ? 'none' : '' }}">
|
style="pointer-events: {{ $chapter->chapter_no == $manga->firstChap->chapter_no ? 'none' : '' }}">
|
||||||
Previous
|
Previous
|
||||||
</a>
|
</a>
|
||||||
{{-- <p> {{ }} </p> --}}
|
|
||||||
<a
|
<a
|
||||||
href="{{ route('page.chapter', [$manga->slug, $chapter->chapter_no + 1 ]) }}"
|
href="{{ route('page.chapter', [$manga, $chapter->chapter_no + 1 ]) }}"
|
||||||
class="btn btn-{{ $chapter->chapter_no == $lastChapter->chapter_no ? 'secondary' : 'dark' }} btn-small"
|
class="btn btn-{{ $chapter->chapter_no == $manga->lastChap->chapter_no ? 'secondary' : 'dark' }} btn-small"
|
||||||
style="pointer-events: {{ $chapter->chapter_no == $lastChapter->chapter_no ? 'none' : '' }}">
|
style="pointer-events: {{ $chapter->chapter_no == $manga->lastChap->chapter_no ? 'none' : '' }}">
|
||||||
Next
|
Next
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<form action="{{route('select.chapter', [$manga->slug])}}" method="post" id="selectChapter" onchange="this.submit();">
|
<form action="{{route('select.chapter', $manga)}}" method="post" id="selectChapter" onchange="this.submit();">
|
||||||
@csrf
|
@csrf
|
||||||
<select name="chapter_no" class="form-select">
|
<select name="chapter_no" class="form-select">
|
||||||
@foreach ($manga->chapters()->latest('chapter_no')->get() as $chap)
|
@foreach ($manga->chapters()->latest('chapter_no')->get() as $chap)
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
<!-- comment outputs here -->
|
<!-- comment outputs here -->
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
@forelse ($chapter->comments()->latest()->get() as $comment)
|
@forelse ($comments as $comment)
|
||||||
<div class="mb-4 border-bottom">
|
<div class="mb-4 border-bottom">
|
||||||
<p class="mb-1">
|
<p class="mb-1">
|
||||||
<span class="fw-bold text-primary"> <i class="bi bi-person-fill"></i> {{ $comment->user->name }}</span>
|
<span class="fw-bold text-primary"> <i class="bi bi-person-fill"></i> {{ $comment->user->name }}</span>
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
@forelse ($hotMangas as $hotManga)
|
@forelse ($hotMangas as $hotManga)
|
||||||
<div class="row border-0 flex-wrap my-3 mb-4">
|
<div class="row border-0 flex-wrap my-3 mb-4">
|
||||||
<div class="overflow-hidden col-3 col-lg-4">
|
<div class="overflow-hidden col-3 col-lg-4">
|
||||||
<a href="{{ route('page.manga', $hotManga->slug) }}">
|
<a href="{{ route('page.manga', $hotManga) }}">
|
||||||
<img src="{{ asset('storage/' . $hotManga->cover) }}" alt="img" class="cover-img img-fluid">
|
<img src="{{ asset('storage/' . $hotManga->cover) }}" alt="img" class="cover-img img-fluid">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-5 col-lg-8">
|
<div class="col-5 col-lg-8">
|
||||||
<a href="{{ route('page.manga', $hotManga->slug) }}" class="text-decoration-none">
|
<a href="{{ route('page.manga', $hotManga) }}" class="text-decoration-none">
|
||||||
<p class="fw-semibold mb-1"> {{ $hotManga->title }} </p>
|
<p class="fw-semibold mb-1"> {{ $hotManga->title }} </p>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -1,22 +1,36 @@
|
|||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<h5>
|
<h5>
|
||||||
<a href="{{ route('home') }}" class="list-group-item list-group-item-action text-primary"><i class="bi bi-speedometer2"></i> Dashboard </a>
|
<a href="{{ route('home') }}" class="list-group-item list-group-item-action text-primary">
|
||||||
|
<i class="bi bi-speedometer2"></i> Dashboard
|
||||||
|
</a>
|
||||||
</h5>
|
</h5>
|
||||||
<h5>Manga</h5>
|
<h5>Manga</h5>
|
||||||
<a href="{{ route('manga.index') }}" class="list-group-item list-group-item-action"><i class="bi bi-book"></i> Manga
|
<a href="{{ route('manga.index') }}" class="list-group-item list-group-item-action">
|
||||||
List </a>
|
<i class="bi bi-book"></i> Manga List
|
||||||
<a href="{{ route('manga.create') }}" class="list-group-item list-group-item-action"><i
|
</a>
|
||||||
class="bi bi-plus-circle-fill"></i> Create Manga</a>
|
<a href="{{ route('manga.create') }}" class="list-group-item list-group-item-action">
|
||||||
|
<i class="bi bi-plus-circle-fill"></i> Create Manga
|
||||||
|
</a>
|
||||||
|
|
||||||
<h5 class="mt-4">Chapters</h5>
|
<h5 class="mt-4">Chapters</h5>
|
||||||
<a href=" {{ route('chapter.index') }} " class="list-group-item list-group-item-action"><i class="bi bi-book"></i>
|
<a href=" {{ route('chapter.index') }} " class="list-group-item list-group-item-action">
|
||||||
Chapter List </a>
|
<i class="bi bi-book"></i> Chapter List
|
||||||
<a href="{{ route('chapter.create') }}" class="list-group-item list-group-item-action"><i
|
</a>
|
||||||
class="bi bi-plus-circle-fill"></i> Create Chapter</a>
|
<a href="{{ route('chapter.create') }}" class="list-group-item list-group-item-action">
|
||||||
|
<i class="bi bi-plus-circle-fill"></i> Create Chapter
|
||||||
|
</a>
|
||||||
|
|
||||||
@can('admin-only')
|
@can('admin-only')
|
||||||
|
<h5 class="mt-4">Genres</h5>
|
||||||
|
<a href="{{ route('genres.index') }}" class="list-group-item list-group-item-action">
|
||||||
|
<i class="bi bi-tags-fill"></i> Genres List
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('genres.create') }}" class="list-group-item list-group-item-action">
|
||||||
|
<i class="bi bi-plus-circle-fill"></i> Create Genre
|
||||||
|
</a>
|
||||||
<h5 class="mt-4">Users</h5>
|
<h5 class="mt-4">Users</h5>
|
||||||
<a href="{{ route('users.list') }}" class="list-group-item list-group-item-action"> <i class="bi bi-people"></i>
|
<a href="{{ route('users.list') }}" class="list-group-item list-group-item-action">
|
||||||
Users List</a>
|
<i class="bi bi-people"></i> Users List
|
||||||
|
</a>
|
||||||
@endcan
|
@endcan
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -31,7 +31,13 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<p class="text-danger">No User Yet</p>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<p class="text-danger fw-semibold mb-0">No User Yet</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -10,6 +10,7 @@ use App\Http\Controllers\MangaController;
|
|||||||
use App\Http\Controllers\ReplyController;
|
use App\Http\Controllers\ReplyController;
|
||||||
use App\Http\Controllers\ChapterController;
|
use App\Http\Controllers\ChapterController;
|
||||||
use App\Http\Controllers\CommentController;
|
use App\Http\Controllers\CommentController;
|
||||||
|
use App\Http\Controllers\GenreController;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
@ -30,14 +31,18 @@ Route::controller(PageController::class)->group(function () {
|
|||||||
Route::post('/{manga:slug}/chapter', 'select')->name('select.chapter');
|
Route::post('/{manga:slug}/chapter', 'select')->name('select.chapter');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//comment and reply
|
||||||
Route::resource('comments', CommentController::class)->middleware('auth');
|
Route::resource('comments', CommentController::class)->middleware('auth');
|
||||||
Route::resource('replies', ReplyController::class)->middleware('auth');
|
Route::resource('replies', ReplyController::class)->middleware('auth');
|
||||||
|
|
||||||
|
//auth
|
||||||
Auth::routes();
|
Auth::routes();
|
||||||
|
|
||||||
|
//home
|
||||||
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])
|
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])
|
||||||
->name('home');
|
->name('home');
|
||||||
|
|
||||||
|
//admin dashboard
|
||||||
Route::middleware(['auth', 'admin.access'])->group(function () {
|
Route::middleware(['auth', 'admin.access'])->group(function () {
|
||||||
Route::resource('manga', MangaController::class);
|
Route::resource('manga', MangaController::class);
|
||||||
|
|
||||||
@ -47,5 +52,13 @@ Route::middleware(['auth', 'admin.access'])->group(function () {
|
|||||||
->name('chapters.manage');
|
->name('chapters.manage');
|
||||||
|
|
||||||
Route::get('/users-list', [UserController::class, 'index'])->name('users.list')->middleware('can:admin-only');
|
Route::get('/users-list', [UserController::class, 'index'])->name('users.list')->middleware('can:admin-only');
|
||||||
});
|
|
||||||
|
|
||||||
|
Route::controller(GenreController::class)->group(function () {
|
||||||
|
Route::get('/genres', 'index')->name('genres.index');
|
||||||
|
Route::get('/genres/create', 'create')->name('genres.create');
|
||||||
|
Route::post('/genres/create', 'store');
|
||||||
|
Route::get('/genres/{genre:name}/edit', 'edit')->name('genres.edit');
|
||||||
|
Route::put('/genres/{genre:id}', 'update')->name('genres.update');
|
||||||
|
Route::delete('/genres/{genre:name}', 'destroy')->name('genres.destroy');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user