Skip to content

Commit

Permalink
Feature: Admin dashboard item page with pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
Timtendo12 committed Jan 22, 2024
1 parent 7a2fe13 commit 217fe5c
Show file tree
Hide file tree
Showing 13 changed files with 822 additions and 605 deletions.
25 changes: 24 additions & 1 deletion src/app/Http/Controllers/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Enums\ModifiedEnum;
use App\Models\Item;
use Inertia\Inertia;

class AdminController extends Controller
Expand All @@ -29,4 +30,26 @@ public function index()
],
]);
}

public function items() {

$items = Item::where('modified_kind', '!=', ModifiedEnum::deleted)->paginate(10)->through(function ($item) {
return [
'id' => $item->id,
'name' => $item->name,
'description' => $item->description,
'author' => $item->author->name,
'category' => $item->category->category,
'age_rating' => $item->ageRating->rating,
'ISBN' => $item->ISBN,
'modified_kind' => $item->modified_kind,
'modified_user' => $item->modified_user,
'modified_at' => $item->modified_at,
];
});

return Inertia::render('admin/items/index', [
'items' => $items,
]);
}
}
5 changes: 1 addition & 4 deletions src/app/Http/Controllers/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Traits\Imports\OpenLibraryTrait;

class IndexController extends Controller
{
use OpenLibraryTrait;
public function index() {
return Inertia::render('index');
return Inertia::render('index');
}
}
5 changes: 2 additions & 3 deletions src/app/Http/Controllers/ItemController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function store(ItemRequest $request)
'type' => $validated['type'],
'name' => $validated['name'],
'description' => $validated['description'],
'category' => $validated['category'],
'category_id' => $validated['category_id'],
'ISBN' => $validated['ISBN'],
'rating' => $validated['rating'],
'borrowing_time' => $validated['borrowing_time'],
Expand Down Expand Up @@ -69,7 +69,7 @@ public function update(ItemRequest $request, Item $item)
'type' => $validated['type'],
'name' => $validated['name'],
'description' => $validated['description'],
'category' => $validated['category'],
'category_id' => $validated['category_id'],
'ISBN' => $validated['ISBN'],
'rating' => $validated['rating'],
'borrowing_time' => $validated['borrowing_time'],
Expand Down Expand Up @@ -103,7 +103,6 @@ public function search(SearchItemRequest $request) {

$items = Item::where('name', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%")
->orWhere('category', 'like', "%{$search}%")
->orWhere('ISBN', 'like', "%{$search}%")
->get();

Expand Down
17 changes: 15 additions & 2 deletions src/app/Models/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,24 @@

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;

class Item extends Model
{
use HasFactory;
protected $guarded = [];

public function author(): BelongsTo
{
return $this->belongsTo(Author::class);
}

public function category(): BelongsTo {
return $this->belongsTo(ItemCategory::class);
}

public function ageRating(): BelongsTo {
return $this->belongsTo(ItemAgeRating::class, 'rating_id');
}
}
1 change: 0 additions & 1 deletion src/app/Models/ItemAgeRating.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@

class ItemAgeRating extends Model
{
use HasFactory;
protected $guarded = [];
}
4 changes: 2 additions & 2 deletions src/app/Traits/Imports/OpenLibraryTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ private function importBook($book) {
'name' => $book['title'],
'author_id' => $author->id,
'description' => "Dit boek is geschreven door {$authorName} en is uitgegeven in {$book['first_publish_year']}.",
'category' => 1,
'category_id' => 1,
'ISBN' => $book['isbn'][0] ?? "N/A",
'rating' => 1,
'rating_id' => 1,
'borrowing_time' => 30,
'modified_kind' => 'I',
'modified_user' => User::where('email', 'superadmin@biblio.nl')->first()->id,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?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::table('items', function (Blueprint $table) {
// remove category_id column
$table->dropForeign(['category']);
$table->dropColumn('category');

// remove rating column
$table->dropForeign(['rating']);
$table->dropColumn('rating');

// add category_id column
$table->unsignedBigInteger('category_id')->nullable()->after('description');
$table->foreign('category_id')->references('id')->on('item_categories');

// add rating_id column
$table->unsignedBigInteger('rating_id')->nullable()->after('ISBN');
$table->foreign('rating_id')->references('id')->on('item_age_ratings');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('items', function (Blueprint $table) {
$table->renameColumn('category_id', 'category');
});
}
};
3 changes: 2 additions & 1 deletion src/resources/js/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './bootstrap';
import { createApp, h } from 'vue'
import { createPinia } from 'pinia'
import { createInertiaApp } from '@inertiajs/vue3'
import { createInertiaApp, Link } from '@inertiajs/vue3'
import ToastPlugin from "vue-toastification";
import "vue-toastification/dist/index.css";
import '@scss/global.scss';
Expand All @@ -18,6 +18,7 @@ createInertiaApp({
.use(createPinia())
.use(ToastPlugin)
.use(VueApexCharts)
.component('InertiaLink', Link)
.mount(el)
},
})
2 changes: 1 addition & 1 deletion src/resources/vue/components/admin/Siderbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ export default {
display: flex;
flex-direction: row;
align-items: start;
background-color: white;
background-color: #f2f2f2;
}
</style>
67 changes: 67 additions & 0 deletions src/resources/vue/components/admin/pagination.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<template>
<div class="pagination" v-if="links.length > 3">
<div class="flex flex-wrap -mb-1">
<template v-for="(link, key) in links" :key="key">
<div v-if="link.url === null" class="link-wrap" v-html="link.label" />
<InertiaLink v-else :key="key" class="inertia-link" :class="{ 'bg-white': link.active }" :href="link.url" v-html="link.label" />
</template>
</div>
</div>
</template>

<script>
export default {
name: "Pagination",
props: {
links: {
type: Array,
required: true
}
},
}
</script>

<style scoped lang="scss">
.link-wrap {
display: inline-block;
margin-right: 0.25rem;
margin-bottom: 0.25rem;
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
line-height: 1.25rem;
border-radius: 0.25rem;
color: #9ca3af;
}
.inertia-link {
margin-right: 0.25rem;
margin-bottom: 0.25rem;
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
line-height: 1.25rem;
border-radius: 0.25rem;
}
.inertia-link:hover {
background-color: #fff;
color: #1d4ed8;
}
.inertia-link:focus {
outline: 2px solid transparent;
outline-offset: 2px;
box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
}
.pagination {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin-top: 1rem;
margin-bottom: 1rem;
width: 100%;
}
</style>
96 changes: 96 additions & 0 deletions src/resources/vue/pages/admin/items/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<template>
<AdminLayout >
<div class="content">
<div class="header">
<h1>Items</h1>
</div>
<div class="table">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Titel</th>
<th scope="col">Beschrijving</th>
<th scope="col">Auteur</th>
<th scope="col">Categorie</th>
<th scope="col">Leeftijd</th>
<th scope="col">ISBN</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items.data">
<th scope="row">{{item.id}}</th>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.author}}</td>
<td>{{item.category}}</td>
<td>{{item.age_rating}}</td>
<td>{{item.ISBN ?? 'Onbekend'}}</td>
</tr>
</tbody>
</table>
</div>
<Pagination :links="items.links" />
</div>
</AdminLayout>
</template>
<script>
import AdminLayout from "@layouts/admin-layout.vue";
import Pagination from "@components/admin/pagination.vue";
import { computed } from 'vue'
import { usePage } from '@inertiajs/vue3'
export default {
name: "admin-items-index",
components: {
AdminLayout,
Pagination
},
setup() {
const page = usePage();
const items = computed(() => page.props.items);
return {items};
}
}
</script>

<style scoped lang="scss">

.content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding: 50px;
}

.header {
display: flex;
justify-content: flex-start;
width: 100%;
padding-left: 30px;
margin-bottom: 10px;
}

.table {
padding: 0 30px 0 30px;
}

table {
border-collapse: collapse;
border-radius: 1em;
overflow: hidden;
}

tbody:has(tr) {
cursor: pointer;
}

td, th {
max-width: 210px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
</style>
1 change: 1 addition & 0 deletions src/routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
Route::get('/', [IndexController::class, 'index']);

Route::get('/admin', [AdminController::class, 'index']);
Route::get('/admin/items', [AdminController::class, 'items']);

Route::post('/auth', [SessionController::class, 'auth'])->name('auth');
Loading

0 comments on commit 217fe5c

Please sign in to comment.