#28 - holidays management

This commit is contained in:
Adrian Hopek 2022-01-24 14:03:39 +01:00
parent 6854c7a9f8
commit 29d81030ac
20 changed files with 792 additions and 9 deletions

View 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();
}
}

View 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"));
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Toby\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Carbon;
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", 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,
];
}
}

View 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(),
];
}
}

View 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
View 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);
}
}

View File

@ -4,29 +4,33 @@ declare(strict_types=1);
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\Carbon;
use Illuminate\Support\Collection;
/**
* @property int $id
* @property int $year
* @property Collection $vacationLimits
* @property Collection $holidays
*/
class YearPeriod extends Model
{
use HasFactory;
protected $fillable = [
"year",
];
protected $guarded = [];
public static function current(): ?static
{
static::findByYear(Carbon::now()->year);
}
public static function findByYear(int $year): ?static
{
/** @var YearPeriod $year */
$year = static::query()->where("year", Carbon::now()->year)->first();
$year = static::query()->where("year", $year)->first();
return $year;
}
@ -35,4 +39,9 @@ class YearPeriod extends Model
{
return $this->hasMany(VacationLimit::class);
}
public function holidays(): HasMany
{
return $this->hasMany(Holiday::class);
}
}

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Toby\Observers;
use Toby\Helpers\PolishHolidaysRetriever;
use Toby\Helpers\UserAvatarGenerator;
use Toby\Models\User;
use Toby\Models\YearPeriod;
@ -12,10 +13,17 @@ class YearPeriodObserver
{
public function __construct(
protected UserAvatarGenerator $generator,
protected PolishHolidaysRetriever $polishHolidaysRetriever,
) {
}
public function created(YearPeriod $yearPeriod): void
{
$this->createVacationLimitsFor($yearPeriod);
$this->createHolidaysFor($yearPeriod);
}
protected function createVacationLimitsFor(YearPeriod $yearPeriod): void
{
$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"],
]);
}
}
}

View File

@ -6,6 +6,7 @@ namespace Toby\Providers;
use Illuminate\Support\Carbon;
use Illuminate\Support\ServiceProvider;
use Toby\Models\Holiday;
use Toby\Models\VacationLimit;
use Toby\Scopes\SelectedYearPeriodScope;
@ -15,6 +16,9 @@ class AppServiceProvider extends ServiceProvider
{
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);
}
}

View 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";
}
}

View File

@ -7,6 +7,7 @@
"require": {
"php": "^8.1",
"ext-pdo": "*",
"azuyalabs/yasumi": "^2.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"inertiajs/inertia-laravel": "^0.5.1",

75
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3412dd2a403927b829237ae4db36351a",
"content-hash": "e3c6ffae4c01db02d0471c52d2370b79",
"packages": [
{
"name": "asm89/stack-cors",
@ -62,6 +62,79 @@
},
"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",
"version": "0.9.3",

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class HolidayFactory extends Factory
{
public function definition(): array
{
$now = Carbon::now();
return [
"name" => $this->faker->word,
"date" => $this->faker->dateTimeBetween($now->startOfYear(), $now->endOfYear()),
];
}
}

View File

@ -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");
}
};

View File

@ -7,6 +7,7 @@ namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Toby\Helpers\PolishHolidaysRetriever;
use Toby\Helpers\UserAvatarGenerator;
use Toby\Models\User;
use Toby\Models\VacationLimit;
@ -54,6 +55,16 @@ class DatabaseSeeder extends Seeder
->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();
}

View 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: new Date(),
});
return { form };
},
methods: {
createHoliday() {
this.form.post('/holidays');
},
},
};
</script>

View File

@ -0,0 +1,112 @@
<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: 'HolidayCreate',
components: {
FlatPickr,
},
props: {
holiday: {
type: Object,
default: () => null,
},
},
setup(props) {
const form = useForm({
name: props.holiday.name,
date: new Date(props.holiday.date),
});
return { form };
},
methods: {
editHoliday() {
this.form.put(`/holidays/${this.holiday.id}`);
},
},
};
</script>

View 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>

View File

@ -322,7 +322,7 @@ export default {
{name: 'Strona główna', href: '/', current: true},
{name: 'Użytkownicy', href: '/users', 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 = [

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
use Illuminate\Support\Facades\Route;
use Toby\Http\Controllers\GoogleController;
use Toby\Http\Controllers\HolidayController;
use Toby\Http\Controllers\LogoutController;
use Toby\Http\Controllers\SelectYearPeriodController;
use Toby\Http\Controllers\UserController;
@ -14,7 +15,9 @@ Route::middleware("auth")->group(function (): void {
Route::post("/logout", LogoutController::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::put("/vacation-limits", [VacationLimitController::class, "update"]);