Merge branch 'main' into #43-vacation-summary-for-employee
# Conflicts: # app/Infrastructure/Http/Controllers/HolidayController.php # app/Infrastructure/Http/Controllers/VacationLimitController.php # app/Infrastructure/Http/Controllers/VacationRequestController.php # composer.lock # resources/js/Pages/Holidays/Index.vue # resources/js/Pages/VacationRequest/Create.vue
This commit is contained in:
commit
474707e691
@ -5,13 +5,31 @@ declare(strict_types=1);
|
|||||||
namespace Toby\Architecture\Providers;
|
namespace Toby\Architecture\Providers;
|
||||||
|
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Toby\Domain\Enums\Role;
|
||||||
|
use Toby\Domain\Policies\VacationRequestPolicy;
|
||||||
|
use Toby\Eloquent\Models\User;
|
||||||
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
|
||||||
class AuthServiceProvider extends ServiceProvider
|
class AuthServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
protected $policies = [];
|
protected $policies = [
|
||||||
|
VacationRequest::class => VacationRequestPolicy::class,
|
||||||
|
];
|
||||||
|
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
$this->registerPolicies();
|
$this->registerPolicies();
|
||||||
|
|
||||||
|
Gate::before(function (User $user) {
|
||||||
|
if ($user->role === Role::Administrator) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Gate::define("manageUsers", fn(User $user) => $user->role === Role::AdministrativeApprover);
|
||||||
|
Gate::define("manageHolidays", fn(User $user) => $user->role === Role::AdministrativeApprover);
|
||||||
|
Gate::define("manageVacationLimits", fn(User $user) => $user->role === Role::AdministrativeApprover);
|
||||||
|
Gate::define("generateTimesheet", fn(User $user) => $user->role === Role::AdministrativeApprover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace Toby\Domain;
|
namespace Toby\Domain;
|
||||||
|
|
||||||
use Carbon\CarbonPeriod;
|
use Carbon\CarbonPeriod;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
||||||
use Toby\Eloquent\Models\Vacation;
|
use Toby\Eloquent\Models\Vacation;
|
||||||
use Toby\Eloquent\Models\YearPeriod;
|
use Toby\Eloquent\Models\YearPeriod;
|
||||||
@ -54,7 +54,7 @@ class CalendarGenerator
|
|||||||
{
|
{
|
||||||
return Vacation::query()
|
return Vacation::query()
|
||||||
->whereBetween("date", [$period->start, $period->end])
|
->whereBetween("date", [$period->start, $period->end])
|
||||||
->whereRelation("vacationRequest", "state", VacationRequestState::Approved->value)
|
->whereRelation("vacationRequest", fn(Builder $query) => $query->states(VacationRequestStatesRetriever::successStates()))
|
||||||
->get()
|
->get()
|
||||||
->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString());
|
->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString());
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Toby\Domain\Enums;
|
|
||||||
|
|
||||||
enum VacationRequestState: string
|
|
||||||
{
|
|
||||||
case Created = "created";
|
|
||||||
case Cancelled = "cancelled";
|
|
||||||
case Rejected = "rejected";
|
|
||||||
case Approved = "approved";
|
|
||||||
case WaitingForTechnical = "waiting_for_technical";
|
|
||||||
case WaitingForAdministrative = "waiting_for_administrative";
|
|
||||||
case AcceptedByTechnical = "accepted_by_technical";
|
|
||||||
case AcceptedByAdministrative = "accepted_by_administrative";
|
|
||||||
|
|
||||||
public function label(): string
|
|
||||||
{
|
|
||||||
return __($this->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function pendingStates(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
self::Created,
|
|
||||||
self::WaitingForTechnical,
|
|
||||||
self::WaitingForAdministrative,
|
|
||||||
self::AcceptedByTechnical,
|
|
||||||
self::AcceptedByAdministrative,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function successStates(): array
|
|
||||||
{
|
|
||||||
return [self::Approved];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function failedStates(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
self::Rejected,
|
|
||||||
self::Cancelled,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function filterByStatus(string $filter): array
|
|
||||||
{
|
|
||||||
return match ($filter) {
|
|
||||||
"pending" => VacationRequestState::pendingStates(),
|
|
||||||
"success" => VacationRequestState::successStates(),
|
|
||||||
"failed" => VacationRequestState::failedStates(),
|
|
||||||
default => VacationRequestState::cases(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,7 @@ namespace Toby\Domain\Events;
|
|||||||
|
|
||||||
use Illuminate\Foundation\Events\Dispatchable;
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
use Toby\Domain\States\VacationRequest\VacationRequestState;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
|
||||||
|
51
app/Domain/Policies/VacationRequestPolicy.php
Normal file
51
app/Domain/Policies/VacationRequestPolicy.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\Policies;
|
||||||
|
|
||||||
|
use Toby\Domain\Enums\Role;
|
||||||
|
use Toby\Eloquent\Models\User;
|
||||||
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
|
||||||
|
class VacationRequestPolicy
|
||||||
|
{
|
||||||
|
public function createOnBehalfOfEmployee(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->role === Role::AdministrativeApprover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function acceptAsAdminApprover(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->role === Role::AdministrativeApprover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function acceptAsTechApprover(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->role === Role::TechnicalApprover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function skipFlow(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->role === Role::AdministrativeApprover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject(User $user): bool
|
||||||
|
{
|
||||||
|
return in_array($user->role, [Role::AdministrativeApprover, Role::TechnicalApprover], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cancel(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->role === Role::AdministrativeApprover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(User $user, VacationRequest $vacationRequest): bool
|
||||||
|
{
|
||||||
|
if ($vacationRequest->user->is($user)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array($user->role, [Role::TechnicalApprover, Role::AdministrativeApprover], true);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class AcceptedByAdministrative extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "accepted_by_administrative";
|
||||||
|
}
|
10
app/Domain/States/VacationRequest/AcceptedByTechnical.php
Normal file
10
app/Domain/States/VacationRequest/AcceptedByTechnical.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class AcceptedByTechnical extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "accepted_by_technical";
|
||||||
|
}
|
10
app/Domain/States/VacationRequest/Approved.php
Normal file
10
app/Domain/States/VacationRequest/Approved.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class Approved extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "approved";
|
||||||
|
}
|
10
app/Domain/States/VacationRequest/Cancelled.php
Normal file
10
app/Domain/States/VacationRequest/Cancelled.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class Cancelled extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "cancelled";
|
||||||
|
}
|
10
app/Domain/States/VacationRequest/Created.php
Normal file
10
app/Domain/States/VacationRequest/Created.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class Created extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "created";
|
||||||
|
}
|
10
app/Domain/States/VacationRequest/Rejected.php
Normal file
10
app/Domain/States/VacationRequest/Rejected.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class Rejected extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "rejected";
|
||||||
|
}
|
39
app/Domain/States/VacationRequest/VacationRequestState.php
Normal file
39
app/Domain/States/VacationRequest/VacationRequestState.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
use Spatie\ModelStates\Exceptions\InvalidConfig;
|
||||||
|
use Spatie\ModelStates\State;
|
||||||
|
use Spatie\ModelStates\StateConfig;
|
||||||
|
|
||||||
|
abstract class VacationRequestState extends State
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws InvalidConfig
|
||||||
|
*/
|
||||||
|
public static function config(): StateConfig
|
||||||
|
{
|
||||||
|
return parent::config()
|
||||||
|
->default(Created::class)
|
||||||
|
->allowTransition(Created::class, Approved::class)
|
||||||
|
->allowTransition(Created::class, WaitingForTechnical::class)
|
||||||
|
->allowTransition(Created::class, WaitingForAdministrative::class)
|
||||||
|
->allowTransition(WaitingForTechnical::class, Rejected::class)
|
||||||
|
->allowTransition(WaitingForTechnical::class, AcceptedByTechnical::class)
|
||||||
|
->allowTransition(WaitingForAdministrative::class, Rejected::class)
|
||||||
|
->allowTransition(WaitingForAdministrative::class, AcceptedByAdministrative::class)
|
||||||
|
->allowTransition(AcceptedByTechnical::class, WaitingForAdministrative::class)
|
||||||
|
->allowTransition(AcceptedByTechnical::class, Approved::class)
|
||||||
|
->allowTransition(AcceptedByAdministrative::class, Approved::class)
|
||||||
|
->allowTransition([
|
||||||
|
Created::class,
|
||||||
|
WaitingForTechnical::class,
|
||||||
|
WaitingForAdministrative::class,
|
||||||
|
AcceptedByTechnical::class,
|
||||||
|
AcceptedByAdministrative::class,
|
||||||
|
Approved::class,
|
||||||
|
], Cancelled::class);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class WaitingForAdministrative extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "waiting_for_administrative";
|
||||||
|
}
|
10
app/Domain/States/VacationRequest/WaitingForTechnical.php
Normal file
10
app/Domain/States/VacationRequest/WaitingForTechnical.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain\States\VacationRequest;
|
||||||
|
|
||||||
|
class WaitingForTechnical extends VacationRequestState
|
||||||
|
{
|
||||||
|
public static string $name = "waiting_for_technical";
|
||||||
|
}
|
@ -6,7 +6,6 @@ namespace Toby\Domain;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\YearPeriod;
|
use Toby\Eloquent\Models\YearPeriod;
|
||||||
@ -26,7 +25,7 @@ class UserVacationStatsRetriever
|
|||||||
"vacationRequest",
|
"vacationRequest",
|
||||||
fn(Builder $query) => $query
|
fn(Builder $query) => $query
|
||||||
->whereIn("type", $this->getLimitableVacationTypes())
|
->whereIn("type", $this->getLimitableVacationTypes())
|
||||||
->states(VacationRequestState::successStates()),
|
->states(VacationRequestStatesRetriever::successStates()),
|
||||||
)
|
)
|
||||||
->count();
|
->count();
|
||||||
}
|
}
|
||||||
@ -40,7 +39,7 @@ class UserVacationStatsRetriever
|
|||||||
"vacationRequest",
|
"vacationRequest",
|
||||||
fn(Builder $query) => $query
|
fn(Builder $query) => $query
|
||||||
->whereIn("type", $this->getLimitableVacationTypes())
|
->whereIn("type", $this->getLimitableVacationTypes())
|
||||||
->states(VacationRequestState::pendingStates()),
|
->states(VacationRequestStatesRetriever::pendingStates()),
|
||||||
)
|
)
|
||||||
->count();
|
->count();
|
||||||
}
|
}
|
||||||
@ -54,7 +53,7 @@ class UserVacationStatsRetriever
|
|||||||
"vacationRequest",
|
"vacationRequest",
|
||||||
fn(Builder $query) => $query
|
fn(Builder $query) => $query
|
||||||
->whereIn("type", $this->getNotLimitableVacationTypes())
|
->whereIn("type", $this->getNotLimitableVacationTypes())
|
||||||
->states(VacationRequestState::successStates()),
|
->states(VacationRequestStatesRetriever::successStates()),
|
||||||
)
|
)
|
||||||
->count();
|
->count();
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,24 @@ namespace Toby\Domain;
|
|||||||
|
|
||||||
use Illuminate\Contracts\Auth\Factory as Auth;
|
use Illuminate\Contracts\Auth\Factory as Auth;
|
||||||
use Illuminate\Contracts\Events\Dispatcher;
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Events\VacationRequestAcceptedByAdministrative;
|
use Toby\Domain\Events\VacationRequestAcceptedByAdministrative;
|
||||||
use Toby\Domain\Events\VacationRequestAcceptedByTechnical;
|
use Toby\Domain\Events\VacationRequestAcceptedByTechnical;
|
||||||
use Toby\Domain\Events\VacationRequestApproved;
|
use Toby\Domain\Events\VacationRequestApproved;
|
||||||
use Toby\Domain\Events\VacationRequestCancelled;
|
use Toby\Domain\Events\VacationRequestCancelled;
|
||||||
use Toby\Domain\Events\VacationRequestCreated;
|
use Toby\Domain\Events\VacationRequestCreated;
|
||||||
use Toby\Domain\Events\VacationRequestRejected;
|
use Toby\Domain\Events\VacationRequestRejected;
|
||||||
|
use Toby\Domain\Events\VacationRequestStateChanged;
|
||||||
use Toby\Domain\Events\VacationRequestWaitsForAdminApproval;
|
use Toby\Domain\Events\VacationRequestWaitsForAdminApproval;
|
||||||
use Toby\Domain\Events\VacationRequestWaitsForTechApproval;
|
use Toby\Domain\Events\VacationRequestWaitsForTechApproval;
|
||||||
|
use Toby\Domain\States\VacationRequest\AcceptedByAdministrative;
|
||||||
|
use Toby\Domain\States\VacationRequest\AcceptedByTechnical;
|
||||||
|
use Toby\Domain\States\VacationRequest\Approved;
|
||||||
|
use Toby\Domain\States\VacationRequest\Cancelled;
|
||||||
|
use Toby\Domain\States\VacationRequest\Rejected;
|
||||||
|
use Toby\Domain\States\VacationRequest\VacationRequestState;
|
||||||
|
use Toby\Domain\States\VacationRequest\WaitingForAdministrative;
|
||||||
|
use Toby\Domain\States\VacationRequest\WaitingForTechnical;
|
||||||
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
|
||||||
class VacationRequestStateManager
|
class VacationRequestStateManager
|
||||||
@ -24,64 +33,77 @@ class VacationRequestStateManager
|
|||||||
protected Dispatcher $dispatcher,
|
protected Dispatcher $dispatcher,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function markAsCreated(VacationRequest $vacationRequest): void
|
public function markAsCreated(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::Created);
|
$this->fireStateChangedEvent($vacationRequest, null, $vacationRequest->state, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestCreated($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestCreated($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function approve(VacationRequest $vacationRequest): void
|
public function approve(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::Approved);
|
$this->changeState($vacationRequest, Approved::class, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestApproved($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestApproved($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reject(VacationRequest $vacationRequest): void
|
public function reject(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::Rejected);
|
$this->changeState($vacationRequest, Rejected::class, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestRejected($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestRejected($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancel(VacationRequest $vacationRequest): void
|
public function cancel(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::Cancelled);
|
$this->changeState($vacationRequest, Cancelled::class, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestCancelled($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestCancelled($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function acceptAsTechnical(VacationRequest $vacationRequest): void
|
public function acceptAsTechnical(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::AcceptedByTechnical);
|
$this->changeState($vacationRequest, AcceptedByTechnical::class, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestAcceptedByTechnical($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestAcceptedByTechnical($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function acceptAsAdministrative(VacationRequest $vacationRequest): void
|
public function acceptAsAdministrative(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::AcceptedByAdministrative);
|
$this->changeState($vacationRequest, AcceptedByAdministrative::class, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestAcceptedByAdministrative($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestAcceptedByAdministrative($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function waitForTechnical(VacationRequest $vacationRequest): void
|
public function waitForTechnical(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::WaitingForTechnical);
|
$this->changeState($vacationRequest, WaitingForTechnical::class, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestWaitsForTechApproval($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestWaitsForTechApproval($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function waitForAdministrative(VacationRequest $vacationRequest): void
|
public function waitForAdministrative(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$this->changeState($vacationRequest, VacationRequestState::WaitingForAdministrative);
|
$this->changeState($vacationRequest, WaitingForAdministrative::class, $user);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(new VacationRequestWaitsForAdminApproval($vacationRequest));
|
$this->dispatcher->dispatch(new VacationRequestWaitsForAdminApproval($vacationRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function changeState(VacationRequest $vacationRequest, VacationRequestState $state): void
|
protected function changeState(VacationRequest $vacationRequest, string $state, ?User $user = null): void
|
||||||
{
|
{
|
||||||
$vacationRequest->changeStateTo($state);
|
$previousState = $vacationRequest->state;
|
||||||
|
$vacationRequest->state->transitionTo($state);
|
||||||
|
$vacationRequest->save();
|
||||||
|
|
||||||
|
$this->fireStateChangedEvent($vacationRequest, $previousState, $vacationRequest->state, $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function fireStateChangedEvent(
|
||||||
|
VacationRequest $vacationRequest,
|
||||||
|
?VacationRequestState $from,
|
||||||
|
VacationRequestState $to,
|
||||||
|
?User $user = null,
|
||||||
|
): void {
|
||||||
|
$event = new VacationRequestStateChanged($vacationRequest, $from, $to, $user);
|
||||||
|
$this->dispatcher->dispatch($event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
60
app/Domain/VacationRequestStatesRetriever.php
Normal file
60
app/Domain/VacationRequestStatesRetriever.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain;
|
||||||
|
|
||||||
|
use Toby\Domain\States\VacationRequest\AcceptedByAdministrative;
|
||||||
|
use Toby\Domain\States\VacationRequest\AcceptedByTechnical;
|
||||||
|
use Toby\Domain\States\VacationRequest\Approved;
|
||||||
|
use Toby\Domain\States\VacationRequest\Cancelled;
|
||||||
|
use Toby\Domain\States\VacationRequest\Created;
|
||||||
|
use Toby\Domain\States\VacationRequest\Rejected;
|
||||||
|
use Toby\Domain\States\VacationRequest\WaitingForAdministrative;
|
||||||
|
use Toby\Domain\States\VacationRequest\WaitingForTechnical;
|
||||||
|
|
||||||
|
class VacationRequestStatesRetriever
|
||||||
|
{
|
||||||
|
public static function pendingStates(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Created::class,
|
||||||
|
WaitingForTechnical::class,
|
||||||
|
WaitingForAdministrative::class,
|
||||||
|
AcceptedByTechnical::class,
|
||||||
|
AcceptedByAdministrative::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function successStates(): array
|
||||||
|
{
|
||||||
|
return [Approved::class];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function failedStates(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Rejected::class,
|
||||||
|
Cancelled::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function all(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
...self::pendingStates(),
|
||||||
|
...self::successStates(),
|
||||||
|
...self::failedStates(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function filterByStatus(string $filter): array
|
||||||
|
{
|
||||||
|
return match ($filter) {
|
||||||
|
"pending" => self::pendingStates(),
|
||||||
|
"success" => self::successStates(),
|
||||||
|
"failed" => self::failedStates(),
|
||||||
|
default => self::all(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,9 @@ namespace Toby\Domain\Validation\Rules;
|
|||||||
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
use Toby\Domain\VacationDaysCalculator;
|
use Toby\Domain\VacationDaysCalculator;
|
||||||
|
use Toby\Domain\VacationRequestStatesRetriever;
|
||||||
use Toby\Domain\VacationTypeConfigRetriever;
|
use Toby\Domain\VacationTypeConfigRetriever;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
@ -52,7 +52,7 @@ class DoesNotExceedLimitRule implements VacationRequestRule
|
|||||||
"vacationRequest",
|
"vacationRequest",
|
||||||
fn(Builder $query) => $query
|
fn(Builder $query) => $query
|
||||||
->whereIn("type", $this->getLimitableVacationTypes())
|
->whereIn("type", $this->getLimitableVacationTypes())
|
||||||
->noStates(VacationRequestState::failedStates()),
|
->noStates(VacationRequestStatesRetriever::failedStates()),
|
||||||
)
|
)
|
||||||
->count();
|
->count();
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Domain\Validation\Rules;
|
namespace Toby\Domain\Validation\Rules;
|
||||||
|
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
use Toby\Domain\VacationRequestStatesRetriever;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
|
||||||
class NoApprovedVacationRequestsInRange implements VacationRequestRule
|
class NoApprovedVacationRequestsInRange implements VacationRequestRule
|
||||||
@ -15,7 +15,7 @@ class NoApprovedVacationRequestsInRange implements VacationRequestRule
|
|||||||
->user
|
->user
|
||||||
->vacationRequests()
|
->vacationRequests()
|
||||||
->overlapsWith($vacationRequest)
|
->overlapsWith($vacationRequest)
|
||||||
->states(VacationRequestState::successStates())
|
->states(VacationRequestStatesRetriever::successStates())
|
||||||
->exists();
|
->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Domain\Validation\Rules;
|
namespace Toby\Domain\Validation\Rules;
|
||||||
|
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
use Toby\Domain\VacationRequestStatesRetriever;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
|
||||||
class NoPendingVacationRequestInRange implements VacationRequestRule
|
class NoPendingVacationRequestInRange implements VacationRequestRule
|
||||||
@ -15,7 +15,7 @@ class NoPendingVacationRequestInRange implements VacationRequestRule
|
|||||||
->user
|
->user
|
||||||
->vacationRequests()
|
->vacationRequests()
|
||||||
->overlapsWith($vacationRequest)
|
->overlapsWith($vacationRequest)
|
||||||
->states(VacationRequestState::pendingStates())
|
->states(VacationRequestStatesRetriever::pendingStates())
|
||||||
->exists();
|
->exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
use Spatie\ModelStates\HasStates;
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
|
use Toby\Domain\States\VacationRequest\VacationRequestState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
@ -34,6 +35,7 @@ use Toby\Domain\Enums\VacationType;
|
|||||||
class VacationRequest extends Model
|
class VacationRequest extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use HasStates;
|
||||||
|
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
@ -69,26 +71,14 @@ class VacationRequest extends Model
|
|||||||
return $this->hasMany(Vacation::class);
|
return $this->hasMany(Vacation::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function changeStateTo(VacationRequestState $state): void
|
public function scopeStates(Builder $query, VacationRequestState|array $states): Builder
|
||||||
{
|
{
|
||||||
$this->state = $state;
|
return $query->whereState("state", $states);
|
||||||
|
|
||||||
$this->save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasFlowSkipped(): bool
|
public function scopeNoStates(Builder $query, VacationRequestState|array $states): Builder
|
||||||
{
|
{
|
||||||
return $this->flow_skipped;
|
return $query->whereNotState("state", $states);
|
||||||
}
|
|
||||||
|
|
||||||
public function scopeStates(Builder $query, array $states): Builder
|
|
||||||
{
|
|
||||||
return $query->whereIn("state", $states);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function scopeNoStates(Builder $query, array $states): Builder
|
|
||||||
{
|
|
||||||
return $query->whereNotIn("state", $states);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scopeOverlapsWith(Builder $query, self $vacationRequest): Builder
|
public function scopeOverlapsWith(Builder $query, self $vacationRequest): Builder
|
||||||
@ -97,6 +87,11 @@ class VacationRequest extends Model
|
|||||||
->where("to", ">=", $vacationRequest->from);
|
->where("to", ">=", $vacationRequest->from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasFlowSkipped(): bool
|
||||||
|
{
|
||||||
|
return $this->flow_skipped;
|
||||||
|
}
|
||||||
|
|
||||||
protected static function newFactory(): VacationRequestFactory
|
protected static function newFactory(): VacationRequestFactory
|
||||||
{
|
{
|
||||||
return VacationRequestFactory::new();
|
return VacationRequestFactory::new();
|
||||||
|
@ -8,7 +8,7 @@ use Database\Factories\VacationRequestActivityFactory;
|
|||||||
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\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
use Toby\Domain\States\VacationRequest\VacationRequestState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
|
@ -6,9 +6,6 @@ namespace Toby\Eloquent\Observers;
|
|||||||
|
|
||||||
use Illuminate\Contracts\Auth\Factory as Auth;
|
use Illuminate\Contracts\Auth\Factory as Auth;
|
||||||
use Illuminate\Contracts\Events\Dispatcher;
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Events\VacationRequestStateChanged;
|
|
||||||
use Toby\Eloquent\Models\User;
|
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
|
||||||
class VacationRequestObserver
|
class VacationRequestObserver
|
||||||
@ -28,31 +25,4 @@ class VacationRequestObserver
|
|||||||
|
|
||||||
$vacationRequest->name = "{$vacationRequestNumber}/${year}";
|
$vacationRequest->name = "{$vacationRequestNumber}/${year}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saved(VacationRequest $vacationRequest): void
|
|
||||||
{
|
|
||||||
if ($vacationRequest->isDirty("state")) {
|
|
||||||
$previousState = $vacationRequest->getOriginal("state");
|
|
||||||
|
|
||||||
$this->fireStateChangedEvent($vacationRequest, $previousState, $vacationRequest->state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function fireStateChangedEvent(
|
|
||||||
VacationRequest $vacationRequest,
|
|
||||||
?VacationRequestState $from,
|
|
||||||
VacationRequestState $to,
|
|
||||||
): void {
|
|
||||||
$event = new VacationRequestStateChanged($vacationRequest, $from, $to, $this->getAuthUser());
|
|
||||||
|
|
||||||
$this->dispatcher->dispatch($event);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAuthUser(): ?User
|
|
||||||
{
|
|
||||||
/** @var User $user */
|
|
||||||
$user = $this->auth->guard()->user();
|
|
||||||
|
|
||||||
return $user;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,8 @@ use Illuminate\Database\Eloquent\Builder;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\UserVacationStatsRetriever;
|
use Toby\Domain\UserVacationStatsRetriever;
|
||||||
|
use Toby\Domain\VacationRequestStatesRetriever;
|
||||||
use Toby\Eloquent\Models\Holiday;
|
use Toby\Eloquent\Models\Holiday;
|
||||||
use Toby\Eloquent\Models\Vacation;
|
use Toby\Eloquent\Models\Vacation;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
@ -31,7 +31,7 @@ class DashboardController extends Controller
|
|||||||
->whereDate("date", $now)
|
->whereDate("date", $now)
|
||||||
->whereRelation(
|
->whereRelation(
|
||||||
"vacationRequest",
|
"vacationRequest",
|
||||||
fn(Builder $query) => $query->states(VacationRequestState::successStates()),
|
fn(Builder $query) => $query->states(VacationRequestStatesRetriever::successStates()),
|
||||||
)
|
)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Infrastructure\Http\Controllers;
|
namespace Toby\Infrastructure\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
||||||
use Toby\Eloquent\Models\Holiday;
|
use Toby\Eloquent\Models\Holiday;
|
||||||
@ -14,7 +16,7 @@ use Toby\Infrastructure\Http\Resources\HolidayResource;
|
|||||||
|
|
||||||
class HolidayController extends Controller
|
class HolidayController extends Controller
|
||||||
{
|
{
|
||||||
public function index(YearPeriodRetriever $yearPeriodRetriever): Response
|
public function index(Request $request, YearPeriodRetriever $yearPeriodRetriever): Response
|
||||||
{
|
{
|
||||||
$yearPeriod = $yearPeriodRetriever->selected();
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
|
|
||||||
@ -25,16 +27,29 @@ class HolidayController extends Controller
|
|||||||
|
|
||||||
return inertia("Holidays/Index", [
|
return inertia("Holidays/Index", [
|
||||||
"holidays" => HolidayResource::collection($holidays),
|
"holidays" => HolidayResource::collection($holidays),
|
||||||
|
"can" => [
|
||||||
|
"manageHolidays" => $request->user()->can("manageHolidays"),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function create(): Response
|
public function create(): Response
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageHolidays");
|
||||||
|
|
||||||
return inertia("Holidays/Create");
|
return inertia("Holidays/Create");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function store(HolidayRequest $request): RedirectResponse
|
public function store(HolidayRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageHolidays");
|
||||||
|
|
||||||
Holiday::query()->create($request->data());
|
Holiday::query()->create($request->data());
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
@ -42,15 +57,25 @@ class HolidayController extends Controller
|
|||||||
->with("success", __("Holiday has been created."));
|
->with("success", __("Holiday has been created."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function edit(Holiday $holiday): Response
|
public function edit(Holiday $holiday): Response
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageHolidays");
|
||||||
|
|
||||||
return inertia("Holidays/Edit", [
|
return inertia("Holidays/Edit", [
|
||||||
"holiday" => new HolidayFormDataResource($holiday),
|
"holiday" => new HolidayFormDataResource($holiday),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function update(HolidayRequest $request, Holiday $holiday): RedirectResponse
|
public function update(HolidayRequest $request, Holiday $holiday): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageHolidays");
|
||||||
|
|
||||||
$holiday->update($request->data());
|
$holiday->update($request->data());
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
@ -58,8 +83,13 @@ class HolidayController extends Controller
|
|||||||
->with("success", __("Holiday has been updated."));
|
->with("success", __("Holiday has been updated."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function destroy(Holiday $holiday): RedirectResponse
|
public function destroy(Holiday $holiday): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageHolidays");
|
||||||
|
|
||||||
$holiday->delete();
|
$holiday->delete();
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
|
@ -16,6 +16,8 @@ class TimesheetController extends Controller
|
|||||||
{
|
{
|
||||||
public function __invoke(Month $month, YearPeriodRetriever $yearPeriodRetriever): BinaryFileResponse
|
public function __invoke(Month $month, YearPeriodRetriever $yearPeriodRetriever): BinaryFileResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("generateTimesheet");
|
||||||
|
|
||||||
$yearPeriod = $yearPeriodRetriever->selected();
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
$carbonMonth = Carbon::create($yearPeriod->year, $month->toCarbonNumber());
|
$carbonMonth = Carbon::create($yearPeriod->year, $month->toCarbonNumber());
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Infrastructure\Http\Controllers;
|
namespace Toby\Infrastructure\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
@ -16,8 +17,13 @@ use Toby\Infrastructure\Http\Resources\UserResource;
|
|||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function index(Request $request): Response
|
public function index(Request $request): Response
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageUsers");
|
||||||
|
|
||||||
$users = User::query()
|
$users = User::query()
|
||||||
->withTrashed()
|
->withTrashed()
|
||||||
->search($request->query("search"))
|
->search($request->query("search"))
|
||||||
@ -32,16 +38,26 @@ class UserController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function create(): Response
|
public function create(): Response
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageUsers");
|
||||||
|
|
||||||
return inertia("Users/Create", [
|
return inertia("Users/Create", [
|
||||||
"employmentForms" => EmploymentForm::casesToSelect(),
|
"employmentForms" => EmploymentForm::casesToSelect(),
|
||||||
"roles" => Role::casesToSelect(),
|
"roles" => Role::casesToSelect(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function store(UserRequest $request): RedirectResponse
|
public function store(UserRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageUsers");
|
||||||
|
|
||||||
User::query()->create($request->data());
|
User::query()->create($request->data());
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
@ -49,8 +65,13 @@ class UserController extends Controller
|
|||||||
->with("success", __("User has been created."));
|
->with("success", __("User has been created."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function edit(User $user): Response
|
public function edit(User $user): Response
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageUsers");
|
||||||
|
|
||||||
return inertia("Users/Edit", [
|
return inertia("Users/Edit", [
|
||||||
"user" => new UserFormDataResource($user),
|
"user" => new UserFormDataResource($user),
|
||||||
"employmentForms" => EmploymentForm::casesToSelect(),
|
"employmentForms" => EmploymentForm::casesToSelect(),
|
||||||
@ -58,8 +79,13 @@ class UserController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function update(UserRequest $request, User $user): RedirectResponse
|
public function update(UserRequest $request, User $user): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageUsers");
|
||||||
|
|
||||||
$user->update($request->data());
|
$user->update($request->data());
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
@ -67,8 +93,13 @@ class UserController extends Controller
|
|||||||
->with("success", __("User has been updated."));
|
->with("success", __("User has been updated."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function destroy(User $user): RedirectResponse
|
public function destroy(User $user): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageUsers");
|
||||||
|
|
||||||
$user->delete();
|
$user->delete();
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
@ -76,8 +107,13 @@ class UserController extends Controller
|
|||||||
->with("success", __("User has been deleted."));
|
->with("success", __("User has been deleted."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function restore(User $user): RedirectResponse
|
public function restore(User $user): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageUsers");
|
||||||
|
|
||||||
$user->restore();
|
$user->restore();
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Infrastructure\Http\Controllers;
|
namespace Toby\Infrastructure\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
use Toby\Domain\CalendarGenerator;
|
use Toby\Domain\CalendarGenerator;
|
||||||
@ -15,6 +16,7 @@ use Toby\Infrastructure\Http\Resources\UserResource;
|
|||||||
class VacationCalendarController extends Controller
|
class VacationCalendarController extends Controller
|
||||||
{
|
{
|
||||||
public function index(
|
public function index(
|
||||||
|
Request $request,
|
||||||
YearPeriodRetriever $yearPeriodRetriever,
|
YearPeriodRetriever $yearPeriodRetriever,
|
||||||
CalendarGenerator $calendarGenerator,
|
CalendarGenerator $calendarGenerator,
|
||||||
?string $month = null,
|
?string $month = null,
|
||||||
@ -35,6 +37,9 @@ class VacationCalendarController extends Controller
|
|||||||
"calendar" => $calendar,
|
"calendar" => $calendar,
|
||||||
"currentMonth" => $month->value,
|
"currentMonth" => $month->value,
|
||||||
"users" => UserResource::collection($users),
|
"users" => UserResource::collection($users),
|
||||||
|
"can" => [
|
||||||
|
"generateTimesheet" => $request->user()->can("generateTimesheet"),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ class VacationLimitController extends Controller
|
|||||||
{
|
{
|
||||||
public function edit(YearPeriodRetriever $yearPeriodRetriever, UserVacationStatsRetriever $statsRetriever): Response
|
public function edit(YearPeriodRetriever $yearPeriodRetriever, UserVacationStatsRetriever $statsRetriever): Response
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageVacationLimits");
|
||||||
|
|
||||||
$yearPeriod = $yearPeriodRetriever->selected();
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
$previousYearPeriod = YearPeriod::findByYear($yearPeriod->year - 1);
|
$previousYearPeriod = YearPeriod::findByYear($yearPeriod->year - 1);
|
||||||
|
|
||||||
@ -44,6 +46,8 @@ class VacationLimitController extends Controller
|
|||||||
|
|
||||||
public function update(VacationLimitRequest $request): RedirectResponse
|
public function update(VacationLimitRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("manageVacationLimits");
|
||||||
|
|
||||||
$data = $request->data();
|
$data = $request->data();
|
||||||
|
|
||||||
foreach ($request->vacationLimits() as $limit) {
|
foreach ($request->vacationLimits() as $limit) {
|
||||||
|
@ -5,15 +5,21 @@ declare(strict_types=1);
|
|||||||
namespace Toby\Infrastructure\Http\Controllers;
|
namespace Toby\Infrastructure\Http\Controllers;
|
||||||
|
|
||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response as LaravelResponse;
|
use Illuminate\Http\Response as LaravelResponse;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
|
use Toby\Domain\States\VacationRequest\AcceptedByAdministrative;
|
||||||
|
use Toby\Domain\States\VacationRequest\AcceptedByTechnical;
|
||||||
|
use Toby\Domain\States\VacationRequest\Cancelled;
|
||||||
|
use Toby\Domain\States\VacationRequest\Rejected;
|
||||||
use Toby\Domain\VacationDaysCalculator;
|
use Toby\Domain\VacationDaysCalculator;
|
||||||
use Toby\Domain\VacationRequestStateManager;
|
use Toby\Domain\VacationRequestStateManager;
|
||||||
|
use Toby\Domain\VacationRequestStatesRetriever;
|
||||||
use Toby\Domain\Validation\VacationRequestValidator;
|
use Toby\Domain\Validation\VacationRequestValidator;
|
||||||
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
@ -34,7 +40,7 @@ class VacationRequestController extends Controller
|
|||||||
->with("vacations")
|
->with("vacations")
|
||||||
->where("year_period_id", $yearPeriodRetriever->selected()->id)
|
->where("year_period_id", $yearPeriodRetriever->selected()->id)
|
||||||
->latest()
|
->latest()
|
||||||
->states(VacationRequestState::filterByStatus($status))
|
->states(VacationRequestStatesRetriever::filterByStatus($status))
|
||||||
->paginate();
|
->paginate();
|
||||||
|
|
||||||
return inertia("VacationRequest/Index", [
|
return inertia("VacationRequest/Index", [
|
||||||
@ -45,16 +51,37 @@ class VacationRequestController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show(VacationRequest $vacationRequest): Response
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
|
public function show(Request $request, VacationRequest $vacationRequest): Response
|
||||||
{
|
{
|
||||||
|
$this->authorize("show", $vacationRequest);
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
return inertia("VacationRequest/Show", [
|
return inertia("VacationRequest/Show", [
|
||||||
"request" => new VacationRequestResource($vacationRequest),
|
"request" => new VacationRequestResource($vacationRequest),
|
||||||
"activities" => VacationRequestActivityResource::collection($vacationRequest->activities),
|
"activities" => VacationRequestActivityResource::collection($vacationRequest->activities),
|
||||||
|
"can" => [
|
||||||
|
"acceptAsTechnical" => $vacationRequest->state->canTransitionTo(AcceptedByTechnical::class)
|
||||||
|
&& $user->can("acceptAsTechApprover", $vacationRequest),
|
||||||
|
"acceptAsAdministrative" => $vacationRequest->state->canTransitionTo(AcceptedByAdministrative::class)
|
||||||
|
&& $user->can("acceptAsAdminApprover", $vacationRequest),
|
||||||
|
"reject" => $vacationRequest->state->canTransitionTo(Rejected::class)
|
||||||
|
&& $user->can("reject", $vacationRequest),
|
||||||
|
"cancel" => $vacationRequest->state->canTransitionTo(Cancelled::class)
|
||||||
|
&& $user->can("cancel", $vacationRequest),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function download(VacationRequest $vacationRequest): LaravelResponse
|
public function download(VacationRequest $vacationRequest): LaravelResponse
|
||||||
{
|
{
|
||||||
|
$this->authorize("show", $vacationRequest);
|
||||||
|
|
||||||
$pdf = PDF::loadView("pdf.vacation-request", [
|
$pdf = PDF::loadView("pdf.vacation-request", [
|
||||||
"vacationRequest" => $vacationRequest,
|
"vacationRequest" => $vacationRequest,
|
||||||
]);
|
]);
|
||||||
@ -62,7 +89,7 @@ class VacationRequestController extends Controller
|
|||||||
return $pdf->stream();
|
return $pdf->stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(YearPeriodRetriever $yearPeriodRetriever): Response
|
public function create(Request $request, YearPeriodRetriever $yearPeriodRetriever): Response
|
||||||
{
|
{
|
||||||
$yearPeriod = $yearPeriodRetriever->selected();
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
|
|
||||||
@ -78,15 +105,31 @@ class VacationRequestController extends Controller
|
|||||||
return inertia("VacationRequest/Create", [
|
return inertia("VacationRequest/Create", [
|
||||||
"vacationTypes" => VacationType::casesToSelect(),
|
"vacationTypes" => VacationType::casesToSelect(),
|
||||||
"users" => UserResource::collection($users),
|
"users" => UserResource::collection($users),
|
||||||
|
"can" => [
|
||||||
|
"createOnBehalfOfEmployee" => $request->user()->can("createOnBehalfOfEmployee", VacationRequest::class),
|
||||||
|
"skipFlow" => $request->user()->can("skipFlow", VacationRequest::class),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
public function store(
|
public function store(
|
||||||
VacationRequestRequest $request,
|
VacationRequestRequest $request,
|
||||||
VacationRequestValidator $vacationRequestValidator,
|
VacationRequestValidator $vacationRequestValidator,
|
||||||
VacationRequestStateManager $stateManager,
|
VacationRequestStateManager $stateManager,
|
||||||
VacationDaysCalculator $vacationDaysCalculator,
|
VacationDaysCalculator $vacationDaysCalculator,
|
||||||
): RedirectResponse {
|
): RedirectResponse {
|
||||||
|
if ($request->createsOnBehalfOfEmployee()) {
|
||||||
|
$this->authorize("createOnBehalfOfEmployee", VacationRequest::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->wantsSkipFlow()) {
|
||||||
|
$this->authorize("skipFlow", VacationRequest::class);
|
||||||
|
}
|
||||||
|
|
||||||
/** @var VacationRequest $vacationRequest */
|
/** @var VacationRequest $vacationRequest */
|
||||||
$vacationRequest = $request->user()->createdVacationRequests()->make($request->data());
|
$vacationRequest = $request->user()->createdVacationRequests()->make($request->data());
|
||||||
$vacationRequestValidator->validate($vacationRequest);
|
$vacationRequestValidator->validate($vacationRequest);
|
||||||
@ -107,48 +150,72 @@ class VacationRequestController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$stateManager->markAsCreated($vacationRequest);
|
$stateManager->markAsCreated($vacationRequest, $request->user());
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
->route("vacation.requests.show", $vacationRequest)
|
->route("vacation.requests.show", $vacationRequest)
|
||||||
->with("success", __("Vacation request has been created."));
|
->with("success", __("Vacation request has been created."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function reject(
|
public function reject(
|
||||||
|
Request $request,
|
||||||
VacationRequest $vacationRequest,
|
VacationRequest $vacationRequest,
|
||||||
VacationRequestStateManager $stateManager,
|
VacationRequestStateManager $stateManager,
|
||||||
): RedirectResponse {
|
): RedirectResponse {
|
||||||
$stateManager->reject($vacationRequest);
|
$this->authorize("reject", $vacationRequest);
|
||||||
|
|
||||||
|
$stateManager->reject($vacationRequest, $request->user());
|
||||||
|
|
||||||
return redirect()->back()
|
return redirect()->back()
|
||||||
->with("success", __("Vacation request has been rejected."));
|
->with("success", __("Vacation request has been rejected."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function cancel(
|
public function cancel(
|
||||||
|
Request $request,
|
||||||
VacationRequest $vacationRequest,
|
VacationRequest $vacationRequest,
|
||||||
VacationRequestStateManager $stateManager,
|
VacationRequestStateManager $stateManager,
|
||||||
): RedirectResponse {
|
): RedirectResponse {
|
||||||
$stateManager->cancel($vacationRequest);
|
$this->authorize("cancel", $vacationRequest);
|
||||||
|
|
||||||
|
$stateManager->cancel($vacationRequest, $request->user());
|
||||||
|
|
||||||
return redirect()->back()
|
return redirect()->back()
|
||||||
->with("success", __("Vacation request has been cancelled."));
|
->with("success", __("Vacation request has been cancelled."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function acceptAsTechnical(
|
public function acceptAsTechnical(
|
||||||
|
Request $request,
|
||||||
VacationRequest $vacationRequest,
|
VacationRequest $vacationRequest,
|
||||||
VacationRequestStateManager $stateManager,
|
VacationRequestStateManager $stateManager,
|
||||||
): RedirectResponse {
|
): RedirectResponse {
|
||||||
$stateManager->acceptAsTechnical($vacationRequest);
|
$this->authorize("acceptAsTechApprover", $vacationRequest);
|
||||||
|
|
||||||
|
$stateManager->acceptAsTechnical($vacationRequest, $request->user());
|
||||||
|
|
||||||
return redirect()->back()
|
return redirect()->back()
|
||||||
->with("success", __("Vacation request has been accepted."));
|
->with("success", __("Vacation request has been accepted."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
public function acceptAsAdministrative(
|
public function acceptAsAdministrative(
|
||||||
|
Request $request,
|
||||||
VacationRequest $vacationRequest,
|
VacationRequest $vacationRequest,
|
||||||
VacationRequestStateManager $stateManager,
|
VacationRequestStateManager $stateManager,
|
||||||
): RedirectResponse {
|
): RedirectResponse {
|
||||||
$stateManager->acceptAsAdministrative($vacationRequest);
|
$this->authorize("acceptAsAdminApprover", $vacationRequest);
|
||||||
|
|
||||||
|
$stateManager->acceptAsAdministrative($vacationRequest, $request->user());
|
||||||
|
|
||||||
return redirect()->back()
|
return redirect()->back()
|
||||||
->with("success", __("Vacation request has been accepted."));
|
->with("success", __("Vacation request has been accepted."));
|
||||||
|
@ -22,6 +22,10 @@ class HandleInertiaRequests extends Middleware
|
|||||||
return array_merge(parent::share($request), [
|
return array_merge(parent::share($request), [
|
||||||
"auth" => fn() => [
|
"auth" => fn() => [
|
||||||
"user" => $user ? new UserResource($user) : null,
|
"user" => $user ? new UserResource($user) : null,
|
||||||
|
"can" => [
|
||||||
|
"manageVacationLimits" => $user ? $user->can("manageVacationLimits") : false,
|
||||||
|
"manageUsers" => $user ? $user->can("manageUsers") : false,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
"flash" => fn() => [
|
"flash" => fn() => [
|
||||||
"success" => $request->session()->get("success"),
|
"success" => $request->session()->get("success"),
|
||||||
|
@ -27,16 +27,29 @@ class VacationRequestRequest extends FormRequest
|
|||||||
|
|
||||||
public function data(): array
|
public function data(): array
|
||||||
{
|
{
|
||||||
$from = $this->get("from");
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
"user_id" => $this->get("user"),
|
"user_id" => $this->get("user"),
|
||||||
"type" => $this->get("type"),
|
"type" => $this->get("type"),
|
||||||
"from" => $from,
|
"from" => $this->get("from"),
|
||||||
"to" => $this->get("to"),
|
"to" => $this->get("to"),
|
||||||
"year_period_id" => YearPeriod::findByYear(Carbon::create($from)->year)->id,
|
"year_period_id" => $this->yearPeriod()->id,
|
||||||
"comment" => $this->get("comment"),
|
"comment" => $this->get("comment"),
|
||||||
"flow_skipped" => $this->boolean("flowSkipped"),
|
"flow_skipped" => $this->boolean("flowSkipped"),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function yearPeriod(): YearPeriod
|
||||||
|
{
|
||||||
|
return YearPeriod::findByYear(Carbon::create($this->get("from"))->year);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createsOnBehalfOfEmployee(): bool
|
||||||
|
{
|
||||||
|
return $this->user()->id !== $this->get("user");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function wantsSkipFlow(): bool
|
||||||
|
{
|
||||||
|
return $this->boolean("flowSkipped");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ class VacationRequestActivityResource extends JsonResource
|
|||||||
"time" => $this->created_at->format("H:i"),
|
"time" => $this->created_at->format("H:i"),
|
||||||
"user" => $this->user ? $this->user->fullName : __("System"),
|
"user" => $this->user ? $this->user->fullName : __("System"),
|
||||||
"state" => $this->to,
|
"state" => $this->to,
|
||||||
"text" => $this->to->label(),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,9 @@
|
|||||||
"laravel/telescope": "^4.6",
|
"laravel/telescope": "^4.6",
|
||||||
"laravel/tinker": "^2.5",
|
"laravel/tinker": "^2.5",
|
||||||
"lasserafn/php-initial-avatar-generator": "^4.2",
|
"lasserafn/php-initial-avatar-generator": "^4.2",
|
||||||
"maatwebsite/excel": "^3.1",
|
"spatie/laravel-google-calendar": "^3.5",
|
||||||
"spatie/laravel-google-calendar": "^3.5"
|
"spatie/laravel-model-states": "^2.1",
|
||||||
|
"maatwebsite/excel": "^3.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"blumilksoftware/codestyle": "^0.10.0",
|
"blumilksoftware/codestyle": "^0.10.0",
|
||||||
|
263
composer.lock
generated
263
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": "1b7f51398015d1bd1a03e5910dc2d72c",
|
"content-hash": "d3f019c6e743a3249af78baefe7acb01",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asm89/stack-cors",
|
"name": "asm89/stack-cors",
|
||||||
@ -760,6 +760,59 @@
|
|||||||
},
|
},
|
||||||
"time": "2021-12-25T01:21:49+00:00"
|
"time": "2021-12-25T01:21:49+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "facade/ignition-contracts",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/facade/ignition-contracts.git",
|
||||||
|
"reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/facade/ignition-contracts/zipball/3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
|
||||||
|
"reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.3|^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^v2.15.8",
|
||||||
|
"phpunit/phpunit": "^9.3.11",
|
||||||
|
"vimeo/psalm": "^3.17.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Facade\\IgnitionContracts\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"homepage": "https://flareapp.io",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Solution contracts for Ignition",
|
||||||
|
"homepage": "https://github.com/facade/ignition-contracts",
|
||||||
|
"keywords": [
|
||||||
|
"contracts",
|
||||||
|
"flare",
|
||||||
|
"ignition"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/facade/ignition-contracts/issues",
|
||||||
|
"source": "https://github.com/facade/ignition-contracts/tree/1.0.2"
|
||||||
|
},
|
||||||
|
"time": "2020-10-16T08:27:54+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "firebase/php-jwt",
|
"name": "firebase/php-jwt",
|
||||||
"version": "v5.5.1",
|
"version": "v5.5.1",
|
||||||
@ -4924,6 +4977,139 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-01-13T09:43:27+00:00"
|
"time": "2022-01-13T09:43:27+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/laravel-model-states",
|
||||||
|
"version": "2.1.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/laravel-model-states.git",
|
||||||
|
"reference": "c9c4865abd2b5ec534214aede784631366bed7d4"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/laravel-model-states/zipball/c9c4865abd2b5ec534214aede784631366bed7d4",
|
||||||
|
"reference": "c9c4865abd2b5ec534214aede784631366bed7d4",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"facade/ignition-contracts": "^1.0",
|
||||||
|
"illuminate/contracts": "^8.73 | ^9.0",
|
||||||
|
"illuminate/database": "^8.73 | ^9.0",
|
||||||
|
"illuminate/support": "^8.73 | ^9.0",
|
||||||
|
"php": "^7.4|^8.0",
|
||||||
|
"spatie/laravel-package-tools": "^1.9"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"orchestra/testbench": "^6.23 | ^7.0",
|
||||||
|
"phpunit/phpunit": "^9.4",
|
||||||
|
"symfony/var-dumper": "^5.3 | ^6.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Spatie\\ModelStates\\ModelStatesServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\ModelStates\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Brent Roose",
|
||||||
|
"email": "brent@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "State support for Eloquent models",
|
||||||
|
"homepage": "https://github.com/spatie/laravel-model-states",
|
||||||
|
"keywords": [
|
||||||
|
"spatie",
|
||||||
|
"state"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/spatie/laravel-model-states/tree/2.1.4"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-01-19T19:57:35+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/laravel-package-tools",
|
||||||
|
"version": "1.11.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/laravel-package-tools.git",
|
||||||
|
"reference": "16a8de828e7f1f32d580c667e1de5bf2943abd6b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/16a8de828e7f1f32d580c667e1de5bf2943abd6b",
|
||||||
|
"reference": "16a8de828e7f1f32d580c667e1de5bf2943abd6b",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/contracts": "^7.0|^8.0|^9.0",
|
||||||
|
"php": "^7.4|^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.4",
|
||||||
|
"orchestra/testbench": "^5.0|^6.23|^7.0",
|
||||||
|
"phpunit/phpunit": "^9.4",
|
||||||
|
"spatie/test-time": "^1.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\LaravelPackageTools\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Tools for creating Laravel packages",
|
||||||
|
"homepage": "https://github.com/spatie/laravel-package-tools",
|
||||||
|
"keywords": [
|
||||||
|
"laravel-package-tools",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/laravel-package-tools/issues",
|
||||||
|
"source": "https://github.com/spatie/laravel-package-tools/tree/1.11.2"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-02-22T08:55:13+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v6.0.5",
|
"version": "v6.0.5",
|
||||||
@ -7687,59 +7873,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2020-11-10T18:47:58+00:00"
|
"time": "2020-11-10T18:47:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "facade/ignition-contracts",
|
|
||||||
"version": "1.0.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/facade/ignition-contracts.git",
|
|
||||||
"reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/facade/ignition-contracts/zipball/3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
|
|
||||||
"reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.3|^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"friendsofphp/php-cs-fixer": "^v2.15.8",
|
|
||||||
"phpunit/phpunit": "^9.3.11",
|
|
||||||
"vimeo/psalm": "^3.17.1"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Facade\\IgnitionContracts\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Freek Van der Herten",
|
|
||||||
"email": "freek@spatie.be",
|
|
||||||
"homepage": "https://flareapp.io",
|
|
||||||
"role": "Developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Solution contracts for Ignition",
|
|
||||||
"homepage": "https://github.com/facade/ignition-contracts",
|
|
||||||
"keywords": [
|
|
||||||
"contracts",
|
|
||||||
"flare",
|
|
||||||
"ignition"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/facade/ignition-contracts/issues",
|
|
||||||
"source": "https://github.com/facade/ignition-contracts/tree/1.0.2"
|
|
||||||
},
|
|
||||||
"time": "2020-10-16T08:27:54+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "fakerphp/faker",
|
"name": "fakerphp/faker",
|
||||||
"version": "v1.19.0",
|
"version": "v1.19.0",
|
||||||
@ -10259,16 +10392,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/flare-client-php",
|
"name": "spatie/flare-client-php",
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/spatie/flare-client-php.git",
|
"url": "https://github.com/spatie/flare-client-php.git",
|
||||||
"reference": "edf253c68fba62cdb29ad6b48e211e29691dcee8"
|
"reference": "8ada1e5f4d7a2869f491c5e75d1f689b69db423e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/edf253c68fba62cdb29ad6b48e211e29691dcee8",
|
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/8ada1e5f4d7a2869f491c5e75d1f689b69db423e",
|
||||||
"reference": "edf253c68fba62cdb29ad6b48e211e29691dcee8",
|
"reference": "8ada1e5f4d7a2869f491c5e75d1f689b69db423e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -10311,7 +10444,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/spatie/flare-client-php/issues",
|
"issues": "https://github.com/spatie/flare-client-php/issues",
|
||||||
"source": "https://github.com/spatie/flare-client-php/tree/1.0.4"
|
"source": "https://github.com/spatie/flare-client-php/tree/1.0.5"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -10319,20 +10452,20 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-02-28T15:04:23+00:00"
|
"time": "2022-03-01T10:52:59+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/ignition",
|
"name": "spatie/ignition",
|
||||||
"version": "1.0.5",
|
"version": "1.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/spatie/ignition.git",
|
"url": "https://github.com/spatie/ignition.git",
|
||||||
"reference": "6b7bb804f4834b080f5ac941f6ac6800a485011e"
|
"reference": "8ecde033600064e3ffdbf804deec0dcb05004387"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/spatie/ignition/zipball/6b7bb804f4834b080f5ac941f6ac6800a485011e",
|
"url": "https://api.github.com/repos/spatie/ignition/zipball/8ecde033600064e3ffdbf804deec0dcb05004387",
|
||||||
"reference": "6b7bb804f4834b080f5ac941f6ac6800a485011e",
|
"reference": "8ecde033600064e3ffdbf804deec0dcb05004387",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -10390,7 +10523,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-02-17T21:40:47+00:00"
|
"time": "2022-03-01T17:01:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/laravel-ignition",
|
"name": "spatie/laravel-ignition",
|
||||||
|
7
config/model-states.php
Normal file
7
config/model-states.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
return [
|
||||||
|
"default_transition" => Spatie\ModelStates\DefaultTransition::class,
|
||||||
|
];
|
@ -28,4 +28,25 @@ class UserFactory extends Factory
|
|||||||
"remember_token" => Str::random(10),
|
"remember_token" => Str::random(10),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function admin(): static
|
||||||
|
{
|
||||||
|
return $this->state([
|
||||||
|
"role" => Role::Administrator,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function technicalApprover(): static
|
||||||
|
{
|
||||||
|
return $this->state([
|
||||||
|
"role" => Role::TechnicalApprover,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function administrativeApprover(): static
|
||||||
|
{
|
||||||
|
return $this->state([
|
||||||
|
"role" => Role::AdministrativeApprover,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ namespace Database\Factories;
|
|||||||
|
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
|
use Toby\Domain\VacationRequestStatesRetriever;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
use Toby\Eloquent\Models\YearPeriod;
|
use Toby\Eloquent\Models\YearPeriod;
|
||||||
@ -28,7 +28,7 @@ class VacationRequestFactory extends Factory
|
|||||||
"year_period_id" => YearPeriod::factory(),
|
"year_period_id" => YearPeriod::factory(),
|
||||||
"name" => fn(array $attributes): string => $this->generateName($attributes),
|
"name" => fn(array $attributes): string => $this->generateName($attributes),
|
||||||
"type" => $this->faker->randomElement(VacationType::cases()),
|
"type" => $this->faker->randomElement(VacationType::cases()),
|
||||||
"state" => $this->faker->randomElement(VacationRequestState::cases()),
|
"state" => $this->faker->randomElement(VacationRequestStatesRetriever::all()),
|
||||||
"from" => $from,
|
"from" => $from,
|
||||||
"to" => $from->addDays($days),
|
"to" => $from->addDays($days),
|
||||||
"comment" => $this->faker->boolean ? $this->faker->paragraph() : null,
|
"comment" => $this->faker->boolean ? $this->faker->paragraph() : null,
|
||||||
|
1486
package-lock.json
generated
1486
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
Kalendarz urlopów
|
Kalendarz urlopów
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div v-if="can.generateTimesheet">
|
||||||
<a
|
<a
|
||||||
:href="`/timesheet/${selectedMonth.value}`"
|
:href="`/timesheet/${selectedMonth.value}`"
|
||||||
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"
|
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"
|
||||||
@ -164,6 +164,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => null,
|
default: () => null,
|
||||||
},
|
},
|
||||||
|
can: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const {getMonths, findMonth} = useMonthInfo()
|
const {getMonths, findMonth} = useMonthInfo()
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
Lista dni wolnych od pracy w danym roku
|
Lista dni wolnych od pracy w danym roku
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div v-if="can.manageHolidays">
|
||||||
<InertiaLink
|
<InertiaLink
|
||||||
href="holidays/create"
|
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"
|
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"
|
||||||
@ -19,120 +19,123 @@
|
|||||||
</InertiaLink>
|
</InertiaLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-x-auto xl:overflow-x-visible overflow-y-auto xl:overflow-y-visible">
|
<div class="border-t border-gray-200">
|
||||||
<table class="min-w-full divide-y divide-gray-200">
|
<div class="overflow-x-auto xl:overflow-x-visible overflow-y-auto xl:overflow-y-visible">
|
||||||
<thead class="bg-gray-50">
|
<table class="min-w-full divide-y divide-gray-200">
|
||||||
<tr>
|
<thead class="bg-gray-100">
|
||||||
<th
|
<tr>
|
||||||
scope="col"
|
<th
|
||||||
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
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">
|
Nazwa
|
||||||
<DotsVerticalIcon
|
</th>
|
||||||
class="h-5 w-5"
|
<th
|
||||||
aria-hidden="true"
|
scope="col"
|
||||||
/>
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
</MenuButton>
|
>
|
||||||
|
Data
|
||||||
<transition
|
</th>
|
||||||
enter-active-class="transition ease-out duration-100"
|
<th
|
||||||
enter-from-class="transform opacity-0 scale-95"
|
scope="col"
|
||||||
enter-to-class="transform opacity-100 scale-100"
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
leave-active-class="transition ease-in duration-75"
|
>
|
||||||
leave-from-class="transform opacity-100 scale-100"
|
Dzień tygodnia
|
||||||
leave-to-class="transform opacity-0 scale-95"
|
</th>
|
||||||
>
|
<th
|
||||||
<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">
|
scope="col"
|
||||||
<div class="py-1">
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
<MenuItem
|
/>
|
||||||
v-slot="{ active }"
|
</tr>
|
||||||
class="flex"
|
</thead>
|
||||||
>
|
<tbody class="bg-white divide-y divide-gray-100">
|
||||||
<InertiaLink
|
<tr
|
||||||
:href="`/holidays/${holiday.id}/edit`"
|
v-for="holiday in holidays.data"
|
||||||
:class="[active ? 'bg-gray-100 text-gray-900' : 'text-gray-700', 'font-medium block px-4 py-2 text-sm']"
|
:key="holiday.id"
|
||||||
>
|
class="hover:bg-blumilk-25"
|
||||||
<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 class="px-4 py-4 whitespace-nowrap text-sm text-gray-500 font-semibold capitalize">
|
||||||
</td>
|
{{ holiday.name }}
|
||||||
</tr>
|
</td>
|
||||||
</tbody>
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
</table>
|
{{ 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
|
||||||
|
v-if="can.manageHolidays"
|
||||||
|
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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -157,6 +160,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => null,
|
default: () => null,
|
||||||
},
|
},
|
||||||
|
can: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return {}
|
return {}
|
||||||
|
@ -1,287 +1,291 @@
|
|||||||
<template>
|
<template>
|
||||||
<InertiaHead title="Złóż wniosek urlopowy" />
|
<InertiaHead title="Złóż wniosek urlopowy" />
|
||||||
<div class="grid grid-cols-1 gap-4 items-start lg:grid-cols-3 lg:gap-8">
|
<div class="grid grid-cols-1 gap-4 items-start lg:grid-cols-3 lg:gap-8">
|
||||||
<div class="grid grid-cols-1 lg:col-span-2 bg-white shadow-md">
|
<div class="lg:col-span-2 h-full bg-white shadow-md flex flex-col">
|
||||||
<div class="p-4 sm:px-6">
|
<div class="p-4 sm:px-6">
|
||||||
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
Złóż wniosek urlopowy
|
Złóż wniosek urlopowy
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<form
|
<form
|
||||||
class="border-t border-gray-200 px-6"
|
class="border-t border-gray-200 h-full px-6"
|
||||||
@submit.prevent="createForm"
|
@submit.prevent="createForm"
|
||||||
>
|
>
|
||||||
<div
|
<div class="h-full flex flex-col justify-between">
|
||||||
v-if="form.errors.vacationRequest"
|
<div>
|
||||||
class="rounded-md bg-red-50 p-4 mt-2"
|
<div
|
||||||
>
|
v-if="form.errors.vacationRequest"
|
||||||
<div class="flex">
|
class="rounded-md bg-red-50 p-4 mt-2"
|
||||||
<div class="flex-shrink-0">
|
>
|
||||||
<XCircleIcon class="h-5 w-5 text-red-400" />
|
<div class="flex">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<XCircleIcon class="h-5 w-5 text-red-400" />
|
||||||
|
</div>
|
||||||
|
<div class="ml-3">
|
||||||
|
<h3 class="text-sm font-medium text-red-800">
|
||||||
|
Wniosek nie mógł zostać utworzony
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 text-sm text-red-700">
|
||||||
|
<span>{{ form.errors.vacationRequest }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3">
|
<Listbox
|
||||||
<h3 class="text-sm font-medium text-red-800">
|
v-if="can.createOnBehalfOfEmployee"
|
||||||
Wniosek nie mógł zostać utworzony
|
v-model="form.user"
|
||||||
</h3>
|
as="div"
|
||||||
<div class="mt-2 text-sm text-red-700">
|
class="sm:grid sm:grid-cols-3 py-4 items-center"
|
||||||
<span>{{ form.errors.vacationRequest }}</span>
|
>
|
||||||
|
<ListboxLabel class="block text-sm font-medium text-gray-700">
|
||||||
|
Osoba składająca wniosek
|
||||||
|
</ListboxLabel>
|
||||||
|
<div class="mt-1 relative sm:mt-0 sm:col-span-2">
|
||||||
|
<ListboxButton
|
||||||
|
class="bg-white relative w-full max-w-lg border rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default sm:text-sm focus:ring-1"
|
||||||
|
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.type, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.type }"
|
||||||
|
>
|
||||||
|
<span class="flex items-center">
|
||||||
|
<img
|
||||||
|
:src="form.user.avatar"
|
||||||
|
class="flex-shrink-0 h-6 w-6 rounded-full"
|
||||||
|
>
|
||||||
|
<span class="ml-3 block truncate">{{ form.user.name }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||||
|
<SelectorIcon class="h-5 w-5 text-gray-400" />
|
||||||
|
</span>
|
||||||
|
</ListboxButton>
|
||||||
|
|
||||||
|
<transition
|
||||||
|
leave-active-class="transition ease-in duration-100"
|
||||||
|
leave-from-class="opacity-100"
|
||||||
|
leave-to-class="opacity-0"
|
||||||
|
>
|
||||||
|
<ListboxOptions
|
||||||
|
class="absolute z-10 mt-1 w-full max-w-lg bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
||||||
|
>
|
||||||
|
<ListboxOption
|
||||||
|
v-for="user in users.data"
|
||||||
|
:key="user.id"
|
||||||
|
v-slot="{ active, selected }"
|
||||||
|
as="template"
|
||||||
|
:value="user"
|
||||||
|
>
|
||||||
|
<li :class="[active ? 'text-white bg-blumilk-600' : 'text-gray-900', 'cursor-default select-none relative py-2 pl-3 pr-9']">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<img
|
||||||
|
:src="user.avatar"
|
||||||
|
alt=""
|
||||||
|
class="flex-shrink-0 h-6 w-6 rounded-full"
|
||||||
|
>
|
||||||
|
<span :class="[selected ? 'font-semibold' : 'font-normal', 'ml-3 block truncate']">
|
||||||
|
{{ user.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="selected"
|
||||||
|
:class="[active ? 'text-white' : 'text-blumilk-600', 'absolute inset-y-0 right-0 flex items-center pr-4']"
|
||||||
|
>
|
||||||
|
<CheckIcon class="h-5 w-5" />
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ListboxOption>
|
||||||
|
</ListboxOptions>
|
||||||
|
</transition>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.type"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.type }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Listbox>
|
||||||
|
<Listbox
|
||||||
|
v-model="form.type"
|
||||||
|
as="div"
|
||||||
|
class="sm:grid sm:grid-cols-3 py-4 items-center"
|
||||||
|
>
|
||||||
|
<ListboxLabel class="block text-sm font-medium text-gray-700">
|
||||||
|
Rodzaj wniosku
|
||||||
|
</ListboxLabel>
|
||||||
|
<div class="mt-1 relative sm:mt-0 sm:col-span-2">
|
||||||
|
<ListboxButton
|
||||||
|
class="bg-white relative w-full max-w-lg border rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default sm:text-sm focus:ring-1"
|
||||||
|
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.type, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.type }"
|
||||||
|
>
|
||||||
|
<span class="block truncate">{{ form.type.label }}</span>
|
||||||
|
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||||
|
<SelectorIcon class="h-5 w-5 text-gray-400" />
|
||||||
|
</span>
|
||||||
|
</ListboxButton>
|
||||||
|
|
||||||
|
<transition
|
||||||
|
leave-active-class="transition ease-in duration-100"
|
||||||
|
leave-from-class="opacity-100"
|
||||||
|
leave-to-class="opacity-0"
|
||||||
|
>
|
||||||
|
<ListboxOptions
|
||||||
|
class="absolute z-10 mt-1 w-full max-w-lg bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
||||||
|
>
|
||||||
|
<ListboxOption
|
||||||
|
v-for="type in vacationTypes"
|
||||||
|
:key="type.value"
|
||||||
|
v-slot="{ active, selected }"
|
||||||
|
as="template"
|
||||||
|
:value="type"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
:class="[active ? 'text-white bg-blumilk-600' : 'text-gray-900', 'cursor-default select-none relative py-2 pl-3 pr-9']"
|
||||||
|
>
|
||||||
|
<span :class="[selected ? 'font-semibold' : 'font-normal', 'block truncate']">
|
||||||
|
{{ type.label }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="selected"
|
||||||
|
:class="[active ? 'text-white' : 'text-blumilk-600', 'absolute inset-y-0 right-0 flex items-center pr-4']"
|
||||||
|
>
|
||||||
|
<CheckIcon class="h-5 w-5" />
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ListboxOption>
|
||||||
|
</ListboxOptions>
|
||||||
|
</transition>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.type"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.type }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Listbox>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<label
|
||||||
|
for="date_from"
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||||
|
>
|
||||||
|
Planowany urlop od
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<FlatPickr
|
||||||
|
id="date_from"
|
||||||
|
v-model="form.from"
|
||||||
|
:config="fromInputConfig"
|
||||||
|
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.from, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.from }"
|
||||||
|
@on-change="onFromChange"
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.from"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.from }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<label
|
||||||
|
for="date_from"
|
||||||
|
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
||||||
|
>
|
||||||
|
Planowany urlop do
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<FlatPickr
|
||||||
|
id="date_to"
|
||||||
|
v-model="form.to"
|
||||||
|
:config="toInputConfig"
|
||||||
|
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.to, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.to }"
|
||||||
|
@on-change="onToChange"
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
v-if="form.errors.to"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors.to }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<span class="block text-sm font-medium text-gray-700 sm:mt-px">Liczba dni urlopu</span>
|
||||||
|
<div
|
||||||
|
class="mt-1 sm:mt-0 sm:col-span-2 w-full max-w-lg bg-gray-50 border border-gray-300 rounded-md px-4 py-2 inline-flex items-center text-gray-500 sm:text-sm"
|
||||||
|
>
|
||||||
|
{{ estimatedDays.length }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
||||||
|
<label
|
||||||
|
for="comment"
|
||||||
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Komentarz
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<textarea
|
||||||
|
id="comment"
|
||||||
|
v-model="form.comment"
|
||||||
|
rows="4"
|
||||||
|
class="shadow-sm focus:ring-blumilk-500 focus:border-blumilk-500 block w-full max-w-lg sm:text-sm border-gray-300 rounded-md"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="can.skipFlow"
|
||||||
|
class="sm:grid sm:grid-cols-3 py-4 items-center"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
for="flowSkipped"
|
||||||
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
Natychmiastowo zatwierdź wniosek
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<Switch
|
||||||
|
id="flowSkipped"
|
||||||
|
v-model="form.flowSkipped"
|
||||||
|
:class="[form.flowSkipped ? 'bg-blumilk-500' : 'bg-gray-200', 'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500']"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
:class="[form.flowSkipped ? 'translate-x-5' : 'translate-x-0', 'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200']"
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="flex justify-end py-3">
|
||||||
<Listbox
|
<div class="space-x-3">
|
||||||
v-model="form.user"
|
<InertiaLink
|
||||||
as="div"
|
href="/vacation-requests"
|
||||||
class="sm:grid sm:grid-cols-3 py-4 items-center"
|
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"
|
||||||
>
|
|
||||||
<ListboxLabel class="block text-sm font-medium text-gray-700">
|
|
||||||
Osoba składająca wniosek
|
|
||||||
</ListboxLabel>
|
|
||||||
<div class="mt-1 relative sm:mt-0 sm:col-span-2">
|
|
||||||
<ListboxButton
|
|
||||||
class="bg-white relative w-full max-w-lg border rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default sm:text-sm focus:ring-1"
|
|
||||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.user, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.user }"
|
|
||||||
>
|
|
||||||
<span class="flex items-center">
|
|
||||||
<img
|
|
||||||
:src="form.user.avatar"
|
|
||||||
class="flex-shrink-0 h-6 w-6 rounded-full"
|
|
||||||
>
|
|
||||||
<span class="ml-3 block truncate">{{ form.user.name }}</span>
|
|
||||||
</span>
|
|
||||||
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
|
||||||
<SelectorIcon class="h-5 w-5 text-gray-400" />
|
|
||||||
</span>
|
|
||||||
</ListboxButton>
|
|
||||||
|
|
||||||
<transition
|
|
||||||
leave-active-class="transition ease-in duration-100"
|
|
||||||
leave-from-class="opacity-100"
|
|
||||||
leave-to-class="opacity-0"
|
|
||||||
>
|
|
||||||
<ListboxOptions
|
|
||||||
class="absolute z-10 mt-1 w-full max-w-lg bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
|
||||||
>
|
>
|
||||||
<ListboxOption
|
Anuluj
|
||||||
v-for="user in users.data"
|
</InertiaLink>
|
||||||
:key="user.id"
|
<button
|
||||||
v-slot="{ active, selected }"
|
type="submit"
|
||||||
as="template"
|
:disabled="form.processing"
|
||||||
:value="user"
|
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"
|
||||||
>
|
|
||||||
<li
|
|
||||||
:class="[active ? 'text-white bg-blumilk-600' : 'text-gray-900', 'cursor-default select-none relative py-2 pl-3 pr-9']"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<img
|
|
||||||
:src="user.avatar"
|
|
||||||
alt=""
|
|
||||||
class="flex-shrink-0 h-6 w-6 rounded-full"
|
|
||||||
>
|
|
||||||
<span :class="[selected ? 'font-semibold' : 'font-normal', 'ml-3 block truncate']">
|
|
||||||
{{ user.name }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="selected"
|
|
||||||
:class="[active ? 'text-white' : 'text-blumilk-600', 'absolute inset-y-0 right-0 flex items-center pr-4']"
|
|
||||||
>
|
|
||||||
<CheckIcon class="h-5 w-5" />
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ListboxOption>
|
|
||||||
</ListboxOptions>
|
|
||||||
</transition>
|
|
||||||
<p
|
|
||||||
v-if="form.errors.type"
|
|
||||||
class="mt-2 text-sm text-red-600"
|
|
||||||
>
|
|
||||||
{{ form.errors.type }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Listbox>
|
|
||||||
<Listbox
|
|
||||||
v-model="form.type"
|
|
||||||
as="div"
|
|
||||||
class="sm:grid sm:grid-cols-3 py-4 items-center"
|
|
||||||
>
|
|
||||||
<ListboxLabel class="block text-sm font-medium text-gray-700">
|
|
||||||
Rodzaj wniosku
|
|
||||||
</ListboxLabel>
|
|
||||||
<div class="mt-1 relative sm:mt-0 sm:col-span-2">
|
|
||||||
<ListboxButton
|
|
||||||
class="bg-white relative w-full max-w-lg border rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default sm:text-sm focus:ring-1"
|
|
||||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.type, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.type }"
|
|
||||||
>
|
|
||||||
<span class="block truncate">{{ form.type.label }}</span>
|
|
||||||
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
|
||||||
<SelectorIcon class="h-5 w-5 text-gray-400" />
|
|
||||||
</span>
|
|
||||||
</ListboxButton>
|
|
||||||
|
|
||||||
<transition
|
|
||||||
leave-active-class="transition ease-in duration-100"
|
|
||||||
leave-from-class="opacity-100"
|
|
||||||
leave-to-class="opacity-0"
|
|
||||||
>
|
|
||||||
<ListboxOptions
|
|
||||||
class="absolute z-10 mt-1 w-full max-w-lg bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
|
|
||||||
>
|
>
|
||||||
<ListboxOption
|
Zapisz
|
||||||
v-for="type in vacationTypes"
|
</button>
|
||||||
:key="type.value"
|
</div>
|
||||||
v-slot="{ active, selected }"
|
|
||||||
as="template"
|
|
||||||
:value="type"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
:class="[active ? 'text-white bg-blumilk-600' : 'text-gray-900', 'cursor-default select-none relative py-2 pl-3 pr-9']"
|
|
||||||
>
|
|
||||||
<span :class="[selected ? 'font-semibold' : 'font-normal', 'block truncate']">
|
|
||||||
{{ type.label }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="selected"
|
|
||||||
:class="[active ? 'text-white' : 'text-blumilk-600', 'absolute inset-y-0 right-0 flex items-center pr-4']"
|
|
||||||
>
|
|
||||||
<CheckIcon class="h-5 w-5" />
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ListboxOption>
|
|
||||||
</ListboxOptions>
|
|
||||||
</transition>
|
|
||||||
<p
|
|
||||||
v-if="form.errors.type"
|
|
||||||
class="mt-2 text-sm text-red-600"
|
|
||||||
>
|
|
||||||
{{ form.errors.type }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Listbox>
|
|
||||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
|
||||||
<label
|
|
||||||
for="date_from"
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
|
||||||
>
|
|
||||||
Planowany urlop od
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
|
||||||
<FlatPickr
|
|
||||||
id="date_from"
|
|
||||||
v-model="form.from"
|
|
||||||
:config="fromInputConfig"
|
|
||||||
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.from, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.from }"
|
|
||||||
@on-change="onFromChange"
|
|
||||||
/>
|
|
||||||
<p
|
|
||||||
v-if="form.errors.from"
|
|
||||||
class="mt-2 text-sm text-red-600"
|
|
||||||
>
|
|
||||||
{{ form.errors.from }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
|
||||||
<label
|
|
||||||
for="date_from"
|
|
||||||
class="block text-sm font-medium text-gray-700 sm:mt-px"
|
|
||||||
>
|
|
||||||
Planowany urlop do
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
|
||||||
<FlatPickr
|
|
||||||
id="date_to"
|
|
||||||
v-model="form.to"
|
|
||||||
:config="toInputConfig"
|
|
||||||
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.to, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.to }"
|
|
||||||
@on-change="onToChange"
|
|
||||||
/>
|
|
||||||
<p
|
|
||||||
v-if="form.errors.to"
|
|
||||||
class="mt-2 text-sm text-red-600"
|
|
||||||
>
|
|
||||||
{{ form.errors.to }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
|
||||||
<span class="block text-sm font-medium text-gray-700 sm:mt-px">Liczba dni urlopu</span>
|
|
||||||
<div
|
|
||||||
class="mt-1 sm:mt-0 sm:col-span-2 w-full max-w-lg bg-gray-50 border border-gray-300 rounded-md px-4 py-2 inline-flex items-center text-gray-500 sm:text-sm"
|
|
||||||
>
|
|
||||||
{{ estimatedDays.length }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
|
||||||
<label
|
|
||||||
for="comment"
|
|
||||||
class="block text-sm font-medium text-gray-700"
|
|
||||||
>
|
|
||||||
Komentarz
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
|
||||||
<textarea
|
|
||||||
id="comment"
|
|
||||||
v-model="form.comment"
|
|
||||||
rows="4"
|
|
||||||
class="shadow-sm focus:ring-blumilk-500 focus:border-blumilk-500 block w-full max-w-lg sm:text-sm border-gray-300 rounded-md"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
|
||||||
<label
|
|
||||||
for="flowSkipped"
|
|
||||||
class="block text-sm font-medium text-gray-700"
|
|
||||||
>
|
|
||||||
Natychmiastowo zatwierdź wniosek
|
|
||||||
</label>
|
|
||||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
|
||||||
<Switch
|
|
||||||
id="flowSkipped"
|
|
||||||
v-model="form.flowSkipped"
|
|
||||||
:class="[form.flowSkipped ? 'bg-blumilk-500' : 'bg-gray-200', 'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blumilk-500']"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
:class="[form.flowSkipped ? 'translate-x-5' : 'translate-x-0', 'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200']"
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-end py-3">
|
|
||||||
<div class="space-x-3">
|
|
||||||
<InertiaLink
|
|
||||||
href="/vacation-requests"
|
|
||||||
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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 bg-white shadow-md h-full">
|
<div class="bg-white shadow-md h-full">
|
||||||
<div>
|
<div class="p-4 sm:px-6">
|
||||||
<div class="p-4 sm:px-6">
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
Urlop wypoczynkowy
|
||||||
Urlop wypoczynkowy
|
</h2>
|
||||||
</h2>
|
</div>
|
||||||
</div>
|
<div class="border-t border-gray-200 px-6 pt-8">
|
||||||
<div class="border-t border-gray-200 px-6 pt-8">
|
<VacationChart :stats="stats" />
|
||||||
<VacationChart :stats="stats" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -329,10 +333,16 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => null,
|
default: () => null,
|
||||||
},
|
},
|
||||||
|
can: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
user: props.users.data.find(user => user.id === props.auth.user.id),
|
user: props.can.createOnBehalfOfEmployee
|
||||||
|
? props.users.data.find(user => user.id === props.auth.user.id)
|
||||||
|
: props.auth.user,
|
||||||
from: null,
|
from: null,
|
||||||
to: null,
|
to: null,
|
||||||
type: props.vacationTypes[0],
|
type: props.vacationTypes[0],
|
||||||
@ -403,12 +413,6 @@ export default {
|
|||||||
.then(res => this.estimatedDays = res.data)
|
.then(res => this.estimatedDays = res.data)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateVacationStats(user) {
|
|
||||||
console.log(user)
|
|
||||||
axios.post('/api/get-vacations-stats')
|
|
||||||
.then(res => this.stats = res.data)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -110,7 +110,10 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white shadow">
|
<div
|
||||||
|
v-if="can.acceptAsTechnical"
|
||||||
|
class="bg-white shadow"
|
||||||
|
>
|
||||||
<div class="px-4 py-5 sm:p-6">
|
<div class="px-4 py-5 sm:p-6">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
Zaakceptuj wniosek jako osoba techniczna
|
Zaakceptuj wniosek jako osoba techniczna
|
||||||
@ -134,7 +137,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white shadow">
|
<div
|
||||||
|
v-if="can.acceptAsAdministrative"
|
||||||
|
class="bg-white shadow"
|
||||||
|
>
|
||||||
<div class="px-4 py-5 sm:p-6">
|
<div class="px-4 py-5 sm:p-6">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
Zaakceptuj wniosek jako osoba administracyjna
|
Zaakceptuj wniosek jako osoba administracyjna
|
||||||
@ -157,7 +163,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white shadow">
|
<div
|
||||||
|
v-if="can.reject"
|
||||||
|
class="bg-white shadow"
|
||||||
|
>
|
||||||
<div class="px-4 py-5 sm:p-6">
|
<div class="px-4 py-5 sm:p-6">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
Odrzuć wniosek
|
Odrzuć wniosek
|
||||||
@ -180,7 +189,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white shadow border border-red-500">
|
<div
|
||||||
|
v-if="can.cancel"
|
||||||
|
class="bg-white shadow border border-red-500"
|
||||||
|
>
|
||||||
<div class="px-4 py-5 sm:p-6">
|
<div class="px-4 py-5 sm:p-6">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
Anuluj wniosek
|
Anuluj wniosek
|
||||||
@ -246,6 +258,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => null,
|
default: () => null,
|
||||||
},
|
},
|
||||||
|
can: {
|
||||||
|
type: Object,
|
||||||
|
default: () => null,
|
||||||
|
},
|
||||||
activities: {
|
activities: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => null,
|
default: () => null,
|
||||||
|
@ -213,12 +213,12 @@
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="h-8 w-8 rounded-full"
|
class="h-8 w-8 rounded-full"
|
||||||
:src="user.avatar"
|
:src="auth.user.avatar"
|
||||||
alt="Avatar"
|
alt="Avatar"
|
||||||
>
|
>
|
||||||
<span class="hidden ml-3 text-gray-700 text-sm font-medium lg:block">
|
<span class="hidden ml-3 text-gray-700 text-sm font-medium lg:block">
|
||||||
<span class="sr-only">Open user menu for </span>
|
<span class="sr-only">Open user menu for </span>
|
||||||
{{ user.name }}
|
{{ auth.user.name }}
|
||||||
</span>
|
</span>
|
||||||
<ChevronDownIcon
|
<ChevronDownIcon
|
||||||
class="hidden flex-shrink-0 ml-1 h-5 w-5 text-gray-400 lg:block"
|
class="hidden flex-shrink-0 ml-1 h-5 w-5 text-gray-400 lg:block"
|
||||||
@ -324,23 +324,24 @@ export default {
|
|||||||
setup() {
|
setup() {
|
||||||
const sidebarOpen = ref(false)
|
const sidebarOpen = ref(false)
|
||||||
|
|
||||||
const user = computed(() => usePage().props.value.auth.user)
|
const auth = computed(() => usePage().props.value.auth)
|
||||||
const years = computed(() => usePage().props.value.years)
|
const years = computed(() => usePage().props.value.years)
|
||||||
|
|
||||||
const navigation = [
|
const navigation = computed(() =>
|
||||||
{name: 'Wnioski urlopowe', href: '/vacation-requests', icon: CollectionIcon},
|
[
|
||||||
{name: 'Kalendarz urlopów', href: '/vacation-calendar', icon: CalendarIcon},
|
{name: 'Wnioski urlopowe', href: '/vacation-requests', icon: CollectionIcon, can: true},
|
||||||
{name: 'Dni wolne', href: '/holidays', icon: StarIcon},
|
{name: 'Kalendarz urlopów', href: '/vacation-calendar', icon: CalendarIcon, can: true},
|
||||||
{name: 'Limity urlopów', href: '/vacation-limits', icon: SunIcon},
|
{name: 'Dni wolne', href: '/holidays', icon: StarIcon, can: true},
|
||||||
{name: 'Użytkownicy', href: '/users', icon: UserGroupIcon},
|
{name: 'Limity urlopów', href: '/vacation-limits', icon: SunIcon, can: auth.value.can.manageVacationLimits},
|
||||||
]
|
{name: 'Użytkownicy', href: '/users', icon: UserGroupIcon, can: auth.value.can.manageUsers},
|
||||||
|
].filter(item => item.can))
|
||||||
|
|
||||||
const userNavigation = [
|
const userNavigation = [
|
||||||
{name: 'Wyloguj się', href: '/logout', method: 'post', as: 'button'},
|
{name: 'Wyloguj się', href: '/logout', method: 'post', as: 'button'},
|
||||||
]
|
]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user,
|
auth,
|
||||||
years,
|
years,
|
||||||
navigation,
|
navigation,
|
||||||
userNavigation,
|
userNavigation,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-chart
|
<v-chart
|
||||||
style="height: 600px;"
|
style="height: 600px;"
|
||||||
|
:autoresize="true"
|
||||||
:option="option"
|
:option="option"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -60,10 +61,20 @@ export default {
|
|||||||
{
|
{
|
||||||
name: 'Urlop wypoczynkowy',
|
name: 'Urlop wypoczynkowy',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 2,
|
||||||
|
},
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
textStyle: {
|
position: 'inner',
|
||||||
fontSize: 16,
|
formatter: param => param.value !== 0 ? param.value : '' ,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#FFFFFF',
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data: [
|
data: [
|
||||||
@ -72,23 +83,6 @@ export default {
|
|||||||
{ value: props.stats.remaining, name: 'Pozostałe' },
|
{ value: props.stats.remaining, name: 'Pozostałe' },
|
||||||
],
|
],
|
||||||
radius: ['30%', '70%'],
|
radius: ['30%', '70%'],
|
||||||
itemStyle : {
|
|
||||||
normal: {
|
|
||||||
borderRadius: 10,
|
|
||||||
borderColor: '#fff',
|
|
||||||
borderWidth: 2,
|
|
||||||
label: {
|
|
||||||
position: 'inner',
|
|
||||||
formatter: param => param.value !== 0 ? param.value : '' ,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
fontSize: 16,
|
|
||||||
color: '#FFFFFF',
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
|
@ -34,7 +34,8 @@ class HolidayTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanCreateHoliday(): void
|
public function testAdminCanCreateHoliday(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
$this->actingAs($admin)
|
$this->actingAs($admin)
|
||||||
@ -53,7 +54,8 @@ class HolidayTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCannotCreateHolidayForYearPeriodThatDoesntExist(): void
|
public function testAdminCannotCreateHolidayForYearPeriodThatDoesntExist(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$year = YearPeriod::query()->max("year") + 1;
|
$year = YearPeriod::query()->max("year") + 1;
|
||||||
|
|
||||||
$this->actingAs($admin)
|
$this->actingAs($admin)
|
||||||
@ -66,7 +68,8 @@ class HolidayTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCannotCreateHolidayIfGivenDataIsUsed(): void
|
public function testAdminCannotCreateHolidayIfGivenDataIsUsed(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
$sameDate = Carbon::create($currentYearPeriod->year, 5, 20)->toDateString();
|
$sameDate = Carbon::create($currentYearPeriod->year, 5, 20)->toDateString();
|
||||||
|
|
||||||
@ -85,7 +88,8 @@ class HolidayTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanEditHoliday(): void
|
public function testAdminCanEditHoliday(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
$holiday = Holiday::factory()->create([
|
$holiday = Holiday::factory()->create([
|
||||||
@ -115,7 +119,8 @@ class HolidayTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanDeleteHoliday(): void
|
public function testAdminCanDeleteHoliday(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$holiday = Holiday::factory()->create();
|
$holiday = Holiday::factory()->create();
|
||||||
|
|
||||||
$this->actingAs($admin)
|
$this->actingAs($admin)
|
||||||
|
@ -19,7 +19,7 @@ class UserTest extends FeatureTestCase
|
|||||||
public function testAdminCanSeeUsersList(): void
|
public function testAdminCanSeeUsersList(): void
|
||||||
{
|
{
|
||||||
User::factory()->count(10)->create();
|
User::factory()->count(10)->create();
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$this->assertDatabaseCount("users", 11);
|
$this->assertDatabaseCount("users", 11);
|
||||||
|
|
||||||
@ -38,18 +38,21 @@ class UserTest extends FeatureTestCase
|
|||||||
"first_name" => "Test",
|
"first_name" => "Test",
|
||||||
"last_name" => "User1",
|
"last_name" => "User1",
|
||||||
])->create();
|
])->create();
|
||||||
|
|
||||||
User::factory([
|
User::factory([
|
||||||
"first_name" => "Test",
|
"first_name" => "Test",
|
||||||
"last_name" => "User2",
|
"last_name" => "User2",
|
||||||
])->create();
|
])->create();
|
||||||
|
|
||||||
User::factory([
|
User::factory([
|
||||||
"first_name" => "Test",
|
"first_name" => "Test",
|
||||||
"last_name" => "User3",
|
"last_name" => "User3",
|
||||||
])->create();
|
])->create();
|
||||||
|
|
||||||
$admin = User::factory([
|
$admin = User::factory([
|
||||||
"first_name" => "John",
|
"first_name" => "John",
|
||||||
"last_name" => "Doe",
|
"last_name" => "Doe",
|
||||||
])->create();
|
])->admin()->create();
|
||||||
|
|
||||||
$this->assertDatabaseCount("users", 4);
|
$this->assertDatabaseCount("users", 4);
|
||||||
|
|
||||||
@ -66,7 +69,7 @@ class UserTest extends FeatureTestCase
|
|||||||
public function testUserListIsPaginated(): void
|
public function testUserListIsPaginated(): void
|
||||||
{
|
{
|
||||||
User::factory()->count(15)->create();
|
User::factory()->count(15)->create();
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$this->assertDatabaseCount("users", 16);
|
$this->assertDatabaseCount("users", 16);
|
||||||
|
|
||||||
@ -81,7 +84,7 @@ class UserTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanCreateUser(): void
|
public function testAdminCanCreateUser(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
Carbon::setTestNow(Carbon::now());
|
Carbon::setTestNow(Carbon::now());
|
||||||
|
|
||||||
$this->actingAs($admin)
|
$this->actingAs($admin)
|
||||||
@ -109,7 +112,8 @@ class UserTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanEditUser(): void
|
public function testAdminCanEditUser(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
|
|
||||||
Carbon::setTestNow();
|
Carbon::setTestNow();
|
||||||
@ -147,7 +151,8 @@ class UserTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanDeleteUser(): void
|
public function testAdminCanDeleteUser(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
|
|
||||||
$this->actingAs($admin)
|
$this->actingAs($admin)
|
||||||
@ -159,7 +164,8 @@ class UserTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanRestoreUser(): void
|
public function testAdminCanRestoreUser(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->create();
|
$admin = User::factory()->admin()->create();
|
||||||
|
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
$user->delete();
|
$user->delete();
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class VacationLimitTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanSeeVacationLimits(): void
|
public function testAdminCanSeeVacationLimits(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->createQuietly();
|
$admin = User::factory()->admin()->createQuietly();
|
||||||
|
|
||||||
User::factory(10)->create();
|
User::factory(10)->create();
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ class VacationLimitTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testAdminCanUpdateVacationLimits(): void
|
public function testAdminCanUpdateVacationLimits(): void
|
||||||
{
|
{
|
||||||
$admin = User::factory()->createQuietly();
|
$admin = User::factory()->admin()->createQuietly();
|
||||||
|
|
||||||
User::factory(3)->create();
|
User::factory(3)->create();
|
||||||
|
|
||||||
|
@ -9,13 +9,16 @@ use Illuminate\Support\Carbon;
|
|||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Inertia\Testing\AssertableInertia as Assert;
|
use Inertia\Testing\AssertableInertia as Assert;
|
||||||
use Tests\FeatureTestCase;
|
use Tests\FeatureTestCase;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
use Toby\Domain\Events\VacationRequestAcceptedByAdministrative;
|
use Toby\Domain\Events\VacationRequestAcceptedByAdministrative;
|
||||||
use Toby\Domain\Events\VacationRequestAcceptedByTechnical;
|
use Toby\Domain\Events\VacationRequestAcceptedByTechnical;
|
||||||
use Toby\Domain\Events\VacationRequestApproved;
|
use Toby\Domain\Events\VacationRequestApproved;
|
||||||
use Toby\Domain\Events\VacationRequestRejected;
|
use Toby\Domain\Events\VacationRequestRejected;
|
||||||
use Toby\Domain\PolishHolidaysRetriever;
|
use Toby\Domain\PolishHolidaysRetriever;
|
||||||
|
use Toby\Domain\States\VacationRequest\Approved;
|
||||||
|
use Toby\Domain\States\VacationRequest\Rejected;
|
||||||
|
use Toby\Domain\States\VacationRequest\WaitingForAdministrative;
|
||||||
|
use Toby\Domain\States\VacationRequest\WaitingForTechnical;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\VacationLimit;
|
use Toby\Eloquent\Models\VacationLimit;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
@ -83,7 +86,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
"year_period_id" => $currentYearPeriod->id,
|
"year_period_id" => $currentYearPeriod->id,
|
||||||
"name" => "1/" . $currentYearPeriod->year,
|
"name" => "1/" . $currentYearPeriod->year,
|
||||||
"type" => VacationType::Vacation->value,
|
"type" => VacationType::Vacation->value,
|
||||||
"state" => VacationRequestState::WaitingForTechnical,
|
"state" => WaitingForTechnical::$name,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 11)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 11)->toDateString(),
|
||||||
"comment" => "Comment for the vacation request.",
|
"comment" => "Comment for the vacation request.",
|
||||||
@ -92,7 +95,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
|
|
||||||
public function testUserCanCreateVacationRequestOnEmployeeBehalf(): void
|
public function testUserCanCreateVacationRequestOnEmployeeBehalf(): void
|
||||||
{
|
{
|
||||||
$creator = User::factory()->createQuietly();
|
$creator = User::factory()->admin()->createQuietly();
|
||||||
$user = User::factory()->createQuietly();
|
$user = User::factory()->createQuietly();
|
||||||
|
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
@ -120,7 +123,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
"year_period_id" => $currentYearPeriod->id,
|
"year_period_id" => $currentYearPeriod->id,
|
||||||
"name" => "1/" . $currentYearPeriod->year,
|
"name" => "1/" . $currentYearPeriod->year,
|
||||||
"type" => VacationType::Vacation->value,
|
"type" => VacationType::Vacation->value,
|
||||||
"state" => VacationRequestState::WaitingForTechnical,
|
"state" => WaitingForTechnical::$name,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 11)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 11)->toDateString(),
|
||||||
"comment" => "Comment for the vacation request.",
|
"comment" => "Comment for the vacation request.",
|
||||||
@ -131,7 +134,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
{
|
{
|
||||||
Event::fake(VacationRequestApproved::class);
|
Event::fake(VacationRequestApproved::class);
|
||||||
|
|
||||||
$creator = User::factory()->createQuietly();
|
$creator = User::factory()->admin()->createQuietly();
|
||||||
$user = User::factory()->createQuietly();
|
$user = User::factory()->createQuietly();
|
||||||
|
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
@ -160,7 +163,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
"year_period_id" => $currentYearPeriod->id,
|
"year_period_id" => $currentYearPeriod->id,
|
||||||
"name" => "1/" . $currentYearPeriod->year,
|
"name" => "1/" . $currentYearPeriod->year,
|
||||||
"type" => VacationType::Vacation->value,
|
"type" => VacationType::Vacation->value,
|
||||||
"state" => VacationRequestState::Approved,
|
"state" => Approved::$name,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 11)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 11)->toDateString(),
|
||||||
"comment" => "Comment for the vacation request.",
|
"comment" => "Comment for the vacation request.",
|
||||||
@ -172,11 +175,11 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
Event::fake(VacationRequestAcceptedByTechnical::class);
|
Event::fake(VacationRequestAcceptedByTechnical::class);
|
||||||
|
|
||||||
$user = User::factory()->createQuietly();
|
$user = User::factory()->createQuietly();
|
||||||
$technicalApprover = User::factory()->createQuietly();
|
$technicalApprover = User::factory()->technicalApprover()->createQuietly();
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
$vacationRequest = VacationRequest::factory([
|
$vacationRequest = VacationRequest::factory([
|
||||||
"state" => VacationRequestState::WaitingForTechnical,
|
"state" => WaitingForTechnical::class,
|
||||||
"type" => VacationType::Vacation,
|
"type" => VacationType::Vacation,
|
||||||
])
|
])
|
||||||
->for($user)
|
->for($user)
|
||||||
@ -195,12 +198,12 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
Event::fake(VacationRequestAcceptedByAdministrative::class);
|
Event::fake(VacationRequestAcceptedByAdministrative::class);
|
||||||
|
|
||||||
$user = User::factory()->createQuietly();
|
$user = User::factory()->createQuietly();
|
||||||
$administrativeApprover = User::factory()->createQuietly();
|
$administrativeApprover = User::factory()->administrativeApprover()->createQuietly();
|
||||||
|
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
$vacationRequest = VacationRequest::factory([
|
$vacationRequest = VacationRequest::factory([
|
||||||
"state" => VacationRequestState::WaitingForAdministrative,
|
"state" => WaitingForAdministrative::class,
|
||||||
])
|
])
|
||||||
->for($user)
|
->for($user)
|
||||||
->for($currentYearPeriod)
|
->for($currentYearPeriod)
|
||||||
@ -218,7 +221,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
Event::fake(VacationRequestRejected::class);
|
Event::fake(VacationRequestRejected::class);
|
||||||
|
|
||||||
$user = User::factory()->createQuietly();
|
$user = User::factory()->createQuietly();
|
||||||
$technicalApprover = User::factory()->createQuietly();
|
$technicalApprover = User::factory()->technicalApprover()->createQuietly();
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
VacationLimit::factory([
|
VacationLimit::factory([
|
||||||
@ -229,7 +232,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
->create();
|
->create();
|
||||||
|
|
||||||
$vacationRequest = VacationRequest::factory([
|
$vacationRequest = VacationRequest::factory([
|
||||||
"state" => VacationRequestState::WaitingForTechnical,
|
"state" => WaitingForTechnical::class,
|
||||||
"type" => VacationType::Vacation,
|
"type" => VacationType::Vacation,
|
||||||
])
|
])
|
||||||
->for($user)
|
->for($user)
|
||||||
@ -241,6 +244,9 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
->assertSessionHasNoErrors();
|
->assertSessionHasNoErrors();
|
||||||
|
|
||||||
Event::assertDispatched(VacationRequestRejected::class);
|
Event::assertDispatched(VacationRequestRejected::class);
|
||||||
|
$this->assertDatabaseHas("vacation_requests", [
|
||||||
|
"state" => Rejected::$name,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUserCannotCreateVacationRequestIfHeExceedsHisVacationLimit(): void
|
public function testUserCannotCreateVacationRequestIfHeExceedsHisVacationLimit(): void
|
||||||
@ -339,7 +345,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
|
|
||||||
VacationRequest::factory([
|
VacationRequest::factory([
|
||||||
"type" => VacationType::Vacation->value,
|
"type" => VacationType::Vacation->value,
|
||||||
"state" => VacationRequestState::WaitingForTechnical,
|
"state" => WaitingForTechnical::class,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
||||||
"comment" => "Comment for the vacation request.",
|
"comment" => "Comment for the vacation request.",
|
||||||
@ -358,8 +364,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
])
|
])
|
||||||
->assertSessionHasErrors([
|
->assertSessionHasErrors([
|
||||||
"vacationRequest" => __("You have pending vacation request in this range."),
|
"vacationRequest" => __("You have pending vacation request in this range."),
|
||||||
])
|
]);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUserCannotCreateVacationRequestIfHeHasApprovedVacationRequestInThisRange(): void
|
public function testUserCannotCreateVacationRequestIfHeHasApprovedVacationRequestInThisRange(): void
|
||||||
@ -367,7 +372,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
$user = User::factory()->createQuietly();
|
$user = User::factory()->createQuietly();
|
||||||
$currentYearPeriod = YearPeriod::current();
|
$currentYearPeriod = YearPeriod::current();
|
||||||
|
|
||||||
$vacationLimit = VacationLimit::factory([
|
VacationLimit::factory([
|
||||||
"days" => 20,
|
"days" => 20,
|
||||||
])
|
])
|
||||||
->for($user)
|
->for($user)
|
||||||
@ -376,7 +381,7 @@ class VacationRequestTest extends FeatureTestCase
|
|||||||
|
|
||||||
VacationRequest::factory([
|
VacationRequest::factory([
|
||||||
"type" => VacationType::Vacation->value,
|
"type" => VacationType::Vacation->value,
|
||||||
"state" => VacationRequestState::Approved,
|
"state" => Approved::class,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 2)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 2)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
||||||
"comment" => "Comment for the vacation request.",
|
"comment" => "Comment for the vacation request.",
|
||||||
|
@ -10,9 +10,9 @@ use Illuminate\Support\Facades\Notification;
|
|||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Tests\Traits\InteractsWithYearPeriods;
|
use Tests\Traits\InteractsWithYearPeriods;
|
||||||
use Toby\Domain\Enums\Role;
|
use Toby\Domain\Enums\Role;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
use Toby\Domain\Notifications\VacationRequestWaitsForTechApprovalNotification;
|
use Toby\Domain\Notifications\VacationRequestWaitsForTechApprovalNotification;
|
||||||
|
use Toby\Domain\States\VacationRequest\Created;
|
||||||
use Toby\Domain\VacationRequestStateManager;
|
use Toby\Domain\VacationRequestStateManager;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
@ -53,7 +53,7 @@ class VacationRequestNotificationTest extends TestCase
|
|||||||
/** @var VacationRequest $vacationRequest */
|
/** @var VacationRequest $vacationRequest */
|
||||||
$vacationRequest = VacationRequest::factory([
|
$vacationRequest = VacationRequest::factory([
|
||||||
"type" => VacationType::Vacation->value,
|
"type" => VacationType::Vacation->value,
|
||||||
"state" => VacationRequestState::Created,
|
"state" => Created::class,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
||||||
"comment" => "Comment for the vacation request.",
|
"comment" => "Comment for the vacation request.",
|
||||||
|
@ -9,8 +9,10 @@ use Illuminate\Support\Carbon;
|
|||||||
use Illuminate\Support\Facades\Notification;
|
use Illuminate\Support\Facades\Notification;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Tests\Traits\InteractsWithYearPeriods;
|
use Tests\Traits\InteractsWithYearPeriods;
|
||||||
use Toby\Domain\Enums\VacationRequestState;
|
|
||||||
use Toby\Domain\Enums\VacationType;
|
use Toby\Domain\Enums\VacationType;
|
||||||
|
use Toby\Domain\States\VacationRequest\Approved;
|
||||||
|
use Toby\Domain\States\VacationRequest\Created;
|
||||||
|
use Toby\Domain\States\VacationRequest\WaitingForTechnical;
|
||||||
use Toby\Domain\VacationRequestStateManager;
|
use Toby\Domain\VacationRequestStateManager;
|
||||||
use Toby\Eloquent\Models\User;
|
use Toby\Eloquent\Models\User;
|
||||||
use Toby\Eloquent\Models\VacationRequest;
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
@ -43,7 +45,7 @@ class VacationRequestStatesTest extends TestCase
|
|||||||
/** @var VacationRequest $vacationRequest */
|
/** @var VacationRequest $vacationRequest */
|
||||||
$vacationRequest = VacationRequest::factory([
|
$vacationRequest = VacationRequest::factory([
|
||||||
"type" => VacationType::Vacation->value,
|
"type" => VacationType::Vacation->value,
|
||||||
"state" => VacationRequestState::Created,
|
"state" => Created::class,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
||||||
"comment" => "Comment for the vacation request.",
|
"comment" => "Comment for the vacation request.",
|
||||||
@ -54,7 +56,7 @@ class VacationRequestStatesTest extends TestCase
|
|||||||
|
|
||||||
$this->stateManager->waitForTechnical($vacationRequest);
|
$this->stateManager->waitForTechnical($vacationRequest);
|
||||||
|
|
||||||
$this->assertEquals(VacationRequestState::WaitingForTechnical, $vacationRequest->state);
|
$this->assertTrue($vacationRequest->state->equals(WaitingForTechnical::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAfterCreatingVacationRequestOfTypeSickVacationItTransitsToProperState(): void
|
public function testAfterCreatingVacationRequestOfTypeSickVacationItTransitsToProperState(): void
|
||||||
@ -66,7 +68,7 @@ class VacationRequestStatesTest extends TestCase
|
|||||||
/** @var VacationRequest $vacationRequest */
|
/** @var VacationRequest $vacationRequest */
|
||||||
$vacationRequest = VacationRequest::factory([
|
$vacationRequest = VacationRequest::factory([
|
||||||
"type" => VacationType::Sick->value,
|
"type" => VacationType::Sick->value,
|
||||||
"state" => VacationRequestState::Created,
|
"state" => Created::class,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 1)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
||||||
])
|
])
|
||||||
@ -76,7 +78,7 @@ class VacationRequestStatesTest extends TestCase
|
|||||||
|
|
||||||
$this->stateManager->approve($vacationRequest);
|
$this->stateManager->approve($vacationRequest);
|
||||||
|
|
||||||
$this->assertEquals(VacationRequestState::Approved, $vacationRequest->state);
|
$this->assertTrue($vacationRequest->state->equals(Approved::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAfterCreatingVacationRequestOfTypeTimeInLieuItTransitsToProperState(): void
|
public function testAfterCreatingVacationRequestOfTypeTimeInLieuItTransitsToProperState(): void
|
||||||
@ -88,7 +90,7 @@ class VacationRequestStatesTest extends TestCase
|
|||||||
/** @var VacationRequest $vacationRequest */
|
/** @var VacationRequest $vacationRequest */
|
||||||
$vacationRequest = VacationRequest::factory([
|
$vacationRequest = VacationRequest::factory([
|
||||||
"type" => VacationType::TimeInLieu->value,
|
"type" => VacationType::TimeInLieu->value,
|
||||||
"state" => VacationRequestState::Created,
|
"state" => Created::class,
|
||||||
"from" => Carbon::create($currentYearPeriod->year, 2, 2)->toDateString(),
|
"from" => Carbon::create($currentYearPeriod->year, 2, 2)->toDateString(),
|
||||||
"to" => Carbon::create($currentYearPeriod->year, 2, 2)->toDateString(),
|
"to" => Carbon::create($currentYearPeriod->year, 2, 2)->toDateString(),
|
||||||
])
|
])
|
||||||
@ -98,6 +100,6 @@ class VacationRequestStatesTest extends TestCase
|
|||||||
|
|
||||||
$this->stateManager->approve($vacationRequest);
|
$this->stateManager->approve($vacationRequest);
|
||||||
|
|
||||||
$this->assertEquals(VacationRequestState::Approved, $vacationRequest->state);
|
$this->assertTrue($vacationRequest->state->equals(Approved::class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user