* #28 - holidays management * #28 - fix * #28 - fix * #28 - fix * #28 - fix * #28 - fix * #28 - fix * #28 - cr fix
This commit is contained in:
parent
6854c7a9f8
commit
026bfe485f
34
app/Helpers/PolishHolidaysRetriever.php
Normal file
34
app/Helpers/PolishHolidaysRetriever.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Helpers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Toby\Models\YearPeriod;
|
||||||
|
use Yasumi\Holiday;
|
||||||
|
use Yasumi\Yasumi;
|
||||||
|
|
||||||
|
class PolishHolidaysRetriever
|
||||||
|
{
|
||||||
|
protected const PROVIDER_KEY = "Poland";
|
||||||
|
protected const LANG_KEY = "pl";
|
||||||
|
|
||||||
|
public function getForYearPeriod(YearPeriod $yearPeriod): Collection
|
||||||
|
{
|
||||||
|
$polishProvider = Yasumi::create(static::PROVIDER_KEY, $yearPeriod->year);
|
||||||
|
|
||||||
|
$holidays = $polishProvider->getHolidays();
|
||||||
|
|
||||||
|
return $this->prepareHolidays($holidays);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareHolidays(array $holidays): Collection
|
||||||
|
{
|
||||||
|
return collect($holidays)->map(fn(Holiday $holiday) => [
|
||||||
|
"name" => $holiday->getName([static::LANG_KEY]),
|
||||||
|
"date" => Carbon::createFromTimestamp($holiday->getTimestamp()),
|
||||||
|
])->values();
|
||||||
|
}
|
||||||
|
}
|
65
app/Http/Controllers/HolidayController.php
Normal file
65
app/Http/Controllers/HolidayController.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Inertia\Response;
|
||||||
|
use Toby\Http\Requests\HolidayRequest;
|
||||||
|
use Toby\Http\Resources\HolidayFormDataResource;
|
||||||
|
use Toby\Http\Resources\HolidayResource;
|
||||||
|
use Toby\Models\Holiday;
|
||||||
|
|
||||||
|
class HolidayController extends Controller
|
||||||
|
{
|
||||||
|
public function index(): Response
|
||||||
|
{
|
||||||
|
$holidays = Holiday::query()
|
||||||
|
->orderBy("date")
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return inertia("Holidays/Index", [
|
||||||
|
"holidays" => HolidayResource::collection($holidays),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): Response
|
||||||
|
{
|
||||||
|
return inertia("Holidays/Create");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(HolidayRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
Holiday::query()->create($request->data());
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route("holidays.index")
|
||||||
|
->with("success", __("Holiday has been created"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Holiday $holiday): Response
|
||||||
|
{
|
||||||
|
return inertia("Holidays/Edit", [
|
||||||
|
"holiday" => new HolidayFormDataResource($holiday),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(HolidayRequest $request, Holiday $holiday): RedirectResponse
|
||||||
|
{
|
||||||
|
$holiday->update($request->data());
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route("holidays.index")
|
||||||
|
->with("success", __("Holiday has been updated"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Holiday $holiday): RedirectResponse
|
||||||
|
{
|
||||||
|
$holiday->delete();
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route("holidays.index")
|
||||||
|
->with("success", __("Holiday has been deleted"));
|
||||||
|
}
|
||||||
|
}
|
37
app/Http/Requests/HolidayRequest.php
Normal file
37
app/Http/Requests/HolidayRequest.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Toby\Models\YearPeriod;
|
||||||
|
use Toby\Rules\YearPeriodExists;
|
||||||
|
|
||||||
|
class HolidayRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"name" => ["required", "min:3", "max:150"],
|
||||||
|
"date" => ["required",
|
||||||
|
"date_format:Y-m-d",
|
||||||
|
Rule::unique("holidays", "date")->ignore($this->holiday),
|
||||||
|
new YearPeriodExists(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function data(): array
|
||||||
|
{
|
||||||
|
$date = $this->get("date");
|
||||||
|
|
||||||
|
return [
|
||||||
|
"name" => $this->get("name"),
|
||||||
|
"date" => $date,
|
||||||
|
"year_period_id" => YearPeriod::findByYear(Carbon::create($date)->year)->id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ class UserRequest extends FormRequest
|
|||||||
"lastName" => ["required", "min:3", "max:80"],
|
"lastName" => ["required", "min:3", "max:80"],
|
||||||
"email" => ["required", "email", Rule::unique("users", "email")->ignore($this->user)],
|
"email" => ["required", "email", Rule::unique("users", "email")->ignore($this->user)],
|
||||||
"employmentForm" => ["required", new Enum(EmploymentForm::class)],
|
"employmentForm" => ["required", new Enum(EmploymentForm::class)],
|
||||||
"employmentDate" => ["required", "date"],
|
"employmentDate" => ["required", "date_format:Y-m-d"],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
app/Http/Resources/HolidayFormDataResource.php
Normal file
21
app/Http/Resources/HolidayFormDataResource.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class HolidayFormDataResource extends JsonResource
|
||||||
|
{
|
||||||
|
public static $wrap = null;
|
||||||
|
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"id" => $this->id,
|
||||||
|
"name" => $this->name,
|
||||||
|
"date" => $this->date->toDateString(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
22
app/Http/Resources/HolidayResource.php
Normal file
22
app/Http/Resources/HolidayResource.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class HolidayResource extends JsonResource
|
||||||
|
{
|
||||||
|
public static $wrap = null;
|
||||||
|
|
||||||
|
public function toArray($request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"id" => $this->id,
|
||||||
|
"name" => $this->name,
|
||||||
|
"displayDate" => $this->date->toDisplayString(),
|
||||||
|
"dayOfWeek" => $this->date->dayName,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
32
app/Models/Holiday.php
Normal file
32
app/Models/Holiday.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $name
|
||||||
|
* @property Carbon $date
|
||||||
|
* @property YearPeriod $yearPeriod
|
||||||
|
*/
|
||||||
|
class Holiday extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
"date" => "date",
|
||||||
|
];
|
||||||
|
|
||||||
|
public function yearPeriod(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(YearPeriod::class);
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@ class User extends Authenticatable
|
|||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
"employment_form" => EmploymentForm::class,
|
"employment_form" => EmploymentForm::class,
|
||||||
"employment_date" => "datetime",
|
"employment_date" => "date",
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
|
@ -4,29 +4,33 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Models;
|
namespace Toby\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property int $year
|
* @property int $year
|
||||||
* @property Collection $vacationLimits
|
* @property Collection $vacationLimits
|
||||||
|
* @property Collection $holidays
|
||||||
*/
|
*/
|
||||||
class YearPeriod extends Model
|
class YearPeriod extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $guarded = [];
|
||||||
"year",
|
|
||||||
];
|
|
||||||
|
|
||||||
public static function current(): ?static
|
public static function current(): ?static
|
||||||
|
{
|
||||||
|
return static::findByYear(Carbon::now()->year);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function findByYear(int $year): ?static
|
||||||
{
|
{
|
||||||
/** @var YearPeriod $year */
|
/** @var YearPeriod $year */
|
||||||
$year = static::query()->where("year", Carbon::now()->year)->first();
|
$year = static::query()->where("year", $year)->first();
|
||||||
|
|
||||||
return $year;
|
return $year;
|
||||||
}
|
}
|
||||||
@ -35,4 +39,9 @@ class YearPeriod extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(VacationLimit::class);
|
return $this->hasMany(VacationLimit::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function holidays(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(Holiday::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Observers;
|
namespace Toby\Observers;
|
||||||
|
|
||||||
|
use Toby\Helpers\PolishHolidaysRetriever;
|
||||||
use Toby\Helpers\UserAvatarGenerator;
|
use Toby\Helpers\UserAvatarGenerator;
|
||||||
use Toby\Models\User;
|
use Toby\Models\User;
|
||||||
use Toby\Models\YearPeriod;
|
use Toby\Models\YearPeriod;
|
||||||
@ -12,10 +13,17 @@ class YearPeriodObserver
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected UserAvatarGenerator $generator,
|
protected UserAvatarGenerator $generator,
|
||||||
|
protected PolishHolidaysRetriever $polishHolidaysRetriever,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function created(YearPeriod $yearPeriod): void
|
public function created(YearPeriod $yearPeriod): void
|
||||||
|
{
|
||||||
|
$this->createVacationLimitsFor($yearPeriod);
|
||||||
|
$this->createHolidaysFor($yearPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createVacationLimitsFor(YearPeriod $yearPeriod): void
|
||||||
{
|
{
|
||||||
$users = User::all();
|
$users = User::all();
|
||||||
|
|
||||||
@ -25,4 +33,16 @@ class YearPeriodObserver
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function createHolidaysFor(YearPeriod $yearPeriod): void
|
||||||
|
{
|
||||||
|
$holidays = $this->polishHolidaysRetriever->getForYearPeriod($yearPeriod);
|
||||||
|
|
||||||
|
foreach ($holidays as $holiday) {
|
||||||
|
$yearPeriod->holidays()->create([
|
||||||
|
"name" => $holiday["name"],
|
||||||
|
"date" => $holiday["date"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ namespace Toby\Providers;
|
|||||||
|
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Toby\Models\Holiday;
|
||||||
use Toby\Models\VacationLimit;
|
use Toby\Models\VacationLimit;
|
||||||
use Toby\Scopes\SelectedYearPeriodScope;
|
use Toby\Scopes\SelectedYearPeriodScope;
|
||||||
|
|
||||||
@ -15,6 +16,9 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
Carbon::macro("toDisplayString", fn() => $this->translatedFormat("j F Y"));
|
Carbon::macro("toDisplayString", fn() => $this->translatedFormat("j F Y"));
|
||||||
|
|
||||||
VacationLimit::addGlobalScope($this->app->make(SelectedYearPeriodScope::class));
|
$selectedYearPeriodScope = $this->app->make(SelectedYearPeriodScope::class);
|
||||||
|
|
||||||
|
VacationLimit::addGlobalScope($selectedYearPeriodScope);
|
||||||
|
Holiday::addGlobalScope($selectedYearPeriodScope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
app/Rules/YearPeriodExists.php
Normal file
24
app/Rules/YearPeriodExists.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Rules;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Validation\Rule;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Toby\Models\YearPeriod;
|
||||||
|
|
||||||
|
class YearPeriodExists implements Rule
|
||||||
|
{
|
||||||
|
public function passes($attribute, $value): bool
|
||||||
|
{
|
||||||
|
$yearPeriod = YearPeriod::findByYear(Carbon::create($value)->year);
|
||||||
|
|
||||||
|
return $yearPeriod !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function message(): string
|
||||||
|
{
|
||||||
|
return "The year period for given year doesn't exist.";
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": "^8.1",
|
"php": "^8.1",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
|
"azuyalabs/yasumi": "^2.4",
|
||||||
"fruitcake/laravel-cors": "^2.0",
|
"fruitcake/laravel-cors": "^2.0",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
"inertiajs/inertia-laravel": "^0.5.1",
|
"inertiajs/inertia-laravel": "^0.5.1",
|
||||||
|
75
composer.lock
generated
75
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "3412dd2a403927b829237ae4db36351a",
|
"content-hash": "e3c6ffae4c01db02d0471c52d2370b79",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asm89/stack-cors",
|
"name": "asm89/stack-cors",
|
||||||
@ -62,6 +62,79 @@
|
|||||||
},
|
},
|
||||||
"time": "2022-01-18T09:12:03+00:00"
|
"time": "2022-01-18T09:12:03+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "azuyalabs/yasumi",
|
||||||
|
"version": "2.4.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/azuyalabs/yasumi.git",
|
||||||
|
"reference": "083a0d0579fee17e68d688d463bc01098ac2691f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/azuyalabs/yasumi/zipball/083a0d0579fee17e68d688d463bc01098ac2691f",
|
||||||
|
"reference": "083a0d0579fee17e68d688d463bc01098ac2691f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"php": ">=7.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^2.16",
|
||||||
|
"infection/infection": "^0.17 | ^0.22",
|
||||||
|
"mikey179/vfsstream": "^1.6",
|
||||||
|
"phan/phan": "^4.0",
|
||||||
|
"phpstan/phpstan": "^0.12.66",
|
||||||
|
"phpunit/phpunit": "^8.5 | ^9.4",
|
||||||
|
"vimeo/psalm": "^4"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-calendar": "For calculating the date of Easter"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Yasumi\\": "src/Yasumi/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sacha Telgenhof",
|
||||||
|
"email": "me@sachatelgenhof.com",
|
||||||
|
"role": "Maintainer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "The easy PHP Library for calculating holidays.",
|
||||||
|
"homepage": "https://www.yasumi.dev",
|
||||||
|
"keywords": [
|
||||||
|
"Bank",
|
||||||
|
"calculation",
|
||||||
|
"calendar",
|
||||||
|
"celebration",
|
||||||
|
"date",
|
||||||
|
"holiday",
|
||||||
|
"holidays",
|
||||||
|
"national",
|
||||||
|
"time"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"docs": "https://www.yasumi.dev",
|
||||||
|
"issues": "https://github.com/azuyalabs/yasumi/issues",
|
||||||
|
"source": "https://github.com/azuyalabs/yasumi"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://www.buymeacoffee.com/sachatelgenhof",
|
||||||
|
"type": "other"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-05-09T09:03:34+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.9.3",
|
"version": "0.9.3",
|
||||||
|
20
database/factories/HolidayFactory.php
Normal file
20
database/factories/HolidayFactory.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Toby\Models\YearPeriod;
|
||||||
|
|
||||||
|
class HolidayFactory extends Factory
|
||||||
|
{
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"name" => $this->faker->word,
|
||||||
|
"date" => $this->faker->unique->date,
|
||||||
|
"year_period_id" => YearPeriod::current()->id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Toby\Enums\EmploymentForm;
|
use Toby\Enums\EmploymentForm;
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ class UserFactory extends Factory
|
|||||||
"last_name" => $this->faker->lastName(),
|
"last_name" => $this->faker->lastName(),
|
||||||
"email" => $this->faker->unique()->safeEmail(),
|
"email" => $this->faker->unique()->safeEmail(),
|
||||||
"employment_form" => $this->faker->randomElement(EmploymentForm::cases()),
|
"employment_form" => $this->faker->randomElement(EmploymentForm::cases()),
|
||||||
"employment_date" => $this->faker->dateTimeBetween("2020-10-27"),
|
"employment_date" => Carbon::createFromInterface($this->faker->dateTimeBetween("2020-10-27"))->toDateString(),
|
||||||
"remember_token" => Str::random(10),
|
"remember_token" => Str::random(10),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ class YearPeriodFactory extends Factory
|
|||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
"year" => $this->faker->unique()->year,
|
"year" => (int)$this->faker->unique()->year,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ return new class() extends Migration {
|
|||||||
$table->string("email")->unique();
|
$table->string("email")->unique();
|
||||||
$table->string("avatar")->nullable();
|
$table->string("avatar")->nullable();
|
||||||
$table->string("employment_form");
|
$table->string("employment_form");
|
||||||
$table->dateTime("employment_date");
|
$table->date("employment_date");
|
||||||
$table->rememberToken();
|
$table->rememberToken();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Toby\Models\YearPeriod;
|
||||||
|
|
||||||
|
return new class() extends Migration {
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create("holidays", function (Blueprint $table): void {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignIdFor(YearPeriod::class)->constrained()->cascadeOnDelete();
|
||||||
|
$table->string("name");
|
||||||
|
$table->date("date")->unique();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists("holidays");
|
||||||
|
}
|
||||||
|
};
|
@ -7,6 +7,7 @@ namespace Database\Seeders;
|
|||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Toby\Helpers\PolishHolidaysRetriever;
|
||||||
use Toby\Helpers\UserAvatarGenerator;
|
use Toby\Helpers\UserAvatarGenerator;
|
||||||
use Toby\Models\User;
|
use Toby\Models\User;
|
||||||
use Toby\Models\VacationLimit;
|
use Toby\Models\VacationLimit;
|
||||||
@ -54,6 +55,16 @@ class DatabaseSeeder extends Seeder
|
|||||||
->create();
|
->create();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
->afterCreating(function (YearPeriod $yearPeriod): void {
|
||||||
|
$polishHolidaysRetriever = new PolishHolidaysRetriever();
|
||||||
|
|
||||||
|
foreach ($polishHolidaysRetriever->getForYearPeriod($yearPeriod) as $holiday) {
|
||||||
|
$yearPeriod->holidays()->create([
|
||||||
|
"name" => $holiday["name"],
|
||||||
|
"date" => $holiday["date"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
})
|
||||||
->create();
|
->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
106
resources/js/Pages/Holidays/Create.vue
Normal file
106
resources/js/Pages/Holidays/Create.vue
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<InertiaHead title="Dodaj dzień wolny" />
|
||||||
|
<div class="bg-white sm:rounded-lg shadow-md">
|
||||||
|
<div class="p-4 sm:px-6">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
Dodaj dzień wolny
|
||||||
|
</h2>
|
||||||
|
<p class="mt-1 text-sm text-gray-500">
|
||||||
|
Użytkownik nie będzie miał możliwości wzięcia urlopu w dzień wolny.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<form
|
||||||
|
class="border-t border-gray-200 px-6"
|
||||||
|
@submit.prevent="createHoliday"
|
||||||
|
>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<label
|
||||||
|
for="name"
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||||
|
>
|
||||||
|
Nazwa
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<input
|
||||||
|
id="name"
|
||||||
|
v-model="form.name"
|
||||||
|
type="text"
|
||||||
|
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||||
|
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.name, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.name }"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.name"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.name }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<label
|
||||||
|
for="date"
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||||
|
>
|
||||||
|
Data
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<FlatPickr
|
||||||
|
id="date"
|
||||||
|
v-model="form.date"
|
||||||
|
placeholder="Wybierz datę"
|
||||||
|
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||||
|
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.date, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.date }"
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.date"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.date }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end py-3">
|
||||||
|
<div class="space-x-3">
|
||||||
|
<InertiaLink
|
||||||
|
href="/holidays"
|
||||||
|
class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||||
|
>
|
||||||
|
Anuluj
|
||||||
|
</InertiaLink>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
:disabled="form.processing"
|
||||||
|
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||||
|
>
|
||||||
|
Zapisz
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useForm } from '@inertiajs/inertia-vue3';
|
||||||
|
import FlatPickr from 'vue-flatpickr-component';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'HolidayCreate',
|
||||||
|
components: {
|
||||||
|
FlatPickr,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const form = useForm({
|
||||||
|
name: null,
|
||||||
|
date: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { form };
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
createHoliday() {
|
||||||
|
this.form.post('/holidays');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
113
resources/js/Pages/Holidays/Edit.vue
Normal file
113
resources/js/Pages/Holidays/Edit.vue
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<template>
|
||||||
|
<InertiaHead title="Edytuj dzień wolny" />
|
||||||
|
<div class="bg-white sm:rounded-lg shadow-md">
|
||||||
|
<div class="p-4 sm:px-6">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
Edytuj dzień wolny
|
||||||
|
</h2>
|
||||||
|
<p class="mt-1 text-sm text-gray-500">
|
||||||
|
Użytkownik nie będzie miał możliwości wzięcia urlopu w dzień wolny.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<form
|
||||||
|
class="border-t border-gray-200 px-6"
|
||||||
|
@submit.prevent="editHoliday"
|
||||||
|
>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<label
|
||||||
|
for="name"
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||||
|
>
|
||||||
|
Nazwa
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<input
|
||||||
|
id="name"
|
||||||
|
v-model="form.name"
|
||||||
|
type="text"
|
||||||
|
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||||
|
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.name, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.name }"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.name"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.name }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<label
|
||||||
|
for="date"
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||||
|
>
|
||||||
|
Data
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<FlatPickr
|
||||||
|
id="date"
|
||||||
|
v-model="form.date"
|
||||||
|
placeholder="Wybierz datę"
|
||||||
|
class="block w-full max-w-lg shadow-sm rounded-md sm:text-sm"
|
||||||
|
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.date, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.date }"
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.date"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.date }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end py-3">
|
||||||
|
<div class="space-x-3">
|
||||||
|
<InertiaLink
|
||||||
|
href="/holidays"
|
||||||
|
class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||||
|
>
|
||||||
|
Anuluj
|
||||||
|
</InertiaLink>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
:disabled="form.processing"
|
||||||
|
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||||
|
>
|
||||||
|
Zapisz
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useForm } from '@inertiajs/inertia-vue3';
|
||||||
|
import FlatPickr from 'vue-flatpickr-component';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'HolidayEdit',
|
||||||
|
components: {
|
||||||
|
FlatPickr,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
holiday: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const form = useForm({
|
||||||
|
name: props.holiday.name,
|
||||||
|
date: props.holiday.date,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { form };
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
editHoliday() {
|
||||||
|
this.form
|
||||||
|
.put(`/holidays/${this.holiday.id}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
167
resources/js/Pages/Holidays/Index.vue
Normal file
167
resources/js/Pages/Holidays/Index.vue
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<InertiaHead title="Dni wolne od pracy" />
|
||||||
|
<div class="bg-white sm:rounded-lg shadow-md">
|
||||||
|
<div class="flex justify-between items-center p-4 sm:px-6">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
Dni wolne od pracy
|
||||||
|
</h2>
|
||||||
|
<p class="mt-1 text-sm text-gray-500">
|
||||||
|
Lista dni wolnych od pracy w danym roku
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<InertiaLink
|
||||||
|
href="holidays/create"
|
||||||
|
class="inline-flex items-center px-4 py-3 border border-transparent text-sm leading-4 font-medium rounded-md shadow-sm text-white bg-blumilk-600 hover:bg-blumilk-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500"
|
||||||
|
>
|
||||||
|
Dodaj dzień wolny
|
||||||
|
</InertiaLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="border-t border-gray-200">
|
||||||
|
<div class="overflow-x-auto xl:overflow-x-visible overflow-y-auto xl:overflow-y-visible">
|
||||||
|
<table class="min-w-full divide-y divide-gray-200">
|
||||||
|
<thead class="bg-gray-100">
|
||||||
|
<tr>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
Nazwa
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
Data
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
Dzień tygodnia
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
|
/>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="bg-white divide-y divide-gray-100">
|
||||||
|
<tr
|
||||||
|
v-for="holiday in holidays.data"
|
||||||
|
:key="holiday.id"
|
||||||
|
class="hover:bg-blumilk-25"
|
||||||
|
>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500 font-semibold capitalize">
|
||||||
|
{{ holiday.name }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
|
{{ holiday.displayDate }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
|
{{ holiday.dayOfWeek }}
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500 text-right">
|
||||||
|
<Menu
|
||||||
|
as="div"
|
||||||
|
class="relative inline-block text-left"
|
||||||
|
>
|
||||||
|
<MenuButton class="rounded-full flex items-center text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-blumilk-500">
|
||||||
|
<DotsVerticalIcon
|
||||||
|
class="h-5 w-5"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</MenuButton>
|
||||||
|
|
||||||
|
<transition
|
||||||
|
enter-active-class="transition ease-out duration-100"
|
||||||
|
enter-from-class="transform opacity-0 scale-95"
|
||||||
|
enter-to-class="transform opacity-100 scale-100"
|
||||||
|
leave-active-class="transition ease-in duration-75"
|
||||||
|
leave-from-class="transform opacity-100 scale-100"
|
||||||
|
leave-to-class="transform opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<MenuItems class="origin-top-right absolute right-0 mt-2 w-56 z-10 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||||
|
<div class="py-1">
|
||||||
|
<MenuItem
|
||||||
|
v-slot="{ active }"
|
||||||
|
class="flex"
|
||||||
|
>
|
||||||
|
<InertiaLink
|
||||||
|
:href="`/holidays/${holiday.id}/edit`"
|
||||||
|
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'font-medium block px-4 py-2 text-sm']"
|
||||||
|
>
|
||||||
|
<PencilIcon
|
||||||
|
class="mr-2 h-5 w-5 text-blue-500"
|
||||||
|
aria-hidden="true"
|
||||||
|
/> Edytuj
|
||||||
|
</InertiaLink>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
v-slot="{ active }"
|
||||||
|
class="flex"
|
||||||
|
>
|
||||||
|
<InertiaLink
|
||||||
|
as="button"
|
||||||
|
method="delete"
|
||||||
|
:preserve-scroll="true"
|
||||||
|
:href="`/holidays/${holiday.id}`"
|
||||||
|
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'block w-full text-left font-medium px-4 py-2 text-sm']"
|
||||||
|
>
|
||||||
|
<TrashIcon
|
||||||
|
class="mr-2 h-5 w-5 text-red-500"
|
||||||
|
aria-hidden="true"
|
||||||
|
/> Usuń
|
||||||
|
</InertiaLink>
|
||||||
|
</MenuItem>
|
||||||
|
</div>
|
||||||
|
</MenuItems>
|
||||||
|
</transition>
|
||||||
|
</Menu>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr
|
||||||
|
v-if="!holidays.data.length"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
colspan="100%"
|
||||||
|
class="text-center py-4 text-xl leading-5 text-gray-700"
|
||||||
|
>
|
||||||
|
Brak danych
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { DotsVerticalIcon, PencilIcon, TrashIcon } from '@heroicons/vue/solid';
|
||||||
|
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'HolidayINdex',
|
||||||
|
components: {
|
||||||
|
DotsVerticalIcon,
|
||||||
|
PencilIcon,
|
||||||
|
TrashIcon,
|
||||||
|
Menu,
|
||||||
|
MenuButton,
|
||||||
|
MenuItem,
|
||||||
|
MenuItems,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
holidays: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
@ -211,7 +211,7 @@ export default {
|
|||||||
lastName: null,
|
lastName: null,
|
||||||
email: null,
|
email: null,
|
||||||
employmentForm: props.employmentForms[0],
|
employmentForm: props.employmentForms[0],
|
||||||
employmentDate: new Date(),
|
employmentDate: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { form };
|
return { form };
|
||||||
|
@ -215,7 +215,7 @@ export default {
|
|||||||
lastName: props.user.lastName,
|
lastName: props.user.lastName,
|
||||||
email: props.user.email,
|
email: props.user.email,
|
||||||
employmentForm: props.employmentForms.find(form => form.value === props.user.employmentForm),
|
employmentForm: props.employmentForms.find(form => form.value === props.user.employmentForm),
|
||||||
employmentDate: new Date(props.user.employmentDate),
|
employmentDate: props.user.employmentDate,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { form };
|
return { form };
|
||||||
|
@ -322,8 +322,7 @@ export default {
|
|||||||
{name: 'Strona główna', href: '/', current: true},
|
{name: 'Strona główna', href: '/', current: true},
|
||||||
{name: 'Użytkownicy', href: '/users', current: false},
|
{name: 'Użytkownicy', href: '/users', current: false},
|
||||||
{name: 'Dostępne urlopy', href: '/vacation-limits', current: false},
|
{name: 'Dostępne urlopy', href: '/vacation-limits', current: false},
|
||||||
{name: 'Company Directory', href: '#', current: false},
|
{name: 'Dni wolne', href: '/holidays', current: false},
|
||||||
{name: 'Openings', href: '#', current: false},
|
|
||||||
];
|
];
|
||||||
const userNavigation = [
|
const userNavigation = [
|
||||||
{name: 'Your Profile', href: '#'},
|
{name: 'Your Profile', href: '#'},
|
||||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Toby\Http\Controllers\GoogleController;
|
use Toby\Http\Controllers\GoogleController;
|
||||||
|
use Toby\Http\Controllers\HolidayController;
|
||||||
use Toby\Http\Controllers\LogoutController;
|
use Toby\Http\Controllers\LogoutController;
|
||||||
use Toby\Http\Controllers\SelectYearPeriodController;
|
use Toby\Http\Controllers\SelectYearPeriodController;
|
||||||
use Toby\Http\Controllers\UserController;
|
use Toby\Http\Controllers\UserController;
|
||||||
@ -14,7 +15,9 @@ Route::middleware("auth")->group(function (): void {
|
|||||||
Route::post("/logout", LogoutController::class);
|
Route::post("/logout", LogoutController::class);
|
||||||
|
|
||||||
Route::resource("users", UserController::class);
|
Route::resource("users", UserController::class);
|
||||||
Route::post("users/{user}/restore", [UserController::class, "restore"])->withTrashed();
|
Route::post("/users/{user}/restore", [UserController::class, "restore"])->withTrashed();
|
||||||
|
|
||||||
|
Route::resource("holidays", HolidayController::class);
|
||||||
|
|
||||||
Route::get("/vacation-limits", [VacationLimitController::class, "edit"])->name("vacation.limits");
|
Route::get("/vacation-limits", [VacationLimitController::class, "edit"])->name("vacation.limits");
|
||||||
Route::put("/vacation-limits", [VacationLimitController::class, "update"]);
|
Route::put("/vacation-limits", [VacationLimitController::class, "update"]);
|
||||||
|
127
tests/Feature/HolidayTest.php
Normal file
127
tests/Feature/HolidayTest.php
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Inertia\Testing\AssertableInertia as Assert;
|
||||||
|
use Tests\FeatureTestCase;
|
||||||
|
use Toby\Models\Holiday;
|
||||||
|
use Toby\Models\User;
|
||||||
|
use Toby\Models\YearPeriod;
|
||||||
|
|
||||||
|
class HolidayTest extends FeatureTestCase
|
||||||
|
{
|
||||||
|
use DatabaseMigrations;
|
||||||
|
|
||||||
|
public function testUserCanSeeHolidayList(): void
|
||||||
|
{
|
||||||
|
Holiday::factory()->count(10)->create();
|
||||||
|
$user = User::factory()->create();
|
||||||
|
|
||||||
|
$this->assertDatabaseCount("holidays", 10);
|
||||||
|
|
||||||
|
$this->actingAs($user)
|
||||||
|
->get("/holidays")
|
||||||
|
->assertInertia(
|
||||||
|
fn(Assert $page) => $page
|
||||||
|
->component("Holidays/Index")
|
||||||
|
->has("holidays.data", 10),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminCanCreateHoliday(): void
|
||||||
|
{
|
||||||
|
$admin = User::factory()->create();
|
||||||
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
|
$this->actingAs($admin)
|
||||||
|
->post("/holidays", [
|
||||||
|
"name" => "Holiday 1",
|
||||||
|
"date" => Carbon::create($currentYearPeriod->year, 5, 20)->toDateString(),
|
||||||
|
])
|
||||||
|
->assertSessionHasNoErrors();
|
||||||
|
|
||||||
|
$this->assertDatabaseHas("holidays", [
|
||||||
|
"name" => "Holiday 1",
|
||||||
|
"date" => Carbon::create($currentYearPeriod->year, 5, 20),
|
||||||
|
"year_period_id" => YearPeriod::current()->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminCannotCreateHolidayForYearPeriodThatDoesntExist(): void
|
||||||
|
{
|
||||||
|
$admin = User::factory()->create();
|
||||||
|
$year = YearPeriod::query()->max("year") + 1;
|
||||||
|
|
||||||
|
$this->actingAs($admin)
|
||||||
|
->post("/holidays", [
|
||||||
|
"name" => "Holiday 1",
|
||||||
|
"date" => Carbon::create($year, 5, 20)->toDateString(),
|
||||||
|
])
|
||||||
|
->assertSessionHasErrors(["date"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminCannotCreateHolidayIfGivenDataIsUsed(): void
|
||||||
|
{
|
||||||
|
$admin = User::factory()->create();
|
||||||
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
$sameDate = Carbon::create($currentYearPeriod->year, 5, 20)->toDateString();
|
||||||
|
|
||||||
|
Holiday::factory()->create([
|
||||||
|
"name" => "Holiday",
|
||||||
|
"date" => $sameDate,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->actingAs($admin)
|
||||||
|
->post("/holidays", [
|
||||||
|
"name" => "Holiday 1",
|
||||||
|
"date" => $sameDate,
|
||||||
|
])
|
||||||
|
->assertSessionHasErrors(["date"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminCanEditHoliday(): void
|
||||||
|
{
|
||||||
|
$admin = User::factory()->create();
|
||||||
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
|
$holiday = Holiday::factory()->create([
|
||||||
|
"name" => "Name to change",
|
||||||
|
"date" => Carbon::create($currentYearPeriod->year, 5, 20),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas("holidays", [
|
||||||
|
"name" => $holiday->name,
|
||||||
|
"date" => $holiday->date->toDateString(),
|
||||||
|
"year_period_id" => $currentYearPeriod->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->actingAs($admin)
|
||||||
|
->put("/holidays/{$holiday->id}", [
|
||||||
|
"name" => "Holiday 1",
|
||||||
|
"date" => Carbon::create($currentYearPeriod->year, 10, 25)->toDateString(),
|
||||||
|
])
|
||||||
|
->assertSessionHasNoErrors();
|
||||||
|
|
||||||
|
$this->assertDatabaseHas("holidays", [
|
||||||
|
"name" => "Holiday 1",
|
||||||
|
"date" => Carbon::create($currentYearPeriod->year, 10, 25)->toDateString(),
|
||||||
|
"year_period_id" => $currentYearPeriod->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAdminCanDeleteHoliday(): void
|
||||||
|
{
|
||||||
|
$admin = User::factory()->create();
|
||||||
|
$holiday = Holiday::factory()->create();
|
||||||
|
|
||||||
|
$this->actingAs($admin)
|
||||||
|
->delete("/holidays/{$holiday->id}")
|
||||||
|
->assertSessionHasNoErrors();
|
||||||
|
|
||||||
|
$this->assertDeleted($holiday);
|
||||||
|
}
|
||||||
|
}
|
@ -89,7 +89,7 @@ class UserTest extends FeatureTestCase
|
|||||||
"lastName" => "Doe",
|
"lastName" => "Doe",
|
||||||
"email" => "john.doe@example.com",
|
"email" => "john.doe@example.com",
|
||||||
"employmentForm" => EmploymentForm::B2B_CONTRACT->value,
|
"employmentForm" => EmploymentForm::B2B_CONTRACT->value,
|
||||||
"employmentDate" => Carbon::now()->toDateTimeString(),
|
"employmentDate" => Carbon::now()->toDateString(),
|
||||||
])
|
])
|
||||||
->assertSessionHasNoErrors();
|
->assertSessionHasNoErrors();
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ class UserTest extends FeatureTestCase
|
|||||||
"last_name" => "Doe",
|
"last_name" => "Doe",
|
||||||
"email" => "john.doe@example.com",
|
"email" => "john.doe@example.com",
|
||||||
"employment_form" => EmploymentForm::B2B_CONTRACT->value,
|
"employment_form" => EmploymentForm::B2B_CONTRACT->value,
|
||||||
"employment_date" => Carbon::now()->toDateTimeString(),
|
"employment_date" => Carbon::now()->toDateString(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ class UserTest extends FeatureTestCase
|
|||||||
"last_name" => $user->last_name,
|
"last_name" => $user->last_name,
|
||||||
"email" => $user->email,
|
"email" => $user->email,
|
||||||
"employment_form" => $user->employment_form->value,
|
"employment_form" => $user->employment_form->value,
|
||||||
"employment_date" => $user->employment_date->toDateTimeString(),
|
"employment_date" => $user->employment_date->toDateString(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->actingAs($admin)
|
$this->actingAs($admin)
|
||||||
@ -123,7 +123,7 @@ class UserTest extends FeatureTestCase
|
|||||||
"lastName" => "Doe",
|
"lastName" => "Doe",
|
||||||
"email" => "john.doe@example.com",
|
"email" => "john.doe@example.com",
|
||||||
"employmentForm" => EmploymentForm::B2B_CONTRACT->value,
|
"employmentForm" => EmploymentForm::B2B_CONTRACT->value,
|
||||||
"employmentDate" => Carbon::now()->toDateTimeString(),
|
"employmentDate" => Carbon::now()->toDateString(),
|
||||||
])
|
])
|
||||||
->assertSessionHasNoErrors();
|
->assertSessionHasNoErrors();
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ class UserTest extends FeatureTestCase
|
|||||||
"last_name" => "Doe",
|
"last_name" => "Doe",
|
||||||
"email" => "john.doe@example.com",
|
"email" => "john.doe@example.com",
|
||||||
"employment_form" => EmploymentForm::B2B_CONTRACT->value,
|
"employment_form" => EmploymentForm::B2B_CONTRACT->value,
|
||||||
"employment_date" => Carbon::now()->toDateTimeString(),
|
"employment_date" => Carbon::now()->toDateString(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ trait InteractsWithYearPeriods
|
|||||||
public function createYearPeriod(int $year): YearPeriod
|
public function createYearPeriod(int $year): YearPeriod
|
||||||
{
|
{
|
||||||
/** @var YearPeriod $yearPeriod */
|
/** @var YearPeriod $yearPeriod */
|
||||||
$yearPeriod = YearPeriod::factory()->create([
|
$yearPeriod = YearPeriod::factory()->createQuietly([
|
||||||
"year" => $year,
|
"year" => $year,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user