Skip to content

Feat/course registrations #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
569f07f
feat: create CourseRegistrationTable, model and controller
frooooooo7 Jan 10, 2025
a030d78
PHP Linting (Pint)
frooooooo7 Jan 10, 2025
659e02a
feat: implement index and update methods for course registrations
frooooooo7 Jan 13, 2025
9c88018
PHP Linting (Pint)
frooooooo7 Jan 13, 2025
f46dc80
refactor: moved data handling logic from service to value objects
frooooooo7 Jan 14, 2025
4067669
PHP Linting (Pint)
frooooooo7 Jan 14, 2025
176d6f3
refactor: use enum values in migration
frooooooo7 Jan 16, 2025
612cef1
refactor:
frooooooo7 Jan 17, 2025
edd6280
feat: add seeder for CourseRegistrations
frooooooo7 Jan 17, 2025
9db9200
PHP Linting (Pint)
frooooooo7 Jan 17, 2025
85c81ec
refactor: CourseRegistration - enum, migration, requests and routes
frooooooo7 Jan 19, 2025
d6a98eb
PHP Linting (Pint)
frooooooo7 Jan 19, 2025
854a7a5
refactor: split registration functionality between StudentCourseRegis…
frooooooo7 Feb 4, 2025
da405e6
PHP Linting (Pint)
frooooooo7 Feb 4, 2025
f24f15c
refactor:
frooooooo7 Feb 9, 2025
0cef8d7
PHP Linting (Pint)
frooooooo7 Feb 9, 2025
9ad52d8
fix: store properly registartions to course_user
frooooooo7 Feb 12, 2025
2ae1f7a
PHP Linting (Pint)
frooooooo7 Feb 12, 2025
9de3774
Merge branch 'dev' into feat/course-registrations
frooooooo7 Feb 22, 2025
24c38e5
feat: add endpoint to retrieve list of students
frooooooo7 Feb 22, 2025
56442b3
PHP Linting (Pint)
frooooooo7 Feb 22, 2025
10e4824
feat: add functionality to accept and decline course registrations
frooooooo7 Feb 23, 2025
32984f1
PHP Linting (Pint)
frooooooo7 Feb 23, 2025
358b107
feat: implement search by name and last name for drivers
frooooooo7 Mar 2, 2025
cfe340d
refactor: requested changes
frooooooo7 Mar 2, 2025
5d4ebe1
PHP Linting (Pint)
frooooooo7 Mar 2, 2025
2797e18
refactor: use QueryBuilder instead of AdminStudentService in students…
frooooooo7 Mar 26, 2025
797d814
PHP Linting (Pint)
frooooooo7 Mar 26, 2025
b358b50
refactor: improve phone number validation and database storage
frooooooo7 Apr 1, 2025
b5da09c
PHP Linting (Pint)
frooooooo7 Apr 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions app/Enums/RegistrationStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Enums;

enum RegistrationStatus: string
{
case PENDING = 'pending';
case ACCEPTED = 'accepted';
case REJECTED = 'rejected';

// get all enum values as an array
public static function values(): array
{
return array_column(self::cases(), 'value');
}

public static function acceptedAndRejectedValues(): array
{
return [
self::ACCEPTED->value,
self::REJECTED->value,
];
}
}
18 changes: 18 additions & 0 deletions app/Http/Controllers/Admin/AdminStudentController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Resources\UserCollection;
use App\Services\Admin\AdminStudentService;
use Illuminate\Http\Request;

class AdminStudentController extends Controller
{
public function __construct(private readonly AdminStudentService $adminStudentService) {}

public function index(Request $request): UserCollection
{
return new UserCollection($this->adminStudentService->index($request)->paginate(self::PER_PAGE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Http\Controllers\CourseRegistration;

use App\Http\Controllers\Controller;
use App\Http\Requests\CourseRegistration\StoreCourseRegistrationRequest;
use App\Http\Resources\CourseRegistration\CourseRegistrationCollection;
use App\Http\Resources\CourseRegistration\CourseRegistrationResource;
use App\Http\Resources\CourseUserResource;
use App\Models\CourseRegistration;
use App\Services\CourseRegistrationService;

class AdminCourseRegistrationController extends Controller
{
public function __construct(protected CourseRegistrationService $courseRegistrationService) {}

public function index(): CourseRegistrationCollection
{
return new CourseRegistrationCollection($this->courseRegistrationService->index());
}

public function store(StoreCourseRegistrationRequest $request): CourseUserResource
{
return new CourseUserResource($this->courseRegistrationService->store($request->getRegistration()));
}

public function accept(CourseRegistration $courseRegistration): CourseRegistrationResource
{
return new CourseRegistrationResource($this->courseRegistrationService->accept($courseRegistration));
}

public function decline(CourseRegistration $courseRegistration): CourseRegistrationResource
{
return new CourseRegistrationResource($this->courseRegistrationService->decline($courseRegistration));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Controllers\CourseRegistration;

use App\Http\Controllers\Controller;
use App\Http\Requests\CourseRegistration\GuestCourseRegistrationRequest;
use App\Http\Resources\CourseRegistration\CourseRegistrationResource;
use App\Models\Course;
use App\Services\GuestCourseRegistrationService;

class GuestCourseRegistrationController extends Controller
{
public function __construct(protected GuestCourseRegistrationService $guestCourseRegistrationService) {}

public function store(GuestCourseRegistrationRequest $request, Course $course): CourseRegistrationResource
{
return new CourseRegistrationResource($this->guestCourseRegistrationService->store($request->getGuestCourseRegistration($course)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace App\Http\Requests\CourseRegistration;

use App\Models\Course;
use App\ValueObjects\StoreGuestCourseRegistration;
use Illuminate\Foundation\Http\FormRequest;

class GuestCourseRegistrationRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => 'required|string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/',
'last_name' => 'required|string|min:2|max:30|regex:/^[a-zA-ZÀ-ž\s\'-]+$/',
'email' => 'required|email|unique:users,email',
'phone' => 'required|regex:/^\+?\d{9,15}$/',
];
}

public function getGuestCourseRegistration(Course $course): StoreGuestCourseRegistration
{
return new StoreGuestCourseRegistration(
$course->id,
$this->get('name'),
$this->get('last_name'),
$this->get('email'),
$this->get('phone'),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Http\Requests\CourseRegistration;

use App\ValueObjects\CreateCourseRegistration;
use Illuminate\Foundation\Http\FormRequest;

class StoreCourseRegistrationRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'user_id' => 'required|exists:users,id',
'course_id' => 'required|exists:courses,id',
];
}

public function getRegistration(): CreateCourseRegistration
{
return new CreateCourseRegistration(
$this->get('user_id'),
$this->get('course_id')
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Resources\CourseRegistration;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class CourseRegistrationCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* @return array<int|string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Http\Resources\CourseRegistration;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class CourseRegistrationResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'course_id' => $this->course_id,
'name' => $this->name,
'last_name' => $this->last_name,
'email' => $this->email,
'phone' => $this->phone,
'status' => $this->status,
'created_at' => $this->created_at?->toDateTimeString(),
'updated_at' => $this->updated_at?->toDateTimeString(),
];
}
}
19 changes: 19 additions & 0 deletions app/Http/Resources/CourseUserResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class CourseUserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}
13 changes: 13 additions & 0 deletions app/Http/Resources/UserCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
public function toArray($request): array
{
return parent::toArray($request);
}
}
12 changes: 12 additions & 0 deletions app/Models/Course.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;

/**
* @property int $id
Expand Down Expand Up @@ -41,4 +43,14 @@ public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}

public function users(): BelongsToMany
{
return $this->belongsToMany(User::class, 'course_user')->withTimestamps();
}

public function registrations(): hasMany
{
return $this->hasMany(CourseRegistration::class);
}
}
28 changes: 28 additions & 0 deletions app/Models/CourseRegistration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Models;

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

class CourseRegistration extends Model
{
/** @use HasFactory<CourseRegistrationFactory> */
use HasFactory;

protected $fillable = [
'course_id',
'name',
'last_name',
'email',
'phone',
'status',
];

public function course(): BelongsTo
{
return $this->belongsTo(Course::class);
}
}
11 changes: 11 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
Expand Down Expand Up @@ -62,4 +63,14 @@ public function creditCard(): HasOne
{
return $this->hasOne(CreditCard::class);
}

public function courses(): BelongsToMany
{
return $this->belongsToMany(Course::class, 'course_user')->withTimestamps();
}

public function isRegisteredToCourse($courseId): bool
{
return $this->courses()->where('course_id', $courseId)->exists();
}
}
26 changes: 26 additions & 0 deletions app/Services/Admin/AdminStudentService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\Services\Admin;

use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;

class AdminStudentService
{
public function index(Request $request): Builder
{

$user = User::role('driver');

if ($request->has('search')) {
$search = strtolower($request->input('search'));
$user->where(function ($q) use ($search) {
$q->whereRaw('LOWER(name) LIKE ?', ["%{$search}%"])
->orWhereRaw('LOWER(last_name) LIKE ?', ["%{$search}%"]);
});
}

return $user;
}
}
Loading