diff --git a/app/Helpers/YearPeriodRetriever.php b/app/Helpers/YearPeriodRetriever.php
new file mode 100644
index 0000000..b474865
--- /dev/null
+++ b/app/Helpers/YearPeriodRetriever.php
@@ -0,0 +1,57 @@
+find($this->session->get(static::SESSION_KEY));
+
+ return $yearPeriod !== null ? $yearPeriod : $this->current();
+ }
+
+ public function current(): YearPeriod
+ {
+ return YearPeriod::current();
+ }
+
+ public function links(): array
+ {
+ $current = $this->selected();
+
+ $years = YearPeriod::query()->whereIn("year", $this->offset($current->year))->get();
+ $navigation = $years->map(fn(YearPeriod $yearPeriod) => $this->toNavigation($yearPeriod));
+
+ return [
+ "current" => $current->year,
+ "navigation" => $navigation->toArray(),
+ ];
+ }
+
+ protected function offset(int $year): array
+ {
+ return range($year - 2, $year + 2);
+ }
+
+ protected function toNavigation(YearPeriod $yearPeriod): array
+ {
+ return [
+ "year" => $yearPeriod->year,
+ "link" => route("year-periods.select", $yearPeriod->id),
+ ];
+ }
+}
diff --git a/app/Http/Controllers/SelectYearPeriodController.php b/app/Http/Controllers/SelectYearPeriodController.php
new file mode 100644
index 0000000..4965ef3
--- /dev/null
+++ b/app/Http/Controllers/SelectYearPeriodController.php
@@ -0,0 +1,22 @@
+session()->put(YearPeriodRetriever::SESSION_KEY, $yearPeriod->id);
+
+ return redirect()
+ ->back()
+ ->with("success", __("Selected year period has been changed"));
+ }
+}
diff --git a/app/Http/Controllers/VacationLimitController.php b/app/Http/Controllers/VacationLimitController.php
new file mode 100644
index 0000000..3d5e6d3
--- /dev/null
+++ b/app/Http/Controllers/VacationLimitController.php
@@ -0,0 +1,34 @@
+ VacationLimitResource::collection(VacationLimit::query()->with("user")->get()),
+ ]);
+ }
+
+ public function update(VacationLimitRequest $request): RedirectResponse
+ {
+ $data = $request->data();
+
+ foreach ($request->vacationLimits() as $limit) {
+ $limit->update($data[$limit->id]);
+ }
+
+ return redirect()
+ ->back()
+ ->with("success", __("Vacation limits have been updated"));
+ }
+}
diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php
index 48117f8..dd63c51 100644
--- a/app/Http/Middleware/HandleInertiaRequests.php
+++ b/app/Http/Middleware/HandleInertiaRequests.php
@@ -6,10 +6,16 @@ namespace Toby\Http\Middleware;
use Illuminate\Http\Request;
use Inertia\Middleware;
+use Toby\Helpers\YearPeriodRetriever;
use Toby\Http\Resources\UserResource;
class HandleInertiaRequests extends Middleware
{
+ public function __construct(
+ protected YearPeriodRetriever $yearPeriodRetriever,
+ ) {
+ }
+
public function share(Request $request): array
{
$user = $request->user();
@@ -22,6 +28,7 @@ class HandleInertiaRequests extends Middleware
"success" => $request->session()->get("success"),
"error" => $request->session()->get("error"),
],
+ "years" => fn() => $user ? $this->yearPeriodRetriever->links() : [],
]);
}
}
diff --git a/app/Http/Requests/VacationLimitRequest.php b/app/Http/Requests/VacationLimitRequest.php
new file mode 100644
index 0000000..fa43bbc
--- /dev/null
+++ b/app/Http/Requests/VacationLimitRequest.php
@@ -0,0 +1,33 @@
+ ["required", "array"],
+ "items.*.id" => ["required", "exists:vacation_limits,id"],
+ "items.*.days" => ["nullable", "integer", "min:0"],
+ ];
+ }
+
+ public function vacationLimits(): Collection
+ {
+ return VacationLimit::query()->find($this->collect("items")->pluck("id"));
+ }
+
+ public function data(): array
+ {
+ return $this->collect("items")
+ ->keyBy("id")
+ ->toArray();
+ }
+}
diff --git a/app/Http/Resources/UserFormDataResource.php b/app/Http/Resources/UserFormDataResource.php
index df7da1f..1ee44f3 100644
--- a/app/Http/Resources/UserFormDataResource.php
+++ b/app/Http/Resources/UserFormDataResource.php
@@ -8,7 +8,7 @@ use Illuminate\Http\Resources\Json\JsonResource;
class UserFormDataResource extends JsonResource
{
- public static $wrap = false;
+ public static $wrap = null;
public function toArray($request): array
{
diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php
index c9217a6..132092b 100644
--- a/app/Http/Resources/UserResource.php
+++ b/app/Http/Resources/UserResource.php
@@ -8,7 +8,7 @@ use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
- public static $wrap = false;
+ public static $wrap = null;
public function toArray($request): array
{
diff --git a/app/Http/Resources/VacationLimitResource.php b/app/Http/Resources/VacationLimitResource.php
new file mode 100644
index 0000000..85692b9
--- /dev/null
+++ b/app/Http/Resources/VacationLimitResource.php
@@ -0,0 +1,22 @@
+ $this->id,
+ "user" => new UserResource($this->user),
+ "hasVacation" => $this->hasVacation(),
+ "days" => $this->days,
+ ];
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
index aa76021..8ab0872 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -6,10 +6,12 @@ namespace Toby\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon;
+use Illuminate\Support\Collection;
use Toby\Enums\EmploymentForm;
/**
@@ -19,6 +21,7 @@ use Toby\Enums\EmploymentForm;
* @property string $avatar
* @property EmploymentForm $employment_form
* @property Carbon $employment_date
+ * @property Collection $vacationLimits
*/
class User extends Authenticatable
{
@@ -43,6 +46,11 @@ class User extends Authenticatable
"remember_token",
];
+ public function vacationLimits(): HasMany
+ {
+ return $this->hasMany(VacationLimit::class);
+ }
+
public function scopeSearch(Builder $query, ?string $text): Builder
{
if ($text === null) {
@@ -53,4 +61,11 @@ class User extends Authenticatable
->where("name", "LIKE", "%{$text}%")
->orWhere("email", "LIKE", "%{$text}%");
}
+
+ public function saveAvatar(string $path): void
+ {
+ $this->avatar = $path;
+
+ $this->save();
+ }
}
diff --git a/app/Models/VacationLimit.php b/app/Models/VacationLimit.php
new file mode 100644
index 0000000..6e6a361
--- /dev/null
+++ b/app/Models/VacationLimit.php
@@ -0,0 +1,37 @@
+days !== null;
+ }
+
+ public function user(): BelongsTo
+ {
+ return $this->belongsTo(User::class);
+ }
+
+ public function yearPeriod(): BelongsTo
+ {
+ return $this->belongsTo(YearPeriod::class);
+ }
+}
diff --git a/app/Models/YearPeriod.php b/app/Models/YearPeriod.php
index bcf2096..569ad03 100644
--- a/app/Models/YearPeriod.php
+++ b/app/Models/YearPeriod.php
@@ -7,10 +7,13 @@ namespace Toby\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\HasMany;
+use Illuminate\Support\Collection;
/**
* @property int $id
* @property int $year
+ * @property Collection $vacationLimits
*/
class YearPeriod extends Model
{
@@ -27,4 +30,9 @@ class YearPeriod extends Model
return $year;
}
+
+ public function vacationLimits(): HasMany
+ {
+ return $this->hasMany(VacationLimit::class);
+ }
}
diff --git a/app/Observers/UserObserver.php b/app/Observers/UserObserver.php
index 32f6f9c..3462cdf 100644
--- a/app/Observers/UserObserver.php
+++ b/app/Observers/UserObserver.php
@@ -6,20 +6,24 @@ namespace Toby\Observers;
use Illuminate\Support\Facades\Storage;
use Toby\Helpers\UserAvatarGenerator;
+use Toby\Helpers\YearPeriodRetriever;
use Toby\Models\User;
class UserObserver
{
public function __construct(
protected UserAvatarGenerator $generator,
+ protected YearPeriodRetriever $yearPeriodRetriever,
) {
}
public function created(User $user): void
{
- $user->avatar = $this->generator->generateFor($user);
+ $user->saveAvatar($this->generator->generateFor($user));
- $user->save();
+ $user->vacationLimits()->create([
+ "year_period_id" => $this->yearPeriodRetriever->current()->id,
+ ]);
}
public function updating(User $user): void
diff --git a/app/Observers/YearPeriodObserver.php b/app/Observers/YearPeriodObserver.php
new file mode 100644
index 0000000..71caa82
--- /dev/null
+++ b/app/Observers/YearPeriodObserver.php
@@ -0,0 +1,28 @@
+vacationLimits()->create([
+ "user_id" => $user->id,
+ ]);
+ }
+ }
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index db3deaa..cf3fe47 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -6,15 +6,15 @@ namespace Toby\Providers;
use Illuminate\Support\Carbon;
use Illuminate\Support\ServiceProvider;
-use Toby\Models\User;
-use Toby\Observers\UserObserver;
+use Toby\Models\VacationLimit;
+use Toby\Scopes\SelectedYearPeriodScope;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
- User::observe(UserObserver::class);
-
Carbon::macro("toDisplayString", fn() => $this->translatedFormat("j F Y"));
+
+ VacationLimit::addGlobalScope($this->app->make(SelectedYearPeriodScope::class));
}
}
diff --git a/app/Providers/ObserverServiceProvider.php b/app/Providers/ObserverServiceProvider.php
new file mode 100644
index 0000000..16badc4
--- /dev/null
+++ b/app/Providers/ObserverServiceProvider.php
@@ -0,0 +1,20 @@
+where("year_period_id", $this->yearPeriodRetriever->selected()->id);
+ }
+}
diff --git a/config/app.php b/config/app.php
index 77122a5..3fa85eb 100644
--- a/config/app.php
+++ b/config/app.php
@@ -42,5 +42,6 @@ return [
Toby\Providers\EventServiceProvider::class,
Toby\Providers\RouteServiceProvider::class,
Toby\Providers\TelescopeServiceProvider::class,
+ Toby\Providers\ObserverServiceProvider::class,
],
];
diff --git a/database/factories/VacationLimitFactory.php b/database/factories/VacationLimitFactory.php
new file mode 100644
index 0000000..d5f3d6d
--- /dev/null
+++ b/database/factories/VacationLimitFactory.php
@@ -0,0 +1,24 @@
+faker->boolean(75);
+
+ return [
+ "user_id" => User::factory(),
+ "year_period_id" => YearPeriod::factory(),
+ "has_vacation" => $hasVacation,
+ "days" => $hasVacation ? $this->faker->numberBetween(20, 26) : null,
+ ];
+ }
+}
diff --git a/database/migrations/2022_01_19_140630_create_vacation_limits_table.php b/database/migrations/2022_01_19_140630_create_vacation_limits_table.php
new file mode 100644
index 0000000..c2b29d5
--- /dev/null
+++ b/database/migrations/2022_01_19_140630_create_vacation_limits_table.php
@@ -0,0 +1,27 @@
+id();
+ $table->foreignIdFor(User::class)->constrained()->cascadeOnDelete();
+ $table->foreignIdFor(YearPeriod::class)->constrained()->cascadeOnDelete();
+ $table->integer("days")->nullable();
+ $table->timestamps();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists("vacation_limits");
+ }
+};
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index af2722b..d6a4f27 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -6,23 +6,61 @@ namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
+use Illuminate\Support\Collection;
+use Toby\Helpers\UserAvatarGenerator;
use Toby\Models\User;
+use Toby\Models\VacationLimit;
use Toby\Models\YearPeriod;
class DatabaseSeeder extends Seeder
{
+ public function __construct(
+ protected UserAvatarGenerator $avatarGenerator,
+ ) {
+ }
+
public function run(): void
{
- User::factory(35)->create();
+ User::unsetEventDispatcher();
+ YearPeriod::unsetEventDispatcher();
+
+ User::factory(9)->create();
User::factory([
"email" => env("LOCAL_EMAIL_FOR_LOGIN_VIA_GOOGLE"),
])->create();
- YearPeriod::factory([
- "year" => Carbon::now()->year,
- ])->create();
- YearPeriod::factory([
- "year" => Carbon::now()->year + 1,
- ])->create();
+ $users = User::all();
+
+ $this->generateAvatarsForUsers($users);
+
+ YearPeriod::factory()
+ ->count(3)
+ ->sequence(
+ [
+ "year" => Carbon::now()->year - 1,
+ ],
+ [
+ "year" => Carbon::now()->year,
+ ],
+ [
+ "year" => Carbon::now()->year + 1,
+ ],
+ )
+ ->afterCreating(function (YearPeriod $yearPeriod) use ($users): void {
+ foreach ($users as $user) {
+ VacationLimit::factory()
+ ->for($yearPeriod)
+ ->for($user)
+ ->create();
+ }
+ })
+ ->create();
+ }
+
+ protected function generateAvatarsForUsers(Collection $users): void
+ {
+ foreach ($users as $user) {
+ $user->saveAvatar($this->avatarGenerator->generateFor($user));
+ }
}
}
diff --git a/package-lock.json b/package-lock.json
index c24807a..7a47b79 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
{
- "name": "application",
+ "name": "toby",
"lockfileVersion": 2,
"requires": true,
"packages": {
diff --git a/resources/js/Pages/VacationLimits.vue b/resources/js/Pages/VacationLimits.vue
new file mode 100644
index 0000000..04afda6
--- /dev/null
+++ b/resources/js/Pages/VacationLimits.vue
@@ -0,0 +1,175 @@
+
+
+ Zarządzaj dostepnymi dniami urlopów dla użytkowników.
+
+ Dostępne dni urlopu dla użytkowników
+
+