From 967cad330921a0f857bf28c0497de84d7b04fd80 Mon Sep 17 00:00:00 2001 From: Kamil Date: Sat, 23 Sep 2023 09:47:28 +0200 Subject: [PATCH] #8 - semester crud --- .env.ci | 1 - app/Enums/SemesterStatus.php | 19 ++++++ .../Dashboard/SemesterController.php | 62 ++++++++++++++++++ app/Http/Requests/SemesterRequest.php | 17 +++++ app/Http/Resources/SemesterResource.php | 24 +++++++ app/Models/Semester.php | 32 ++++++++++ app/Models/Student.php | 9 +++ app/Models/User.php | 6 ++ database/factories/SemesterFactory.php | 17 +++++ ...23_09_23_075139_create_semesters_table.php | 24 +++++++ resources/js/Layouts/DashboardLayout.vue | 2 +- .../js/Pages/Dashboard/Semester/Create.vue | 48 ++++++++++++++ .../js/Pages/Dashboard/Semester/Edit.vue | 52 +++++++++++++++ .../js/Pages/Dashboard/Semester/Index.vue | 63 ++++++++++++++++++ routes/web.php | 9 +++ tests/Feature/SemesterTest.php | 64 +++++++++++++++++++ tests/Feature/StudentTest.php | 2 +- 17 files changed, 448 insertions(+), 3 deletions(-) create mode 100644 app/Enums/SemesterStatus.php create mode 100644 app/Http/Controllers/Dashboard/SemesterController.php create mode 100644 app/Http/Requests/SemesterRequest.php create mode 100644 app/Http/Resources/SemesterResource.php create mode 100644 app/Models/Semester.php create mode 100644 database/factories/SemesterFactory.php create mode 100644 database/migrations/2023_09_23_075139_create_semesters_table.php create mode 100644 resources/js/Pages/Dashboard/Semester/Create.vue create mode 100644 resources/js/Pages/Dashboard/Semester/Edit.vue create mode 100644 resources/js/Pages/Dashboard/Semester/Index.vue create mode 100644 tests/Feature/SemesterTest.php diff --git a/.env.ci b/.env.ci index c590d6f..849585b 100644 --- a/.env.ci +++ b/.env.ci @@ -21,4 +21,3 @@ DB_PORT=5432 DB_DATABASE=keating DB_USERNAME=keating DB_PASSWORD=password -DB_ROOT_PASSWORD=example diff --git a/app/Enums/SemesterStatus.php b/app/Enums/SemesterStatus.php new file mode 100644 index 0000000..26e7462 --- /dev/null +++ b/app/Enums/SemesterStatus.php @@ -0,0 +1,19 @@ +value) { + "active" => "aktywny", + "inactive" => "nieaktywny", + }; + } +} diff --git a/app/Http/Controllers/Dashboard/SemesterController.php b/app/Http/Controllers/Dashboard/SemesterController.php new file mode 100644 index 0000000..d6c3f78 --- /dev/null +++ b/app/Http/Controllers/Dashboard/SemesterController.php @@ -0,0 +1,62 @@ + SemesterResource::collection($semesters), + ]); + } + + public function create(): Response + { + return inertia("Dashboard/Semester/Create"); + } + + public function store(SemesterRequest $request): RedirectResponse + { + Semester::query()->create($request->validated()); + + return redirect() + ->route("semesters.index") + ->with("success", "Dodano semestr"); + } + + public function edit(Semester $semester): Response + { + return inertia("Dashboard/Semester/Edit", [ + "semester" => $semester, + ]); + } + + public function update(SemesterRequest $request, Semester $semester): RedirectResponse + { + $semester->update($request->validated()); + + return redirect() + ->route("semesters.index") + ->with("success", "Zaktualizowano semestr"); + } + + public function destroy(Semester $semester): RedirectResponse + { + $semester->delete(); + + return redirect()->back() + ->with("success", "Usunięto semestr"); + } +} diff --git a/app/Http/Requests/SemesterRequest.php b/app/Http/Requests/SemesterRequest.php new file mode 100644 index 0000000..9848c9f --- /dev/null +++ b/app/Http/Requests/SemesterRequest.php @@ -0,0 +1,17 @@ + ["required", "max:255"], + ]; + } +} diff --git a/app/Http/Resources/SemesterResource.php b/app/Http/Resources/SemesterResource.php new file mode 100644 index 0000000..c3d12d7 --- /dev/null +++ b/app/Http/Resources/SemesterResource.php @@ -0,0 +1,24 @@ + $semester->name, + "status" => $semester->status, + "status_label" => $semester->status->getLabel(), + ]; + } +} diff --git a/app/Models/Semester.php b/app/Models/Semester.php new file mode 100644 index 0000000..7e3eccd --- /dev/null +++ b/app/Models/Semester.php @@ -0,0 +1,32 @@ + SemesterStatus::class, + ]; +} diff --git a/app/Models/Student.php b/app/Models/Student.php index 004e4f3..a40f402 100644 --- a/app/Models/Student.php +++ b/app/Models/Student.php @@ -4,10 +4,19 @@ namespace App\Models; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Concerns\HasUlids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +/** + * @property string $id + * @property string $name + * @property string $surname + * @property string $index_number + * @property Carbon $created_at + * @property Carbon $updated_at + */ class Student extends Model { use HasFactory; diff --git a/app/Models/User.php b/app/Models/User.php index 5da4bc2..1321513 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -9,6 +9,12 @@ use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; +/** + * @property string $id + * @property string $name + * @property string $email + * @property string $password + */ class User extends Authenticatable { use HasApiTokens; diff --git a/database/factories/SemesterFactory.php b/database/factories/SemesterFactory.php new file mode 100644 index 0000000..914628c --- /dev/null +++ b/database/factories/SemesterFactory.php @@ -0,0 +1,17 @@ + "Semestr" . fake()->numberBetween(1, 7), + ]; + } +} diff --git a/database/migrations/2023_09_23_075139_create_semesters_table.php b/database/migrations/2023_09_23_075139_create_semesters_table.php new file mode 100644 index 0000000..e3eb53c --- /dev/null +++ b/database/migrations/2023_09_23_075139_create_semesters_table.php @@ -0,0 +1,24 @@ +ulid("id")->primary(); + $table->string("name"); + $table->enum("status", ["active", "inactive"])->default("inactive"); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists("semesters"); + } +}; diff --git a/resources/js/Layouts/DashboardLayout.vue b/resources/js/Layouts/DashboardLayout.vue index 830d61e..be9dd9b 100644 --- a/resources/js/Layouts/DashboardLayout.vue +++ b/resources/js/Layouts/DashboardLayout.vue @@ -54,7 +54,7 @@ const navigation = [ elements: [ { name: 'Kursy', href: '#', icon: BriefcaseIcon, current: false }, { name: 'Kierunki i specjalności', href: '#', icon: MagnifyingGlassIcon, current: false }, - { name: 'Semestry', href: '#', icon: ClipboardIcon, current: false }, + { name: 'Semestry', href: '/dashboard/semesters', icon: ClipboardIcon, current: false }, { name: 'Formy zajęć', href: '#', icon: CodeBracketSquareIcon, current: false }, { name: 'Tryby studiów', href: '#', icon: ClockIcon, current: false }, ], diff --git a/resources/js/Pages/Dashboard/Semester/Create.vue b/resources/js/Pages/Dashboard/Semester/Create.vue new file mode 100644 index 0000000..1f1669f --- /dev/null +++ b/resources/js/Pages/Dashboard/Semester/Create.vue @@ -0,0 +1,48 @@ + + + diff --git a/resources/js/Pages/Dashboard/Semester/Edit.vue b/resources/js/Pages/Dashboard/Semester/Edit.vue new file mode 100644 index 0000000..e45cc24 --- /dev/null +++ b/resources/js/Pages/Dashboard/Semester/Edit.vue @@ -0,0 +1,52 @@ + + + diff --git a/resources/js/Pages/Dashboard/Semester/Index.vue b/resources/js/Pages/Dashboard/Semester/Index.vue new file mode 100644 index 0000000..2d13497 --- /dev/null +++ b/resources/js/Pages/Dashboard/Semester/Index.vue @@ -0,0 +1,63 @@ + + + diff --git a/routes/web.php b/routes/web.php index 048cad3..99bb4b0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,6 +3,7 @@ declare(strict_types=1); use App\Http\Controllers\Dashboard\DashboardController; +use App\Http\Controllers\Dashboard\SemesterController; use App\Http\Controllers\Dashboard\StudentController; use App\Http\Controllers\Public\HomeController; use App\Http\Controllers\Public\NewsController; @@ -21,4 +22,12 @@ Route::patch("/students/{student}", "update")->name("students.update"); Route::delete("/students/{student}", "destroy")->name("students.destroy"); }); + Route::controller(SemesterController::class)->group(function (): void { + Route::get("/semesters", "index")->name("semesters.index"); + Route::get("/semesters/create", "create")->name("semesters.create"); + Route::post("/semesters", "store")->name("semesters.store"); + Route::get("/semesters/{semester}/edit", "edit")->name("semesters.edit"); + Route::patch("/semesters/{semester}", "update")->name("semesters.update"); + Route::delete("/semesters/{semester}", "destroy")->name("semesters.destroy"); + }); }); diff --git a/tests/Feature/SemesterTest.php b/tests/Feature/SemesterTest.php new file mode 100644 index 0000000..92238bb --- /dev/null +++ b/tests/Feature/SemesterTest.php @@ -0,0 +1,64 @@ +assertDatabaseCount("semesters", 0); + + $this->post("/dashboard/semesters", [ + "name" => "Semester 1", + ])->assertSessionHasNoErrors(); + + $this->assertDatabaseCount("semesters", 1); + } + + public function testSemesterCanBeUpdated(): void + { + $semester = Semester::factory()->create(); + + $this->assertDatabaseMissing("semesters", [ + "name" => "Semester 1", + ]); + + $this->patch("/dashboard/semesters/{$semester->id}", [ + "name" => "Semester 1", + ])->assertSessionHasNoErrors(); + + $this->assertDatabaseHas("semesters", [ + "name" => "Semester 1", + ]); + } + + public function testSemesterCannotBeCreatedWithInvalidData(): void + { + $this->post("/dashboard/semesters", [ + "name" => Str::random(256), + ])->assertSessionHasErrors([ + "name", + ]); + + $this->assertDatabaseCount("semesters", 0); + } + + public function testSemesterCanBeDeleted(): void + { + $semester = Semester::factory()->create(); + $this->assertDatabaseCount("semesters", 1); + + $this->delete("/dashboard/semesters/{$semester->id}"); + + $this->assertDatabaseCount("semesters", 0); + } +} diff --git a/tests/Feature/StudentTest.php b/tests/Feature/StudentTest.php index 7b357f1..1497d31 100644 --- a/tests/Feature/StudentTest.php +++ b/tests/Feature/StudentTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\Feature\Frontend; +namespace Tests\Feature; use App\Models\Student; use Illuminate\Foundation\Testing\RefreshDatabase;