* wip * wip * wip * wip * wip * wip * wip * #5 - bump dependencies * #43 - wip * #43 - add composer script * #43 - fix * #43 - fix * #43 - wip * #43 - ecs fix * #43 - cr fix * #43 - cr fix * #43 - fix Co-authored-by: EwelinaLasowy <ewelina.lasowy@blumilk.pl>
This commit is contained in:
parent
d825dd727f
commit
3d9726039c
@ -6,9 +6,6 @@ namespace Toby\Architecture\Providers;
|
|||||||
|
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Toby\Eloquent\Models\Holiday;
|
|
||||||
use Toby\Eloquent\Models\VacationLimit;
|
|
||||||
use Toby\Eloquent\Scopes\SelectedYearPeriodScope;
|
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
@ -16,10 +13,5 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
Carbon::macro("toDisplayString", fn() => $this->translatedFormat("j F Y"));
|
Carbon::macro("toDisplayString", fn() => $this->translatedFormat("j F Y"));
|
||||||
Carbon::macro("toDisplayDate", fn() => $this->translatedFormat("d.m.Y"));
|
Carbon::macro("toDisplayDate", fn() => $this->translatedFormat("d.m.Y"));
|
||||||
|
|
||||||
$selectedYearPeriodScope = $this->app->make(SelectedYearPeriodScope::class);
|
|
||||||
|
|
||||||
VacationLimit::addGlobalScope($selectedYearPeriodScope);
|
|
||||||
Holiday::addGlobalScope($selectedYearPeriodScope);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,7 @@ class CalendarGenerator
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected YearPeriodRetriever $yearPeriodRetriever,
|
protected YearPeriodRetriever $yearPeriodRetriever,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function generate(Carbon $month): array
|
public function generate(Carbon $month): array
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ namespace Toby\Domain\Enums;
|
|||||||
enum EmploymentForm: string
|
enum EmploymentForm: string
|
||||||
{
|
{
|
||||||
case EmploymentContract = "employment_contract";
|
case EmploymentContract = "employment_contract";
|
||||||
case ComissionContract = "commission_contract";
|
case CommissionContract = "commission_contract";
|
||||||
case B2bContract = "b2b_contract";
|
case B2bContract = "b2b_contract";
|
||||||
case BoardMemberContract = "board_member_contract";
|
case BoardMemberContract = "board_member_contract";
|
||||||
|
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestAcceptedByAdministrative
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestAcceptedByTechnical
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestApproved
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestCancelled
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestCreated
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestRejected
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,5 @@ class VacationRequestStateChanged
|
|||||||
public ?VacationRequestState $from,
|
public ?VacationRequestState $from,
|
||||||
public VacationRequestState $to,
|
public VacationRequestState $to,
|
||||||
public ?User $user = null,
|
public ?User $user = null,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestWaitsForAdminApproval
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ class VacationRequestWaitsForTechApproval
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public VacationRequest $vacationRequest,
|
public VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,7 @@ class HandleAcceptedByAdministrativeVacationRequest
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequestStateManager $stateManager,
|
protected VacationRequestStateManager $stateManager,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestAcceptedByAdministrative $event): void
|
public function handle(VacationRequestAcceptedByAdministrative $event): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ class HandleAcceptedByTechnicalVacationRequest
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationTypeConfigRetriever $configRetriever,
|
protected VacationTypeConfigRetriever $configRetriever,
|
||||||
protected VacationRequestStateManager $stateManager,
|
protected VacationRequestStateManager $stateManager,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestAcceptedByTechnical $event): void
|
public function handle(VacationRequestAcceptedByTechnical $event): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ class HandleCreatedVacationRequest
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationTypeConfigRetriever $configRetriever,
|
protected VacationTypeConfigRetriever $configRetriever,
|
||||||
protected VacationRequestStateManager $stateManager,
|
protected VacationRequestStateManager $stateManager,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestCreated $event): void
|
public function handle(VacationRequestCreated $event): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ use Toby\Eloquent\Models\User;
|
|||||||
class SendApprovedVacationRequestNotification
|
class SendApprovedVacationRequestNotification
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestApproved $event): void
|
public function handle(VacationRequestApproved $event): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ use Toby\Eloquent\Models\User;
|
|||||||
class SendCancelledVacationRequestNotification
|
class SendCancelledVacationRequestNotification
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestCancelled $event): void
|
public function handle(VacationRequestCancelled $event): void
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,7 @@ use Toby\Domain\Notifications\VacationRequestCreatedOnEmployeeBehalf;
|
|||||||
class SendCreatedVacationRequestNotification
|
class SendCreatedVacationRequestNotification
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestCreated $event): void
|
public function handle(VacationRequestCreated $event): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ use Toby\Eloquent\Models\User;
|
|||||||
class SendRejectedVacationRequestNotification
|
class SendRejectedVacationRequestNotification
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestRejected $event): void
|
public function handle(VacationRequestRejected $event): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ use Toby\Eloquent\Models\User;
|
|||||||
class SendWaitedForAdministrativeVacationRequestNotification
|
class SendWaitedForAdministrativeVacationRequestNotification
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestWaitsForAdminApproval $event): void
|
public function handle(VacationRequestWaitsForAdminApproval $event): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ use Toby\Eloquent\Models\User;
|
|||||||
class SendWaitedForTechnicalVacationRequestNotification
|
class SendWaitedForTechnicalVacationRequestNotification
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(VacationRequestWaitsForTechApproval $event): void
|
public function handle(VacationRequestWaitsForTechApproval $event): void
|
||||||
{
|
{
|
||||||
|
@ -18,8 +18,7 @@ class VacationRequestApprovedNotification extends Notification
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
protected User $user,
|
protected User $user,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function via(): array
|
public function via(): array
|
||||||
{
|
{
|
||||||
|
@ -18,8 +18,7 @@ class VacationRequestCancelledNotification extends Notification
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
protected User $user,
|
protected User $user,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function via(): array
|
public function via(): array
|
||||||
{
|
{
|
||||||
|
@ -16,8 +16,7 @@ class VacationRequestCreatedNotification extends Notification
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function via(): array
|
public function via(): array
|
||||||
{
|
{
|
||||||
|
@ -16,8 +16,7 @@ class VacationRequestCreatedOnEmployeeBehalf extends Notification
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function via(): array
|
public function via(): array
|
||||||
{
|
{
|
||||||
|
@ -18,8 +18,7 @@ class VacationRequestRejectedNotification extends Notification
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
protected User $user,
|
protected User $user,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function via(): array
|
public function via(): array
|
||||||
{
|
{
|
||||||
|
@ -18,8 +18,7 @@ class VacationRequestWaitsForAdminApprovalNotification extends Notification
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
protected User $user,
|
protected User $user,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function via(): array
|
public function via(): array
|
||||||
{
|
{
|
||||||
|
@ -18,8 +18,7 @@ class VacationRequestWaitsForTechApprovalNotification extends Notification
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
protected User $user,
|
protected User $user,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function via(): array
|
public function via(): array
|
||||||
{
|
{
|
||||||
|
@ -41,8 +41,7 @@ class TimesheetPerUserSheet implements WithTitle, WithHeadings, WithEvents, With
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected User $user,
|
protected User $user,
|
||||||
protected Carbon $month,
|
protected Carbon $month,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function title(): string
|
public function title(): string
|
||||||
{
|
{
|
||||||
|
93
app/Domain/UserVacationStatsRetriever.php
Normal file
93
app/Domain/UserVacationStatsRetriever.php
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Domain;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Toby\Domain\Enums\VacationType;
|
||||||
|
use Toby\Eloquent\Models\User;
|
||||||
|
use Toby\Eloquent\Models\YearPeriod;
|
||||||
|
|
||||||
|
class UserVacationStatsRetriever
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected VacationTypeConfigRetriever $configRetriever,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function getUsedVacationDays(User $user, YearPeriod $yearPeriod): int
|
||||||
|
{
|
||||||
|
return $user
|
||||||
|
->vacations()
|
||||||
|
->where("year_period_id", $yearPeriod->id)
|
||||||
|
->whereRelation(
|
||||||
|
"vacationRequest",
|
||||||
|
fn(Builder $query) => $query
|
||||||
|
->whereIn("type", $this->getLimitableVacationTypes())
|
||||||
|
->states(VacationRequestStatesRetriever::successStates()),
|
||||||
|
)
|
||||||
|
->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPendingVacationDays(User $user, YearPeriod $yearPeriod): int
|
||||||
|
{
|
||||||
|
return $user
|
||||||
|
->vacations()
|
||||||
|
->where("year_period_id", $yearPeriod->id)
|
||||||
|
->whereRelation(
|
||||||
|
"vacationRequest",
|
||||||
|
fn(Builder $query) => $query
|
||||||
|
->whereIn("type", $this->getLimitableVacationTypes())
|
||||||
|
->states(VacationRequestStatesRetriever::pendingStates()),
|
||||||
|
)
|
||||||
|
->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOtherApprovedVacationDays(User $user, YearPeriod $yearPeriod): int
|
||||||
|
{
|
||||||
|
return $user
|
||||||
|
->vacations()
|
||||||
|
->where("year_period_id", $yearPeriod->id)
|
||||||
|
->whereRelation(
|
||||||
|
"vacationRequest",
|
||||||
|
fn(Builder $query) => $query
|
||||||
|
->whereIn("type", $this->getNotLimitableVacationTypes())
|
||||||
|
->states(VacationRequestStatesRetriever::successStates()),
|
||||||
|
)
|
||||||
|
->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRemainingVacationDays(User $user, YearPeriod $yearPeriod): int
|
||||||
|
{
|
||||||
|
$limit = $this->getVacationDaysLimit($user, $yearPeriod);
|
||||||
|
$used = $this->getUsedVacationDays($user, $yearPeriod);
|
||||||
|
$pending = $this->getPendingVacationDays($user, $yearPeriod);
|
||||||
|
|
||||||
|
return $limit - $used - $pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVacationDaysLimit(User $user, YearPeriod $yearPeriod): int
|
||||||
|
{
|
||||||
|
$limit = $user->vacationLimits()
|
||||||
|
->where("year_period_id", $yearPeriod->id)
|
||||||
|
->first()
|
||||||
|
->days;
|
||||||
|
|
||||||
|
return $limit ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLimitableVacationTypes(): Collection
|
||||||
|
{
|
||||||
|
$types = new Collection(VacationType::cases());
|
||||||
|
|
||||||
|
return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getNotLimitableVacationTypes(): Collection
|
||||||
|
{
|
||||||
|
$types = new Collection(VacationType::cases());
|
||||||
|
|
||||||
|
return $types->filter(fn(VacationType $type) => !$this->configRetriever->hasLimit($type));
|
||||||
|
}
|
||||||
|
}
|
@ -31,8 +31,7 @@ class VacationRequestStateManager
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected Auth $auth,
|
protected Auth $auth,
|
||||||
protected Dispatcher $dispatcher,
|
protected Dispatcher $dispatcher,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function markAsCreated(VacationRequest $vacationRequest, ?User $user = null): void
|
public function markAsCreated(VacationRequest $vacationRequest, ?User $user = null): void
|
||||||
{
|
{
|
||||||
|
@ -16,8 +16,7 @@ class VacationTypeConfigRetriever
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected Repository $config,
|
protected Repository $config,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function needsTechnicalApproval(VacationType $type): bool
|
public function needsTechnicalApproval(VacationType $type): bool
|
||||||
{
|
{
|
||||||
|
@ -19,8 +19,7 @@ class DoesNotExceedLimitRule implements VacationRequestRule
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationTypeConfigRetriever $configRetriever,
|
protected VacationTypeConfigRetriever $configRetriever,
|
||||||
protected VacationDaysCalculator $vacationDaysCalculator,
|
protected VacationDaysCalculator $vacationDaysCalculator,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function check(VacationRequest $vacationRequest): bool
|
public function check(VacationRequest $vacationRequest): bool
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,7 @@ class MinimumOneVacationDayRule implements VacationRequestRule
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationDaysCalculator $vacationDaysCalculator,
|
protected VacationDaysCalculator $vacationDaysCalculator,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function check(VacationRequest $vacationRequest): bool
|
public function check(VacationRequest $vacationRequest): bool
|
||||||
{
|
{
|
||||||
|
@ -26,8 +26,7 @@ class VacationRequestValidator
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected Container $container,
|
protected Container $container,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
|
@ -14,8 +14,7 @@ class UserAvatarGenerator
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected InitialAvatar $generator,
|
protected InitialAvatar $generator,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function generateFor(User $user): string
|
public function generateFor(User $user): string
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ class YearPeriodRetriever
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected Session $session,
|
protected Session $session,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function selected(): YearPeriod
|
public function selected(): YearPeriod
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Toby\Eloquent\Models;
|
namespace Toby\Eloquent\Models;
|
||||||
|
|
||||||
|
use Database\Factories\VacationRequestActivityFactory;
|
||||||
|
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\States\VacationRequest\VacationRequestState;
|
use Toby\Domain\States\VacationRequest\VacationRequestState;
|
||||||
@ -17,6 +19,8 @@ use Toby\Domain\States\VacationRequest\VacationRequestState;
|
|||||||
*/
|
*/
|
||||||
class VacationRequestActivity extends Model
|
class VacationRequestActivity extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
@ -33,4 +37,9 @@ class VacationRequestActivity extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(VacationRequest::class);
|
return $this->belongsTo(VacationRequest::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function newFactory(): VacationRequestActivityFactory
|
||||||
|
{
|
||||||
|
return VacationRequestActivityFactory::new();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,7 @@ class UserObserver
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected UserAvatarGenerator $generator,
|
protected UserAvatarGenerator $generator,
|
||||||
protected YearPeriodRetriever $yearPeriodRetriever,
|
protected YearPeriodRetriever $yearPeriodRetriever,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function created(User $user): void
|
public function created(User $user): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ class VacationRequestObserver
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected Auth $auth,
|
protected Auth $auth,
|
||||||
protected Dispatcher $dispatcher,
|
protected Dispatcher $dispatcher,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function creating(VacationRequest $vacationRequest): void
|
public function creating(VacationRequest $vacationRequest): void
|
||||||
{
|
{
|
||||||
|
@ -14,8 +14,7 @@ class YearPeriodObserver
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected UserAvatarGenerator $generator,
|
protected UserAvatarGenerator $generator,
|
||||||
protected PolishHolidaysRetriever $polishHolidaysRetriever,
|
protected PolishHolidaysRetriever $polishHolidaysRetriever,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function created(YearPeriod $yearPeriod): void
|
public function created(YearPeriod $yearPeriod): void
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,7 @@ class SelectedYearPeriodScope implements Scope
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected YearPeriodRetriever $yearPeriodRetriever,
|
protected YearPeriodRetriever $yearPeriodRetriever,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function apply(Builder $builder, Model $model): Builder
|
public function apply(Builder $builder, Model $model): Builder
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Infrastructure\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Toby\Domain\UserVacationStatsRetriever;
|
||||||
|
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
||||||
|
use Toby\Eloquent\Models\User;
|
||||||
|
use Toby\Infrastructure\Http\Controllers\Controller;
|
||||||
|
use Toby\Infrastructure\Http\Requests\Api\CalculateVacationStatsRequest;
|
||||||
|
|
||||||
|
class CalculateUserVacationStatsController extends Controller
|
||||||
|
{
|
||||||
|
public function __invoke(
|
||||||
|
CalculateVacationStatsRequest $request,
|
||||||
|
UserVacationStatsRetriever $vacationStatsRetriever,
|
||||||
|
YearPeriodRetriever $yearPeriodRetriever,
|
||||||
|
): JsonResponse {
|
||||||
|
/** @var User $user */
|
||||||
|
$user = User::query()->find($request->get("user"));
|
||||||
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
|
|
||||||
|
$limit = $vacationStatsRetriever->getVacationDaysLimit($user, $yearPeriod);
|
||||||
|
$used = $vacationStatsRetriever->getUsedVacationDays($user, $yearPeriod);
|
||||||
|
$pending = $vacationStatsRetriever->getPendingVacationDays($user, $yearPeriod);
|
||||||
|
$other = $vacationStatsRetriever->getOtherApprovedVacationDays($user, $yearPeriod);
|
||||||
|
$remaining = $limit - $used - $pending;
|
||||||
|
|
||||||
|
return new JsonResponse([
|
||||||
|
"limit" => $limit,
|
||||||
|
"remaining" => $remaining,
|
||||||
|
"used" => $used,
|
||||||
|
"pending" => $pending,
|
||||||
|
"other" => $other,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
68
app/Infrastructure/Http/Controllers/DashboardController.php
Normal file
68
app/Infrastructure/Http/Controllers/DashboardController.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Infrastructure\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Inertia\Response;
|
||||||
|
use Toby\Domain\UserVacationStatsRetriever;
|
||||||
|
use Toby\Domain\VacationRequestStatesRetriever;
|
||||||
|
use Toby\Eloquent\Models\Holiday;
|
||||||
|
use Toby\Eloquent\Models\Vacation;
|
||||||
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
use Toby\Eloquent\Models\YearPeriod;
|
||||||
|
use Toby\Infrastructure\Http\Resources\AbsenceResource;
|
||||||
|
use Toby\Infrastructure\Http\Resources\HolidayResource;
|
||||||
|
use Toby\Infrastructure\Http\Resources\VacationRequestResource;
|
||||||
|
|
||||||
|
class DashboardController extends Controller
|
||||||
|
{
|
||||||
|
public function __invoke(Request $request, UserVacationStatsRetriever $vacationStatsRetriever): Response
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
$now = Carbon::now();
|
||||||
|
$yearPeriod = YearPeriod::findByYear($now->year);
|
||||||
|
|
||||||
|
$absences = Vacation::query()
|
||||||
|
->with(["user", "vacationRequest"])
|
||||||
|
->whereDate("date", $now)
|
||||||
|
->whereRelation(
|
||||||
|
"vacationRequest",
|
||||||
|
fn(Builder $query) => $query->states(VacationRequestStatesRetriever::successStates()),
|
||||||
|
)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$vacationRequests = VacationRequest::query()
|
||||||
|
->latest("updated_at")
|
||||||
|
->limit(3)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$holidays = Holiday::query()
|
||||||
|
->whereDate("date", ">=", $now)
|
||||||
|
->latest()
|
||||||
|
->limit(3)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$limit = $vacationStatsRetriever->getVacationDaysLimit($user, $yearPeriod);
|
||||||
|
$used = $vacationStatsRetriever->getUsedVacationDays($user, $yearPeriod);
|
||||||
|
$pending = $vacationStatsRetriever->getPendingVacationDays($user, $yearPeriod);
|
||||||
|
$other = $vacationStatsRetriever->getOtherApprovedVacationDays($user, $yearPeriod);
|
||||||
|
$remaining = $limit - $used - $pending;
|
||||||
|
|
||||||
|
return inertia("Dashboard", [
|
||||||
|
"absences" => AbsenceResource::collection($absences),
|
||||||
|
"vacationRequests" => VacationRequestResource::collection($vacationRequests),
|
||||||
|
"holidays" => HolidayResource::collection($holidays),
|
||||||
|
"stats" => [
|
||||||
|
"limit" => $limit,
|
||||||
|
"remaining" => $remaining,
|
||||||
|
"used" => $used,
|
||||||
|
"pending" => $pending,
|
||||||
|
"other" => $other,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ 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;
|
||||||
|
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
||||||
use Toby\Eloquent\Models\Holiday;
|
use Toby\Eloquent\Models\Holiday;
|
||||||
use Toby\Infrastructure\Http\Requests\HolidayRequest;
|
use Toby\Infrastructure\Http\Requests\HolidayRequest;
|
||||||
use Toby\Infrastructure\Http\Resources\HolidayFormDataResource;
|
use Toby\Infrastructure\Http\Resources\HolidayFormDataResource;
|
||||||
@ -15,9 +16,12 @@ use Toby\Infrastructure\Http\Resources\HolidayResource;
|
|||||||
|
|
||||||
class HolidayController extends Controller
|
class HolidayController extends Controller
|
||||||
{
|
{
|
||||||
public function index(Request $request): Response
|
public function index(Request $request, YearPeriodRetriever $yearPeriodRetriever): Response
|
||||||
{
|
{
|
||||||
$holidays = Holiday::query()
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
|
|
||||||
|
$holidays = $yearPeriod
|
||||||
|
->holidays()
|
||||||
->orderBy("date")
|
->orderBy("date")
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
@ -6,24 +6,41 @@ namespace Toby\Infrastructure\Http\Controllers;
|
|||||||
|
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
|
use Toby\Domain\UserVacationStatsRetriever;
|
||||||
|
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
||||||
use Toby\Eloquent\Models\VacationLimit;
|
use Toby\Eloquent\Models\VacationLimit;
|
||||||
|
use Toby\Eloquent\Models\YearPeriod;
|
||||||
use Toby\Infrastructure\Http\Requests\VacationLimitRequest;
|
use Toby\Infrastructure\Http\Requests\VacationLimitRequest;
|
||||||
use Toby\Infrastructure\Http\Resources\VacationLimitResource;
|
use Toby\Infrastructure\Http\Resources\UserResource;
|
||||||
|
|
||||||
class VacationLimitController extends Controller
|
class VacationLimitController extends Controller
|
||||||
{
|
{
|
||||||
public function edit(): Response
|
public function edit(YearPeriodRetriever $yearPeriodRetriever, UserVacationStatsRetriever $statsRetriever): Response
|
||||||
{
|
{
|
||||||
$this->authorize("manageVacationLimits");
|
$this->authorize("manageVacationLimits");
|
||||||
|
|
||||||
$limits = VacationLimit::query()
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
|
$previousYearPeriod = YearPeriod::findByYear($yearPeriod->year - 1);
|
||||||
|
|
||||||
|
$limits = $yearPeriod
|
||||||
|
->vacationLimits()
|
||||||
->with("user")
|
->with("user")
|
||||||
->orderByUserField("last_name")
|
->orderByUserField("last_name")
|
||||||
->orderByUserField("first_name")
|
->orderByUserField("first_name")
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
$limitsResource = $limits->map(fn(VacationLimit $limit) => [
|
||||||
|
"id" => $limit->id,
|
||||||
|
"user" => new UserResource($limit->user),
|
||||||
|
"hasVacation" => $limit->hasVacation(),
|
||||||
|
"days" => $limit->days,
|
||||||
|
"remainingLastYear" => $previousYearPeriod
|
||||||
|
? $statsRetriever->getRemainingVacationDays($limit->user, $previousYearPeriod)
|
||||||
|
: 0,
|
||||||
|
]);
|
||||||
|
|
||||||
return inertia("VacationLimits", [
|
return inertia("VacationLimits", [
|
||||||
"limits" => VacationLimitResource::collection($limits),
|
"limits" => $limitsResource,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ namespace Toby\Infrastructure\Http\Controllers;
|
|||||||
|
|
||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
use Illuminate\Auth\Access\AuthorizationException;
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
|
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;
|
||||||
@ -88,9 +89,15 @@ class VacationRequestController extends Controller
|
|||||||
return $pdf->stream();
|
return $pdf->stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(Request $request): Response
|
public function create(Request $request, YearPeriodRetriever $yearPeriodRetriever): Response
|
||||||
{
|
{
|
||||||
|
$yearPeriod = $yearPeriodRetriever->selected();
|
||||||
|
|
||||||
$users = User::query()
|
$users = User::query()
|
||||||
|
->whereRelation(
|
||||||
|
"vacationlimits",
|
||||||
|
fn(Builder $query) => $query->where("year_period_id", $yearPeriod->id)->whereNotNull("days"),
|
||||||
|
)
|
||||||
->orderBy("last_name")
|
->orderBy("last_name")
|
||||||
->orderBy("first_name")
|
->orderBy("first_name")
|
||||||
->get();
|
->get();
|
||||||
|
@ -13,8 +13,7 @@ class HandleInertiaRequests extends Middleware
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected YearPeriodRetriever $yearPeriodRetriever,
|
protected YearPeriodRetriever $yearPeriodRetriever,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function share(Request $request): array
|
public function share(Request $request): array
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Toby\Infrastructure\Http\Requests\Api;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CalculateVacationStatsRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"user" => ["required", "exists:users,id"],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ namespace Toby\Infrastructure\Http\Resources;
|
|||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
class VacationLimitResource extends JsonResource
|
class AbsenceResource extends JsonResource
|
||||||
{
|
{
|
||||||
public static $wrap = null;
|
public static $wrap = null;
|
||||||
|
|
||||||
@ -15,8 +15,7 @@ class VacationLimitResource extends JsonResource
|
|||||||
return [
|
return [
|
||||||
"id" => $this->id,
|
"id" => $this->id,
|
||||||
"user" => new UserResource($this->user),
|
"user" => new UserResource($this->user),
|
||||||
"hasVacation" => $this->hasVacation(),
|
"date" => $this->date->toDisplayString(),
|
||||||
"days" => $this->days,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,8 +18,7 @@ class ClearVacationRequestDaysInGoogleCalendar implements ShouldQueue
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
|
@ -18,8 +18,7 @@ class SendVacationRequestDaysToGoogleCalendar implements ShouldQueue
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected VacationRequest $vacationRequest,
|
protected VacationRequest $vacationRequest,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"maatwebsite/excel": "^3.1"
|
"maatwebsite/excel": "^3.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"blumilksoftware/codestyle": "^0.9.0",
|
"blumilksoftware/codestyle": "^0.10.0",
|
||||||
"spatie/laravel-ignition": "^1.0",
|
"spatie/laravel-ignition": "^1.0",
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"laravel/dusk": "^6.21",
|
"laravel/dusk": "^6.21",
|
||||||
@ -47,6 +47,11 @@
|
|||||||
"ecs": "./vendor/bin/ecs check --clear-cache",
|
"ecs": "./vendor/bin/ecs check --clear-cache",
|
||||||
"ecsf": "./vendor/bin/ecs check --clear-cache --fix",
|
"ecsf": "./vendor/bin/ecs check --clear-cache --fix",
|
||||||
"test": "@php artisan test",
|
"test": "@php artisan test",
|
||||||
|
"fresh": "@php artisan migrate:fresh",
|
||||||
|
"fresh:demo": [
|
||||||
|
"composer fresh",
|
||||||
|
"@php artisan db:seed --class=DemoSeeder"
|
||||||
|
],
|
||||||
"post-autoload-dump": [
|
"post-autoload-dump": [
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
"@php artisan package:discover --ansi"
|
"@php artisan package:discover --ansi"
|
||||||
|
713
composer.lock
generated
713
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": "c090431972dc8bfbe198ce9fc9f816f3",
|
"content-hash": "d3f019c6e743a3249af78baefe7acb01",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asm89/stack-cors",
|
"name": "asm89/stack-cors",
|
||||||
@ -7468,21 +7468,22 @@
|
|||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "blumilksoftware/codestyle",
|
"name": "blumilksoftware/codestyle",
|
||||||
"version": "v0.9.0",
|
"version": "v0.10.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/blumilksoftware/codestyle.git",
|
"url": "https://github.com/blumilksoftware/codestyle.git",
|
||||||
"reference": "c1e06d9df22adaf1f0ae646dfbc0620b28e9a79a"
|
"reference": "39da9ec4922e633e8f0bd065f244365217e9d00a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/c1e06d9df22adaf1f0ae646dfbc0620b28e9a79a",
|
"url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/39da9ec4922e633e8f0bd065f244365217e9d00a",
|
||||||
"reference": "c1e06d9df22adaf1f0ae646dfbc0620b28e9a79a",
|
"reference": "39da9ec4922e633e8f0bd065f244365217e9d00a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
"kubawerlos/php-cs-fixer-custom-fixers": "^3.7",
|
||||||
"php": "^8.0",
|
"php": "^8.0",
|
||||||
"symplify/easy-coding-standard": "10.0.8"
|
"symplify/easy-coding-standard": "10.1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"composer/composer": "2.*",
|
"composer/composer": "2.*",
|
||||||
@ -7509,9 +7510,299 @@
|
|||||||
"description": "Blumilk codestyle configurator",
|
"description": "Blumilk codestyle configurator",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/blumilksoftware/codestyle/issues",
|
"issues": "https://github.com/blumilksoftware/codestyle/issues",
|
||||||
"source": "https://github.com/blumilksoftware/codestyle/tree/v0.9.0"
|
"source": "https://github.com/blumilksoftware/codestyle/tree/v0.10.0"
|
||||||
},
|
},
|
||||||
"time": "2022-01-04T07:21:36+00:00"
|
"time": "2022-02-23T07:26:50+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "composer/pcre",
|
||||||
|
"version": "3.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/composer/pcre.git",
|
||||||
|
"reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd",
|
||||||
|
"reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.4 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "^1.3",
|
||||||
|
"phpstan/phpstan-strict-rules": "^1.1",
|
||||||
|
"symfony/phpunit-bridge": "^5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "3.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Composer\\Pcre\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Jordi Boggiano",
|
||||||
|
"email": "j.boggiano@seld.be",
|
||||||
|
"homepage": "http://seld.be"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
|
||||||
|
"keywords": [
|
||||||
|
"PCRE",
|
||||||
|
"preg",
|
||||||
|
"regex",
|
||||||
|
"regular expression"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/composer/pcre/issues",
|
||||||
|
"source": "https://github.com/composer/pcre/tree/3.0.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://packagist.com",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/composer",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-02-25T20:21:48+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "composer/semver",
|
||||||
|
"version": "3.2.9",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/composer/semver.git",
|
||||||
|
"reference": "a951f614bd64dcd26137bc9b7b2637ddcfc57649"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/composer/semver/zipball/a951f614bd64dcd26137bc9b7b2637ddcfc57649",
|
||||||
|
"reference": "a951f614bd64dcd26137bc9b7b2637ddcfc57649",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "^1.4",
|
||||||
|
"symfony/phpunit-bridge": "^4.2 || ^5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "3.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Composer\\Semver\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nils Adermann",
|
||||||
|
"email": "naderman@naderman.de",
|
||||||
|
"homepage": "http://www.naderman.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jordi Boggiano",
|
||||||
|
"email": "j.boggiano@seld.be",
|
||||||
|
"homepage": "http://seld.be"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rob Bast",
|
||||||
|
"email": "rob.bast@gmail.com",
|
||||||
|
"homepage": "http://robbast.nl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Semver library that offers utilities, version constraint parsing and validation.",
|
||||||
|
"keywords": [
|
||||||
|
"semantic",
|
||||||
|
"semver",
|
||||||
|
"validation",
|
||||||
|
"versioning"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"irc": "irc://irc.freenode.org/composer",
|
||||||
|
"issues": "https://github.com/composer/semver/issues",
|
||||||
|
"source": "https://github.com/composer/semver/tree/3.2.9"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://packagist.com",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/composer",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-02-04T13:58:43+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "composer/xdebug-handler",
|
||||||
|
"version": "3.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/composer/xdebug-handler.git",
|
||||||
|
"reference": "ced299686f41dce890debac69273b47ffe98a40c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
|
||||||
|
"reference": "ced299686f41dce890debac69273b47ffe98a40c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"composer/pcre": "^1 || ^2 || ^3",
|
||||||
|
"php": "^7.2.5 || ^8.0",
|
||||||
|
"psr/log": "^1 || ^2 || ^3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "^1.0",
|
||||||
|
"phpstan/phpstan-strict-rules": "^1.1",
|
||||||
|
"symfony/phpunit-bridge": "^6.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Composer\\XdebugHandler\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "John Stevenson",
|
||||||
|
"email": "john-stevenson@blueyonder.co.uk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Restarts a process without Xdebug.",
|
||||||
|
"keywords": [
|
||||||
|
"Xdebug",
|
||||||
|
"performance"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"irc": "irc://irc.freenode.org/composer",
|
||||||
|
"issues": "https://github.com/composer/xdebug-handler/issues",
|
||||||
|
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://packagist.com",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/composer",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-02-25T21:32:43+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "doctrine/annotations",
|
||||||
|
"version": "1.13.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/doctrine/annotations.git",
|
||||||
|
"reference": "5b668aef16090008790395c02c893b1ba13f7e08"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08",
|
||||||
|
"reference": "5b668aef16090008790395c02c893b1ba13f7e08",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"doctrine/lexer": "1.*",
|
||||||
|
"ext-tokenizer": "*",
|
||||||
|
"php": "^7.1 || ^8.0",
|
||||||
|
"psr/cache": "^1 || ^2 || ^3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"doctrine/cache": "^1.11 || ^2.0",
|
||||||
|
"doctrine/coding-standard": "^6.0 || ^8.1",
|
||||||
|
"phpstan/phpstan": "^0.12.20",
|
||||||
|
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
|
||||||
|
"symfony/cache": "^4.4 || ^5.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Guilherme Blanco",
|
||||||
|
"email": "guilhermeblanco@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Roman Borschel",
|
||||||
|
"email": "roman@code-factory.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Benjamin Eberlei",
|
||||||
|
"email": "kontakt@beberlei.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jonathan Wage",
|
||||||
|
"email": "jonwage@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Johannes Schmitt",
|
||||||
|
"email": "schmittjoh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Docblock Annotations Parser",
|
||||||
|
"homepage": "https://www.doctrine-project.org/projects/annotations.html",
|
||||||
|
"keywords": [
|
||||||
|
"annotations",
|
||||||
|
"docblock",
|
||||||
|
"parser"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/doctrine/annotations/issues",
|
||||||
|
"source": "https://github.com/doctrine/annotations/tree/1.13.2"
|
||||||
|
},
|
||||||
|
"time": "2021-08-05T19:00:23+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
@ -7720,6 +8011,95 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-01-07T12:00:00+00:00"
|
"time": "2022-01-07T12:00:00+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
|
"version": "v3.6.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
||||||
|
"reference": "1975e4453eb2726d1f50da0ce7fa91295029a4fa"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/1975e4453eb2726d1f50da0ce7fa91295029a4fa",
|
||||||
|
"reference": "1975e4453eb2726d1f50da0ce7fa91295029a4fa",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"composer/semver": "^3.2",
|
||||||
|
"composer/xdebug-handler": "^3.0",
|
||||||
|
"doctrine/annotations": "^1.13",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-tokenizer": "*",
|
||||||
|
"php": "^7.4 || ^8.0",
|
||||||
|
"php-cs-fixer/diff": "^2.0",
|
||||||
|
"symfony/console": "^5.4 || ^6.0",
|
||||||
|
"symfony/event-dispatcher": "^5.4 || ^6.0",
|
||||||
|
"symfony/filesystem": "^5.4 || ^6.0",
|
||||||
|
"symfony/finder": "^5.4 || ^6.0",
|
||||||
|
"symfony/options-resolver": "^5.4 || ^6.0",
|
||||||
|
"symfony/polyfill-mbstring": "^1.23",
|
||||||
|
"symfony/polyfill-php80": "^1.23",
|
||||||
|
"symfony/polyfill-php81": "^1.23",
|
||||||
|
"symfony/process": "^5.4 || ^6.0",
|
||||||
|
"symfony/stopwatch": "^5.4 || ^6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"justinrainbow/json-schema": "^5.2",
|
||||||
|
"keradus/cli-executor": "^1.5",
|
||||||
|
"mikey179/vfsstream": "^1.6.10",
|
||||||
|
"php-coveralls/php-coveralls": "^2.5.2",
|
||||||
|
"php-cs-fixer/accessible-object": "^1.1",
|
||||||
|
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2",
|
||||||
|
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1",
|
||||||
|
"phpspec/prophecy": "^1.15",
|
||||||
|
"phpspec/prophecy-phpunit": "^2.0",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"phpunitgoodpractices/polyfill": "^1.5",
|
||||||
|
"phpunitgoodpractices/traits": "^1.9.1",
|
||||||
|
"symfony/phpunit-bridge": "^6.0",
|
||||||
|
"symfony/yaml": "^5.4 || ^6.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-dom": "For handling output formats in XML",
|
||||||
|
"ext-mbstring": "For handling non-UTF8 characters."
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"php-cs-fixer"
|
||||||
|
],
|
||||||
|
"type": "application",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"PhpCsFixer\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dariusz Rumiński",
|
||||||
|
"email": "dariusz.ruminski@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A tool to automatically fix PHP code style",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues",
|
||||||
|
"source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.6.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/keradus",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-02-07T18:02:40+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "hamcrest/hamcrest-php",
|
"name": "hamcrest/hamcrest-php",
|
||||||
"version": "v2.0.1",
|
"version": "v2.0.1",
|
||||||
@ -7771,6 +8151,53 @@
|
|||||||
},
|
},
|
||||||
"time": "2020-07-09T08:09:16+00:00"
|
"time": "2020-07-09T08:09:16+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "kubawerlos/php-cs-fixer-custom-fixers",
|
||||||
|
"version": "v3.8.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git",
|
||||||
|
"reference": "cddb6d7a365ce95dd554c357ebc16318b5e6bd0d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/cddb6d7a365ce95dd554c357ebc16318b5e6bd0d",
|
||||||
|
"reference": "cddb6d7a365ce95dd554c357ebc16318b5e6bd0d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-filter": "*",
|
||||||
|
"ext-tokenizer": "*",
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.6.0",
|
||||||
|
"php": "^7.4 || ^8.0",
|
||||||
|
"symfony/finder": "^4.0 || ^5.0 || ^6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^8.5.3 || ^9.1.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"PhpCsFixerCustomFixers\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Kuba Werłos",
|
||||||
|
"email": "werlos@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A set of custom fixers for PHP CS Fixer",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/issues",
|
||||||
|
"source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.8.1"
|
||||||
|
},
|
||||||
|
"time": "2022-02-15T17:06:25+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/dusk",
|
"name": "laravel/dusk",
|
||||||
"version": "v6.22.1",
|
"version": "v6.22.1",
|
||||||
@ -8172,6 +8599,58 @@
|
|||||||
},
|
},
|
||||||
"time": "2022-02-21T01:04:05+00:00"
|
"time": "2022-02-21T01:04:05+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "php-cs-fixer/diff",
|
||||||
|
"version": "v2.0.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/PHP-CS-Fixer/diff.git",
|
||||||
|
"reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3",
|
||||||
|
"reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^5.6 || ^7.0 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0",
|
||||||
|
"symfony/process": "^3.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sebastian Bergmann",
|
||||||
|
"email": "sebastian@phpunit.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kore Nordmann",
|
||||||
|
"email": "mail@kore-nordmann.de"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "sebastian/diff v3 backport support for PHP 5.6+",
|
||||||
|
"homepage": "https://github.com/PHP-CS-Fixer",
|
||||||
|
"keywords": [
|
||||||
|
"diff"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHP-CS-Fixer/diff/issues",
|
||||||
|
"source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2"
|
||||||
|
},
|
||||||
|
"time": "2020-10-14T08:32:19+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "php-webdriver/webdriver",
|
"name": "php-webdriver/webdriver",
|
||||||
"version": "1.12.0",
|
"version": "1.12.0",
|
||||||
@ -9977,16 +10456,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"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": {
|
||||||
@ -10044,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",
|
||||||
@ -10134,17 +10613,209 @@
|
|||||||
"time": "2022-02-15T11:02:15+00:00"
|
"time": "2022-02-15T11:02:15+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symplify/easy-coding-standard",
|
"name": "symfony/filesystem",
|
||||||
"version": "10.0.8",
|
"version": "v6.0.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symplify/easy-coding-standard.git",
|
"url": "https://github.com/symfony/filesystem.git",
|
||||||
"reference": "12ef3b0f500d485e6313926e5f2900a74c578394"
|
"reference": "6646c13f787057d64701a3a0235cf9567c6ccbbd"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/12ef3b0f500d485e6313926e5f2900a74c578394",
|
"url": "https://api.github.com/repos/symfony/filesystem/zipball/6646c13f787057d64701a3a0235cf9567c6ccbbd",
|
||||||
"reference": "12ef3b0f500d485e6313926e5f2900a74c578394",
|
"reference": "6646c13f787057d64701a3a0235cf9567c6ccbbd",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.0.2",
|
||||||
|
"symfony/polyfill-ctype": "~1.8",
|
||||||
|
"symfony/polyfill-mbstring": "~1.8"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Filesystem\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides basic utilities for the filesystem",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/filesystem/tree/v6.0.5"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-02-28T07:42:30+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/options-resolver",
|
||||||
|
"version": "v6.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/options-resolver.git",
|
||||||
|
"reference": "51f7006670febe4cbcbae177cbffe93ff833250d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/51f7006670febe4cbcbae177cbffe93ff833250d",
|
||||||
|
"reference": "51f7006670febe4cbcbae177cbffe93ff833250d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.0.2",
|
||||||
|
"symfony/deprecation-contracts": "^2.1|^3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\OptionsResolver\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides an improved replacement for the array_replace PHP function",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"config",
|
||||||
|
"configuration",
|
||||||
|
"options"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/options-resolver/tree/v6.0.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-01-02T09:55:41+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/stopwatch",
|
||||||
|
"version": "v6.0.5",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/stopwatch.git",
|
||||||
|
"reference": "f2c1780607ec6502f2121d9729fd8150a655d337"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/f2c1780607ec6502f2121d9729fd8150a655d337",
|
||||||
|
"reference": "f2c1780607ec6502f2121d9729fd8150a655d337",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.0.2",
|
||||||
|
"symfony/service-contracts": "^1|^2|^3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Stopwatch\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides a way to profile code",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/stopwatch/tree/v6.0.5"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-02-21T17:15:17+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symplify/easy-coding-standard",
|
||||||
|
"version": "10.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symplify/easy-coding-standard.git",
|
||||||
|
"reference": "dcad0cff507fc3e56bf345dcd634dbea3ce0917e"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/dcad0cff507fc3e56bf345dcd634dbea3ce0917e",
|
||||||
|
"reference": "dcad0cff507fc3e56bf345dcd634dbea3ce0917e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -10174,7 +10845,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Prefixed scoped version of ECS package",
|
"description": "Prefixed scoped version of ECS package",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symplify/easy-coding-standard/tree/10.0.8"
|
"source": "https://github.com/symplify/easy-coding-standard/tree/10.1.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -10186,7 +10857,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-12-31T12:19:54+00:00"
|
"time": "2022-02-21T11:18:44+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
|
22
database/factories/VacationRequestActivityFactory.php
Normal file
22
database/factories/VacationRequestActivityFactory.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Toby\Domain\Enums\VacationRequestState;
|
||||||
|
use Toby\Eloquent\Models\VacationRequestActivity;
|
||||||
|
|
||||||
|
class VacationRequestActivityFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = VacationRequestActivity::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"from" => $this->faker->randomElement(VacationRequestState::cases()),
|
||||||
|
"to" => $this->faker->randomElement(VacationRequestState::cases()),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -19,8 +19,7 @@ class DatabaseSeeder extends Seeder
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected UserAvatarGenerator $avatarGenerator,
|
protected UserAvatarGenerator $avatarGenerator,
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
|
330
database/seeders/DemoSeeder.php
Normal file
330
database/seeders/DemoSeeder.php
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Toby\Domain\Enums\EmploymentForm;
|
||||||
|
use Toby\Domain\Enums\Role;
|
||||||
|
use Toby\Domain\Enums\VacationRequestState;
|
||||||
|
use Toby\Domain\Enums\VacationType;
|
||||||
|
use Toby\Domain\PolishHolidaysRetriever;
|
||||||
|
use Toby\Domain\VacationDaysCalculator;
|
||||||
|
use Toby\Eloquent\Helpers\UserAvatarGenerator;
|
||||||
|
use Toby\Eloquent\Models\User;
|
||||||
|
use Toby\Eloquent\Models\VacationLimit;
|
||||||
|
use Toby\Eloquent\Models\VacationRequest;
|
||||||
|
use Toby\Eloquent\Models\VacationRequestActivity;
|
||||||
|
use Toby\Eloquent\Models\YearPeriod;
|
||||||
|
|
||||||
|
class DemoSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected UserAvatarGenerator $avatarGenerator,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
User::unsetEventDispatcher();
|
||||||
|
YearPeriod::unsetEventDispatcher();
|
||||||
|
VacationRequest::unsetEventDispatcher();
|
||||||
|
|
||||||
|
$employee1 = User::factory([
|
||||||
|
"first_name" => "Jan",
|
||||||
|
"last_name" => "Kowalski",
|
||||||
|
"email" => env("LOCAL_EMAIL_FOR_LOGIN_VIA_GOOGLE"),
|
||||||
|
"employment_form" => EmploymentForm::EmploymentContract,
|
||||||
|
"position" => "programista",
|
||||||
|
"role" => Role::Employee,
|
||||||
|
"employment_date" => Carbon::createFromDate(2021, 12, 31),
|
||||||
|
"remember_token" => Str::random(10),
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$employee2 = User::factory([
|
||||||
|
"first_name" => "Anna",
|
||||||
|
"last_name" => "Nowak",
|
||||||
|
"email" => "anna.nowak@example.com",
|
||||||
|
"employment_form" => EmploymentForm::CommissionContract,
|
||||||
|
"position" => "tester",
|
||||||
|
"role" => Role::Employee,
|
||||||
|
"employment_date" => Carbon::createFromDate(2021, 5, 10),
|
||||||
|
"remember_token" => Str::random(10),
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$employee3 = User::factory([
|
||||||
|
"first_name" => "Tola",
|
||||||
|
"last_name" => "Sawicka",
|
||||||
|
"email" => "tola.sawicka@example.com",
|
||||||
|
"employment_form" => EmploymentForm::B2bContract,
|
||||||
|
"position" => "programista",
|
||||||
|
"role" => Role::Employee,
|
||||||
|
"employment_date" => Carbon::createFromDate(2021, 1, 4),
|
||||||
|
"remember_token" => Str::random(10),
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$technicalApprover = User::factory([
|
||||||
|
"first_name" => "Maciej",
|
||||||
|
"last_name" => "Ziółkowski",
|
||||||
|
"email" => "maciej.ziolkowski@example.com",
|
||||||
|
"employment_form" => EmploymentForm::BoardMemberContract,
|
||||||
|
"position" => "programista",
|
||||||
|
"role" => Role::TechnicalApprover,
|
||||||
|
"employment_date" => Carbon::createFromDate(2021, 1, 4),
|
||||||
|
"remember_token" => Str::random(10),
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$administrativeApprover = User::factory([
|
||||||
|
"first_name" => "Katarzyna",
|
||||||
|
"last_name" => "Zając",
|
||||||
|
"email" => "katarzyna.zajac@example.com",
|
||||||
|
"employment_form" => EmploymentForm::EmploymentContract,
|
||||||
|
"position" => "dyrektor",
|
||||||
|
"role" => Role::AdministrativeApprover,
|
||||||
|
"employment_date" => Carbon::createFromDate(2021, 1, 4),
|
||||||
|
"remember_token" => Str::random(10),
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$admin = User::factory([
|
||||||
|
"first_name" => "Miłosz",
|
||||||
|
"last_name" => "Borowski",
|
||||||
|
"email" => "milosz.borowski@example.com",
|
||||||
|
"employment_form" => EmploymentForm::EmploymentContract,
|
||||||
|
"position" => "administrator",
|
||||||
|
"role" => Role::Administrator,
|
||||||
|
"employment_date" => Carbon::createFromDate(2021, 1, 4),
|
||||||
|
"remember_token" => Str::random(10),
|
||||||
|
])
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$users = User::all();
|
||||||
|
|
||||||
|
$this->generateAvatarsForUsers($users);
|
||||||
|
|
||||||
|
$year = 2021;
|
||||||
|
|
||||||
|
YearPeriod::factory()
|
||||||
|
->count(2)
|
||||||
|
->sequence(
|
||||||
|
[
|
||||||
|
"year" => Carbon::createFromDate($year)->year,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"year" => Carbon::createFromDate($year + 1)->year,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
->afterCreating(function (YearPeriod $yearPeriod) use ($users): void {
|
||||||
|
foreach ($users as $user) {
|
||||||
|
VacationLimit::factory([
|
||||||
|
"days" => $user->employment_form === EmploymentForm::EmploymentContract ? 26 : null,
|
||||||
|
])
|
||||||
|
->for($yearPeriod)
|
||||||
|
->for($user)
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->afterCreating(function (YearPeriod $yearPeriod): void {
|
||||||
|
$polishHolidaysRetriever = new PolishHolidaysRetriever();
|
||||||
|
|
||||||
|
foreach ($polishHolidaysRetriever->getForYearPeriod($yearPeriod) as $holiday) {
|
||||||
|
$yearPeriod->holidays()->create([
|
||||||
|
"name" => $holiday["name"],
|
||||||
|
"date" => $holiday["date"],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$currentYearPeriod = YearPeriod::query()->where("year", 2022)->first();
|
||||||
|
|
||||||
|
/** @var VacationRequest $vacationRequestApproved */
|
||||||
|
$vacationRequestApproved = VacationRequest::factory([
|
||||||
|
"type" => VacationType::Vacation->value,
|
||||||
|
"state" => VacationRequestState::Created,
|
||||||
|
"from" => Carbon::create($currentYearPeriod->year, 1, 31)->toDateString(),
|
||||||
|
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
|
||||||
|
"comment" => "Komentarz do wniosku urlopowego.",
|
||||||
|
])
|
||||||
|
->for($employee1)
|
||||||
|
->for($employee1, "creator")
|
||||||
|
->for($currentYearPeriod)
|
||||||
|
->afterCreating(function (VacationRequest $vacationRequest): void {
|
||||||
|
$days = app(VacationDaysCalculator::class)->calculateDays(
|
||||||
|
$vacationRequest->yearPeriod,
|
||||||
|
$vacationRequest->from,
|
||||||
|
$vacationRequest->to,
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($days as $day) {
|
||||||
|
$vacationRequest->vacations()->create([
|
||||||
|
"date" => $day,
|
||||||
|
"user_id" => $vacationRequest->user->id,
|
||||||
|
"year_period_id" => $vacationRequest->yearPeriod->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => null,
|
||||||
|
"to" => VacationRequestState::Created,
|
||||||
|
])->for($vacationRequestApproved)
|
||||||
|
->for($employee1)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::Created,
|
||||||
|
"to" => VacationRequestState::WaitingForTechnical,
|
||||||
|
])->for($vacationRequestApproved)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::WaitingForTechnical,
|
||||||
|
"to" => VacationRequestState::AcceptedByTechnical,
|
||||||
|
])->for($vacationRequestApproved)
|
||||||
|
->for($technicalApprover)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::AcceptedByTechnical,
|
||||||
|
"to" => VacationRequestState::WaitingForAdministrative,
|
||||||
|
])->for($vacationRequestApproved)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::WaitingForAdministrative,
|
||||||
|
"to" => VacationRequestState::AcceptedByAdministrative,
|
||||||
|
])->for($vacationRequestApproved)
|
||||||
|
->for($administrativeApprover)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::AcceptedByAdministrative,
|
||||||
|
"to" => VacationRequestState::Approved,
|
||||||
|
])->for($vacationRequestApproved)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$vacationRequestApproved->changeStateTo(VacationRequestState::Approved);
|
||||||
|
|
||||||
|
/** @var VacationRequest $vacationRequestWaitsForAdminApproval */
|
||||||
|
$vacationRequestWaitsForAdminApproval = VacationRequest::factory([
|
||||||
|
"type" => VacationType::Vacation->value,
|
||||||
|
"state" => VacationRequestState::Created,
|
||||||
|
"from" => Carbon::create($currentYearPeriod->year, 2, 14)->toDateString(),
|
||||||
|
"to" => Carbon::create($currentYearPeriod->year, 2, 14)->toDateString(),
|
||||||
|
"comment" => "Komentarz do wniosku urlopowego.",
|
||||||
|
])
|
||||||
|
->for($employee1)
|
||||||
|
->for($employee1, "creator")
|
||||||
|
->for($currentYearPeriod)
|
||||||
|
->afterCreating(function (VacationRequest $vacationRequest): void {
|
||||||
|
$days = app(VacationDaysCalculator::class)->calculateDays(
|
||||||
|
$vacationRequest->yearPeriod,
|
||||||
|
$vacationRequest->from,
|
||||||
|
$vacationRequest->to,
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($days as $day) {
|
||||||
|
$vacationRequest->vacations()->create([
|
||||||
|
"date" => $day,
|
||||||
|
"user_id" => $vacationRequest->user->id,
|
||||||
|
"year_period_id" => $vacationRequest->yearPeriod->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => null,
|
||||||
|
"to" => VacationRequestState::Created,
|
||||||
|
])->for($vacationRequestWaitsForAdminApproval)
|
||||||
|
->for($employee1)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::Created,
|
||||||
|
"to" => VacationRequestState::WaitingForTechnical,
|
||||||
|
])->for($vacationRequestWaitsForAdminApproval)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::WaitingForTechnical,
|
||||||
|
"to" => VacationRequestState::AcceptedByTechnical,
|
||||||
|
])->for($vacationRequestWaitsForAdminApproval)
|
||||||
|
->for($technicalApprover)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::AcceptedByTechnical,
|
||||||
|
"to" => VacationRequestState::WaitingForAdministrative,
|
||||||
|
])->for($vacationRequestWaitsForAdminApproval)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$vacationRequestWaitsForAdminApproval->changeStateTo(VacationRequestState::WaitingForAdministrative);
|
||||||
|
|
||||||
|
/** @var VacationRequest $vacationRequestRejected */
|
||||||
|
$vacationRequestRejected = VacationRequest::factory([
|
||||||
|
"type" => VacationType::Vacation->value,
|
||||||
|
"state" => VacationRequestState::Created,
|
||||||
|
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
||||||
|
"to" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
|
||||||
|
"comment" => "",
|
||||||
|
])
|
||||||
|
->for($employee1)
|
||||||
|
->for($employee1, "creator")
|
||||||
|
->for($currentYearPeriod)
|
||||||
|
->afterCreating(function (VacationRequest $vacationRequest): void {
|
||||||
|
$days = app(VacationDaysCalculator::class)->calculateDays(
|
||||||
|
$vacationRequest->yearPeriod,
|
||||||
|
$vacationRequest->from,
|
||||||
|
$vacationRequest->to,
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($days as $day) {
|
||||||
|
$vacationRequest->vacations()->create([
|
||||||
|
"date" => $day,
|
||||||
|
"user_id" => $vacationRequest->user->id,
|
||||||
|
"year_period_id" => $vacationRequest->yearPeriod->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => null,
|
||||||
|
"to" => VacationRequestState::Created,
|
||||||
|
])->for($vacationRequestRejected)
|
||||||
|
->for($employee1)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::Created,
|
||||||
|
"to" => VacationRequestState::WaitingForTechnical,
|
||||||
|
])->for($vacationRequestRejected)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
VacationRequestActivity::factory([
|
||||||
|
"from" => VacationRequestState::WaitingForTechnical,
|
||||||
|
"to" => VacationRequestState::Rejected,
|
||||||
|
])->for($vacationRequestRejected)
|
||||||
|
->for($technicalApprover)
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$vacationRequestRejected->changeStateTo(VacationRequestState::Rejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateAvatarsForUsers(Collection $users): void
|
||||||
|
{
|
||||||
|
foreach ($users as $user) {
|
||||||
|
$user->saveAvatar($this->avatarGenerator->generateFor($user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1992
package-lock.json
generated
1992
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@ -12,31 +12,32 @@
|
|||||||
"lintf": "./node_modules/.bin/eslint resources/js --ext .js,.vue --fix"
|
"lintf": "./node_modules/.bin/eslint resources/js --ext .js,.vue --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/vue": "^1.4.2",
|
"@headlessui/vue": "^1.5.0",
|
||||||
"@heroicons/vue": "^1.0.5",
|
"@heroicons/vue": "^1.0.5",
|
||||||
"@inertiajs/inertia": "^0.11.0",
|
"@inertiajs/inertia": "^0.11.0",
|
||||||
"@inertiajs/inertia-vue3": "^0.6.0",
|
"@inertiajs/inertia-vue3": "^0.6.0",
|
||||||
"@inertiajs/progress": "^0.2.7",
|
"@inertiajs/progress": "^0.2.7",
|
||||||
"@tailwindcss/forms": "^0.4.0",
|
"@tailwindcss/forms": "^0.4.0",
|
||||||
"@tailwindcss/line-clamp": "^0.3.1",
|
"@tailwindcss/line-clamp": "^0.3.1",
|
||||||
"@tailwindcss/typography": "^0.5.0",
|
"@tailwindcss/typography": "^0.5.2",
|
||||||
"@vue/compiler-sfc": "^3.2.26",
|
"@vue/compiler-sfc": "^3.2.31",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.26.0",
|
||||||
"echarts": "^5.2.2",
|
"echarts": "^5.3.0",
|
||||||
|
"eslit": "^6.0.0",
|
||||||
"flatpickr": "^4.6.9",
|
"flatpickr": "^4.6.9",
|
||||||
"laravel-mix": "^6.0.6",
|
"laravel-mix": "^6.0.43",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"postcss": "^8.4.5",
|
"postcss": "^8.4.7",
|
||||||
"tailwindcss": "^3.0.13",
|
"tailwindcss": "^3.0.23",
|
||||||
"vue": "^3.2.26",
|
"vue": "^3.2.31",
|
||||||
"vue-echarts": "^6.0.2",
|
"vue-echarts": "^6.0.2",
|
||||||
"vue-flatpickr-component": "^9.0.5",
|
"vue-flatpickr-component": "^9.0.5",
|
||||||
"vue-loader": "^17.0.0",
|
"vue-loader": "^17.0.0",
|
||||||
"vue-toastification": "^2.0.0-rc.5"
|
"vue-toastification": "^2.0.0-rc.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.6.0",
|
"eslint": "^8.10.0",
|
||||||
"eslint-plugin-vue": "^8.2.0"
|
"eslint-plugin-vue": "^8.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
: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"
|
||||||
>
|
>
|
||||||
Pobierz plik excel
|
Pobierz plik Excel
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,17 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<InertiaHead title="Strona główna" />
|
<InertiaHead title="Strona główna" />
|
||||||
<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">
|
||||||
<!-- Left column -->
|
|
||||||
<div class="grid grid-cols-1 gap-4 lg:col-span-2">
|
<div class="grid grid-cols-1 gap-4 lg:col-span-2">
|
||||||
<!-- Welcome panel -->
|
<section>
|
||||||
<section aria-labelledby="profile-overview-title">
|
<div class=" bg-white overflow-hidden shadow">
|
||||||
<div class="rounded-lg bg-white overflow-hidden shadow">
|
|
||||||
<h2
|
|
||||||
id="profile-overview-title"
|
|
||||||
class="sr-only"
|
|
||||||
>
|
|
||||||
Profile Overview
|
|
||||||
</h2>
|
|
||||||
<div class="bg-white p-6">
|
<div class="bg-white p-6">
|
||||||
<div class="sm:flex sm:items-center sm:justify-between">
|
<div class="sm:flex sm:items-center sm:justify-between">
|
||||||
<div class="sm:flex sm:space-x-5">
|
<div class="sm:flex sm:space-x-5">
|
||||||
@ -24,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-4 text-center sm:mt-0 sm:pt-1 sm:text-left">
|
<div class="mt-4 text-center sm:mt-0 sm:pt-1 sm:text-left">
|
||||||
<p class="text-sm font-medium text-gray-600">
|
<p class="text-sm font-medium text-gray-600">
|
||||||
Welcome back,
|
Cześć,
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xl font-bold text-gray-900 sm:text-2xl">
|
<p class="text-xl font-bold text-gray-900 sm:text-2xl">
|
||||||
{{ user.name }}
|
{{ user.name }}
|
||||||
@ -34,136 +26,109 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5 flex justify-center sm:mt-0">
|
|
||||||
<InertiaLink
|
|
||||||
href="#"
|
|
||||||
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"
|
|
||||||
>
|
|
||||||
View profile
|
|
||||||
</InertiaLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="border-t border-gray-200 bg-gray-50 grid grid-cols-1 divide-y divide-gray-200 sm:grid-cols-3 sm:divide-y-0 sm:divide-x"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="stat in stats"
|
|
||||||
:key="stat.label"
|
|
||||||
class="px-6 py-5 text-sm font-medium text-center"
|
|
||||||
>
|
|
||||||
<span class="text-gray-900">{{ stat.value }}</span>
|
|
||||||
{{ ' ' }}
|
|
||||||
<span class="text-gray-600">{{ stat.label }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section>
|
||||||
<!-- Actions panel -->
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<section aria-labelledby="quick-links-title">
|
<div class="bg-white shadow-md p-4">
|
||||||
<div
|
<VacationChart :stats="stats" />
|
||||||
class="rounded-lg bg-gray-200 overflow-hidden shadow divide-y divide-gray-200 sm:divide-y-0 sm:grid sm:grid-cols-2 sm:gap-px"
|
</div>
|
||||||
>
|
<div class="h-full">
|
||||||
<h2
|
<div class="grid grid-cols-2 gap-4 h-full">
|
||||||
id="quick-links-title"
|
<div class="px-4 py-5 bg-white shadow-md sm:p-6">
|
||||||
class="sr-only"
|
<dd class="mt-1 text-4xl font-semibold text-blumilk-500">
|
||||||
>
|
{{ stats.remaining }}
|
||||||
Quick links
|
</dd>
|
||||||
</h2>
|
<dt class="text-md font-medium text-gray-700 truncate">
|
||||||
<div
|
Pozostało
|
||||||
v-for="(action, actionIdx) in actions"
|
</dt>
|
||||||
:key="action.name"
|
<dt class="text-sm font-medium text-gray-500 mt-2">
|
||||||
:class="[actionIdx === 0 ? 'rounded-tl-lg rounded-tr-lg sm:rounded-tr-none' : '', actionIdx === 1 ? 'sm:rounded-tr-lg' : '', actionIdx === actions.length - 2 ? 'sm:rounded-bl-lg' : '', actionIdx === actions.length - 1 ? 'rounded-bl-lg rounded-br-lg sm:rounded-bl-none' : '', 'relative group bg-white p-6 focus-within:ring-2 focus-within:ring-inset focus-within:ring-cyan-500']"
|
Dni do wykorzystania teraz.
|
||||||
>
|
</dt>
|
||||||
<div>
|
</div>
|
||||||
<span
|
<div class="px-4 py-5 bg-white shadow-md sm:p-6">
|
||||||
:class="[action.iconBackground, action.iconForeground, 'rounded-lg inline-flex p-3 ring-4 ring-white']"
|
<dd class="mt-1 text-4xl font-semibold text-blumilk-700">
|
||||||
>
|
{{ stats.used }}
|
||||||
<component
|
</dd>
|
||||||
:is="action.icon"
|
<dt class="text-md font-medium text-gray-700 truncate">
|
||||||
class="h-6 w-6"
|
Dni wykorzystane
|
||||||
aria-hidden="true"
|
</dt>
|
||||||
/>
|
<dt class="text-sm font-medium text-gray-500 mt-2">
|
||||||
</span>
|
Dni, które zostały już wykorzystane na urlop wypoczynkowy.
|
||||||
|
</dt>
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-5 bg-white shadow-md sm:p-6">
|
||||||
|
<dt class="mt-1 text-4xl font-semibold text-blumilk-200">
|
||||||
|
{{ stats.pending }}
|
||||||
|
</dt>
|
||||||
|
<dd class="text-md font-medium text-gray-500 truncate">
|
||||||
|
Rozpatrywane
|
||||||
|
</dd>
|
||||||
|
<dt class="text-sm font-medium text-gray-500 mt-2">
|
||||||
|
Dni czekające na akceptację przełożonych.
|
||||||
|
</dt>
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-5 bg-white shadow-md sm:p-6">
|
||||||
|
<dt class="mt-1 text-4xl font-semibold text-gray-900">
|
||||||
|
{{ stats.limit }}
|
||||||
|
</dt>
|
||||||
|
<dd class="text-md font-medium text-gray-500 truncate">
|
||||||
|
Limit urlopu
|
||||||
|
</dd>
|
||||||
|
<dt class="text-sm font-medium text-gray-500 mt-2">
|
||||||
|
Twój roczny limit urlopu wypoczynkowego.
|
||||||
|
</dt>
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-5 bg-white shadow-md sm:p-6 col-span-2">
|
||||||
|
<dt class="mt-1 text-4xl font-semibold text-gray-900">
|
||||||
|
{{ stats.other }}
|
||||||
|
</dt>
|
||||||
|
<dd class="text-md font-medium text-gray-500 truncate">
|
||||||
|
Inne urlopy
|
||||||
|
</dd>
|
||||||
|
<dt class="text-sm font-medium text-gray-500 mt-2">
|
||||||
|
Urlopy bezpłatne, okolicznościowe, zwolnienia lekarskie, itd., które zostały już zatwierdzone.
|
||||||
|
</dt>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-8">
|
|
||||||
<h3 class="text-lg font-medium">
|
|
||||||
<InertiaLink
|
|
||||||
:href="action.href"
|
|
||||||
class="focus:outline-none"
|
|
||||||
>
|
|
||||||
<!-- Extend touch target to entire panel -->
|
|
||||||
<span
|
|
||||||
class="absolute inset-0"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
{{ action.name }}
|
|
||||||
</InertiaLink>
|
|
||||||
</h3>
|
|
||||||
<p class="mt-2 text-sm text-gray-500">
|
|
||||||
Doloribus dolores nostrum quia qui natus officia quod et dolorem. Sit
|
|
||||||
repellendus qui ut at blanditiis et quo et molestiae.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
class="pointer-events-none absolute top-6 right-6 text-gray-300 group-hover:text-gray-400"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="h-6 w-6"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M20 4h1a1 1 0 00-1-1v1zm-1 12a1 1 0 102 0h-2zM8 3a1 1 0 000 2V3zM3.293 19.293a1 1 0 101.414 1.414l-1.414-1.414zM19 4v12h2V4h-2zm1-1H8v2h12V3zm-.707.293l-16 16 1.414 1.414 16-16-1.414-1.414z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right column -->
|
|
||||||
<div class="grid grid-cols-1 gap-4">
|
<div class="grid grid-cols-1 gap-4">
|
||||||
<!-- Announcements -->
|
<section>
|
||||||
<section aria-labelledby="announcements-title">
|
<div class="bg-white shadow-md">
|
||||||
<div class="rounded-lg bg-white overflow-hidden shadow">
|
<div class="p-4 sm:px-6">
|
||||||
<div class="p-6">
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
<h2
|
Twoje wnioski
|
||||||
id="announcements-title"
|
|
||||||
class="text-base font-medium text-gray-900"
|
|
||||||
>
|
|
||||||
Announcements
|
|
||||||
</h2>
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="border-t border-gray-200 pb-5 px-4 sm:px-6">
|
||||||
<div class="flow-root mt-6">
|
<div class="flow-root mt-6">
|
||||||
<ul
|
<ul class="-my-5 divide-y divide-gray-200">
|
||||||
role="list"
|
|
||||||
class="-my-5 divide-y divide-gray-200"
|
|
||||||
>
|
|
||||||
<li
|
<li
|
||||||
v-for="announcement in announcements"
|
v-for="request in vacationRequests.data"
|
||||||
:key="announcement.id"
|
:key="request.id"
|
||||||
class="py-5"
|
class="py-5"
|
||||||
>
|
>
|
||||||
<div class="relative focus-within:ring-2 focus-within:ring-cyan-500">
|
<div class="relative focus-within:ring-2 focus-within:ring-cyan-500">
|
||||||
<h3 class="text-sm font-semibold text-gray-800">
|
<h3 class="text-sm font-semibold text-blumilk-600 hover:text-blumilk-500">
|
||||||
<InertiaLink
|
<InertiaLink
|
||||||
:href="announcement.href"
|
:href="`/vacation-requests/${request.id}`"
|
||||||
class="hover:underline focus:outline-none"
|
class="hover:underline focus:outline-none"
|
||||||
>
|
>
|
||||||
<!-- Extend touch target to entire panel -->
|
<span class="absolute inset-0" />
|
||||||
<span
|
Wniosek o {{ request.type.toLowerCase() }}
|
||||||
class="absolute inset-0"
|
[{{ request.name }}]
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
{{ announcement.title }}
|
|
||||||
</InertiaLink>
|
</InertiaLink>
|
||||||
</h3>
|
</h3>
|
||||||
<p class="mt-1 text-sm text-gray-600 line-clamp-2">
|
<p class="mt-1 text-sm text-gray-600">
|
||||||
{{ announcement.preview }}
|
{{ request.from }} - {{ request.to }}
|
||||||
|
</p>
|
||||||
|
<p class="mt-2 text-sm text-gray-600">
|
||||||
|
<Status :status="request.state" />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -171,71 +136,84 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<InertiaLink
|
<InertiaLink
|
||||||
href="#"
|
href="/vacation-requests"
|
||||||
class="w-full flex justify-center items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"
|
class="w-full flex justify-center items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"
|
||||||
>
|
>
|
||||||
View all
|
Zobacz wszystkie
|
||||||
</InertiaLink>
|
</InertiaLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section>
|
||||||
<!-- Recent Hires -->
|
<div class="bg-white shadow-md">
|
||||||
<section aria-labelledby="recent-hires-title">
|
<div class="p-4 sm:px-6">
|
||||||
<div class="rounded-lg bg-white overflow-hidden shadow">
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
<div class="p-6">
|
Dzisiejsze nieobecności
|
||||||
<h2
|
|
||||||
id="recent-hires-title"
|
|
||||||
class="text-base font-medium text-gray-900"
|
|
||||||
>
|
|
||||||
Recent Hires
|
|
||||||
</h2>
|
</h2>
|
||||||
<div class="flow-root mt-6">
|
</div>
|
||||||
<ul
|
<div class="border-t border-gray-200 px-4 sm:px-6">
|
||||||
role="list"
|
<ul class="divide-y divide-gray-200">
|
||||||
class="-my-5 divide-y divide-gray-200"
|
<li
|
||||||
|
v-for="absence in absences.data"
|
||||||
|
:key="absence.user.id"
|
||||||
|
class="py-4 flex"
|
||||||
>
|
>
|
||||||
<li
|
<img
|
||||||
v-for="person in recentHires"
|
class="h-10 w-10 rounded-full"
|
||||||
:key="person.handle"
|
:src="absence.user.avatar"
|
||||||
class="py-4"
|
|
||||||
>
|
>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="ml-3">
|
||||||
<div class="flex-shrink-0">
|
<p class="text-sm font-medium text-gray-900">
|
||||||
<img
|
{{ absence.user.name }}
|
||||||
class="h-8 w-8 rounded-full"
|
</p>
|
||||||
:src="person.imageUrl"
|
<p class="text-sm text-gray-500">
|
||||||
alt=""
|
{{ absence.user.email }}
|
||||||
>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 min-w-0">
|
</li>
|
||||||
<p class="text-sm font-medium text-gray-900 truncate">
|
<li v-if="! absences.data.length">
|
||||||
{{ person.name }}
|
<p class="py-2">
|
||||||
</p>
|
Brak danych
|
||||||
<p class="text-sm text-gray-500 truncate">
|
</p>
|
||||||
{{ '@' + person.handle }}
|
</li>
|
||||||
</p>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
</div>
|
||||||
<InertiaLink
|
</section>
|
||||||
:href="person.href"
|
<section>
|
||||||
class="inline-flex items-center shadow-sm px-2.5 py-0.5 border border-gray-300 text-sm leading-5 font-medium rounded-full text-gray-700 bg-white hover:bg-gray-50"
|
<div class="bg-white shadow-md">
|
||||||
>
|
<div>
|
||||||
View
|
<div class="p-4 sm:px-6">
|
||||||
</InertiaLink>
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
</div>
|
Najbliższe dni wolne
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="border-t border-gray-200 px-4 pb-5 sm:px-6">
|
||||||
|
<ul class="divide-y divide-gray-200">
|
||||||
|
<li
|
||||||
|
v-for="holiday in holidays.data"
|
||||||
|
:key="holiday.id.id"
|
||||||
|
class="py-4 flex"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-medium text-gray-900">
|
||||||
|
{{ holiday.name }}
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{{ holiday.displayDate }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
<div>
|
||||||
<div class="mt-6">
|
<InertiaLink
|
||||||
<InertiaLink
|
href="/holidays"
|
||||||
href="#"
|
class="w-full flex justify-center items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"
|
||||||
class="w-full flex justify-center items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"
|
>
|
||||||
>
|
Zobacz wszystkie
|
||||||
View all
|
</InertiaLink>
|
||||||
</InertiaLink>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -245,129 +223,41 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
|
||||||
AcademicCapIcon,
|
|
||||||
BadgeCheckIcon,
|
|
||||||
CashIcon,
|
|
||||||
ClockIcon,
|
|
||||||
ReceiptRefundIcon,
|
|
||||||
UsersIcon,
|
|
||||||
} from '@heroicons/vue/outline'
|
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
import {usePage} from '@inertiajs/inertia-vue3'
|
import {usePage} from '@inertiajs/inertia-vue3'
|
||||||
|
import Status from '@/Shared/Status'
|
||||||
|
import VacationChart from '@/Shared/VacationChart'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DashboardPage',
|
name: 'DashboardPage',
|
||||||
|
components: {Status, VacationChart},
|
||||||
|
props: {
|
||||||
|
absences: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
vacationRequests: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
holidays: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
stats: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
used: 0,
|
||||||
|
pending: 0,
|
||||||
|
remaining: 0,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const user = computed(() => usePage().props.value.auth.user)
|
const user = computed(() => usePage().props.value.auth.user)
|
||||||
const stats = [
|
|
||||||
{label: 'Vacation days left', value: 12},
|
|
||||||
{label: 'Sick days left', value: 4},
|
|
||||||
{label: 'Personal days left', value: 2},
|
|
||||||
]
|
|
||||||
const actions = [
|
|
||||||
{
|
|
||||||
icon: ClockIcon,
|
|
||||||
name: 'Request time off',
|
|
||||||
href: '#',
|
|
||||||
iconForeground: 'text-teal-700',
|
|
||||||
iconBackground: 'bg-teal-50',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: BadgeCheckIcon,
|
|
||||||
name: 'Benefits',
|
|
||||||
href: '#',
|
|
||||||
iconForeground: 'text-purple-700',
|
|
||||||
iconBackground: 'bg-purple-50',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: UsersIcon,
|
|
||||||
name: 'Schedule a one-on-one',
|
|
||||||
href: '#',
|
|
||||||
iconForeground: 'text-sky-700',
|
|
||||||
iconBackground: 'bg-sky-50',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: CashIcon,
|
|
||||||
name: 'Payroll',
|
|
||||||
href: '#',
|
|
||||||
iconForeground: 'text-yellow-700',
|
|
||||||
iconBackground: 'bg-yellow-50',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: ReceiptRefundIcon,
|
|
||||||
name: 'Submit an expense',
|
|
||||||
href: '#',
|
|
||||||
iconForeground: 'text-rose-700',
|
|
||||||
iconBackground: 'bg-rose-50',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: AcademicCapIcon,
|
|
||||||
name: 'Training',
|
|
||||||
href: '#',
|
|
||||||
iconForeground: 'text-indigo-700',
|
|
||||||
iconBackground: 'bg-indigo-50',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const recentHires = [
|
|
||||||
{
|
|
||||||
name: 'Leonard Krasner',
|
|
||||||
handle: 'leonardkrasner',
|
|
||||||
imageUrl:
|
|
||||||
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Floyd Miles',
|
|
||||||
handle: 'floydmiles',
|
|
||||||
imageUrl:
|
|
||||||
'https://images.unsplash.com/photo-1463453091185-61582044d556?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Emily Selman',
|
|
||||||
handle: 'emilyselman',
|
|
||||||
imageUrl:
|
|
||||||
'https://images.unsplash.com/photo-1502685104226-ee32379fefbe?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Kristin Watson',
|
|
||||||
handle: 'kristinwatson',
|
|
||||||
imageUrl:
|
|
||||||
'https://images.unsplash.com/photo-1500917293891-ef795e70e1f6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
||||||
href: '#',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
const announcements = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'Office closed on July 2nd',
|
|
||||||
href: '#',
|
|
||||||
preview:
|
|
||||||
'Cum qui rem deleniti. Suscipit in dolor veritatis sequi aut. Vero ut earum quis deleniti. Ut a sunt eum cum ut repudiandae possimus. Nihil ex tempora neque cum consectetur dolores.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: 'New password policy',
|
|
||||||
href: '#',
|
|
||||||
preview:
|
|
||||||
'Alias inventore ut autem optio voluptas et repellendus. Facere totam quaerat quam quo laudantium cumque eaque excepturi vel. Accusamus maxime ipsam reprehenderit rerum id repellendus rerum. Culpa cum vel natus. Est sit autem mollitia.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: 'Office closed on July 2nd',
|
|
||||||
href: '#',
|
|
||||||
preview:
|
|
||||||
'Tenetur libero voluptatem rerum occaecati qui est molestiae exercitationem. Voluptate quisquam iure assumenda consequatur ex et recusandae. Alias consectetur voluptatibus. Accusamus a ab dicta et. Consequatur quis dignissimos voluptatem nisi.',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
stats,
|
|
||||||
actions,
|
|
||||||
recentHires,
|
|
||||||
announcements,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -11,119 +11,128 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-200">
|
<div class="overflow-x-auto xl:overflow-x-visible overflow-y-auto xl:overflow-y-visible">
|
||||||
<div class="overflow-x-auto xl:overflow-x-visible overflow-y-auto xl:overflow-y-visible">
|
<form @submit.prevent="submitVacationDays">
|
||||||
<form @submit.prevent="submitVacationDays">
|
<table class="min-w-full divide-y divide-gray-200">
|
||||||
<table class="min-w-full divide-y divide-gray-200">
|
<thead class="bg-gray-50">
|
||||||
<thead class="bg-gray-50">
|
<tr>
|
||||||
<tr>
|
<th
|
||||||
<th
|
scope="col"
|
||||||
scope="col"
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
Imię i nazwisko
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
Forma zatrudnienia
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
Posiada urlop?
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
Dostępne dni w roku
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="bg-white divide-y divide-gray-100">
|
|
||||||
<tr
|
|
||||||
v-for="(item, index) in form.items"
|
|
||||||
:key="item.id"
|
|
||||||
class="hover:bg-blumilk-25"
|
|
||||||
>
|
>
|
||||||
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
Imię i nazwisko
|
||||||
<div class="flex">
|
</th>
|
||||||
<span
|
<th
|
||||||
class="inline-flex items-center justify-center h-10 w-10 rounded-full"
|
scope="col"
|
||||||
>
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
<img
|
>
|
||||||
class="h-10 w-10 rounded-full"
|
Forma zatrudnienia
|
||||||
:src="item.user.avatar"
|
</th>
|
||||||
alt=""
|
<th
|
||||||
>
|
scope="col"
|
||||||
</span>
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
<div class="ml-3">
|
>
|
||||||
<p class="text-sm font-medium break-all text-gray-900">
|
Posiada urlop?
|
||||||
{{ item.user.name }}
|
</th>
|
||||||
</p>
|
<th
|
||||||
<p class="text-sm break-all text-gray-500">
|
scope="col"
|
||||||
{{ item.user.email }}
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
</p>
|
>
|
||||||
</div>
|
Pozostałe dni z poprzedniego roku
|
||||||
</div>
|
</th>
|
||||||
</td>
|
<th
|
||||||
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
scope="col"
|
||||||
{{ item.user.employmentForm }}
|
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider"
|
||||||
</td>
|
>
|
||||||
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
Dostępne dni w roku
|
||||||
<Switch
|
</th>
|
||||||
v-model="item.hasVacation"
|
</tr>
|
||||||
:class="[item.hasVacation ? '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']"
|
</thead>
|
||||||
|
<tbody class="bg-white divide-y divide-gray-100">
|
||||||
|
<tr
|
||||||
|
v-for="(item, index) in form.items"
|
||||||
|
:key="item.id"
|
||||||
|
class="hover:bg-blumilk-25"
|
||||||
|
>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
|
<div class="flex">
|
||||||
|
<span
|
||||||
|
class="inline-flex items-center justify-center h-10 w-10 rounded-full"
|
||||||
>
|
>
|
||||||
<span
|
<img
|
||||||
:class="[item.hasVacation ? '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']"
|
class="h-10 w-10 rounded-full"
|
||||||
/>
|
:src="item.user.avatar"
|
||||||
</Switch>
|
alt=""
|
||||||
</td>
|
|
||||||
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
||||||
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
|
||||||
<input
|
|
||||||
v-model="item.days"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
class="block w-full shadow-sm rounded-md sm:text-sm disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none disabled:cursor-not-allowed"
|
|
||||||
:disabled="!item.hasVacation"
|
|
||||||
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`items.${index}.days`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`items.${index}.days`] }"
|
|
||||||
>
|
>
|
||||||
<p
|
</span>
|
||||||
v-if="form.errors[`items.${index}.days`]"
|
<div class="ml-3">
|
||||||
class="mt-2 text-sm text-red-600"
|
<p class="text-sm font-medium break-all text-gray-900">
|
||||||
>
|
{{ item.user.name }}
|
||||||
{{ form.errors[`items.${index}.days`] }}
|
</p>
|
||||||
|
<p class="text-sm break-all text-gray-500">
|
||||||
|
{{ item.user.email }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
</td>
|
||||||
<tr
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
v-if="!form.items.length"
|
{{ item.user.employmentForm }}
|
||||||
>
|
</td>
|
||||||
<td
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
colspan="100%"
|
<Switch
|
||||||
class="text-center py-4 text-xl leading-5 text-gray-700"
|
v-model="item.hasVacation"
|
||||||
|
:class="[item.hasVacation ? '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']"
|
||||||
>
|
>
|
||||||
Brak danych
|
<span
|
||||||
</td>
|
:class="[item.hasVacation ? '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']"
|
||||||
</tr>
|
/>
|
||||||
</tbody>
|
</Switch>
|
||||||
</table>
|
</td>
|
||||||
<div class="flex justify-end py-3 px-4">
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
<button
|
<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">
|
||||||
type="submit"
|
{{ item.remainingLastYear }}
|
||||||
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"
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<input
|
||||||
|
v-model="item.days"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
class="block w-full shadow-sm rounded-md sm:text-sm disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none disabled:cursor-not-allowed"
|
||||||
|
:disabled="!item.hasVacation"
|
||||||
|
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`items.${index}.days`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`items.${index}.days`] }"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
v-if="form.errors[`items.${index}.days`]"
|
||||||
|
class="mt-2 text-sm text-red-600"
|
||||||
|
>
|
||||||
|
{{ form.errors[`items.${index}.days`] }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr
|
||||||
|
v-if="!form.items.length"
|
||||||
>
|
>
|
||||||
Zapisz
|
<td
|
||||||
</button>
|
colspan="100%"
|
||||||
</div>
|
class="text-center py-4 text-xl leading-5 text-gray-700"
|
||||||
</form>
|
>
|
||||||
</div>
|
Brak danych
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="flex justify-end py-3 px-4">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
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>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -149,7 +158,7 @@ export default {
|
|||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
items: props.limits.data,
|
items: props.limits,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,277 +1,324 @@
|
|||||||
<template>
|
<template>
|
||||||
<InertiaHead title="Złóż wniosek urlopowy" />
|
<InertiaHead title="Złóż wniosek urlopowy" />
|
||||||
<div class="bg-white shadow-md">
|
<div class="grid grid-cols-1 gap-4 items-start lg:grid-cols-3 lg:gap-8">
|
||||||
<div class="p-4 sm:px-6">
|
<div class="lg:col-span-2 h-full bg-white shadow-md flex flex-col">
|
||||||
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
<div class="p-4 sm:px-6">
|
||||||
Złóż wniosek urlopowy
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
</h2>
|
Złóż wniosek urlopowy
|
||||||
</div>
|
</h2>
|
||||||
<form
|
</div>
|
||||||
class="border-t border-gray-200 px-6"
|
<form
|
||||||
@submit.prevent="createForm"
|
class="border-t border-gray-200 h-full px-6"
|
||||||
>
|
@submit.prevent="createForm"
|
||||||
<div
|
|
||||||
v-if="form.errors.vacationRequest"
|
|
||||||
class="rounded-md bg-red-50 p-4 mt-2"
|
|
||||||
>
|
>
|
||||||
<div class="flex">
|
<div class="h-full flex flex-col justify-around">
|
||||||
<div class="flex-shrink-0">
|
<div>
|
||||||
<XCircleIcon class="h-5 w-5 text-red-400" />
|
<div
|
||||||
|
v-if="form.errors.vacationRequest"
|
||||||
|
class="rounded-md bg-red-50 p-4 mt-2"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
<Listbox
|
||||||
|
v-if="can.createOnBehalfOfEmployee"
|
||||||
|
v-model="form.user"
|
||||||
|
as="div"
|
||||||
|
class="sm:grid sm:grid-cols-3 py-4 items-center"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
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"
|
||||||
|
>
|
||||||
|
Osoba składająca wniosek
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 sm:mt-0 sm:col-span-2">
|
||||||
|
<div class="flex justify-start items-center">
|
||||||
|
<span class="inline-flex items-center justify-center h-10 w-10 rounded-full">
|
||||||
|
<img
|
||||||
|
class="h-10 w-10 rounded-full"
|
||||||
|
:src="auth.user.avatar"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<div class="ml-3">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{{ auth.user.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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 class="ml-3">
|
<div class="flex justify-end py-3">
|
||||||
<h3 class="text-sm font-medium text-red-800">
|
<div class="space-x-3">
|
||||||
Wniosek nie mógł zostać utworzony
|
<InertiaLink
|
||||||
</h3>
|
href="/vacation-requests"
|
||||||
<div class="mt-2 text-sm text-red-700">
|
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"
|
||||||
<span>{{ form.errors.vacationRequest }}</span>
|
>
|
||||||
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="bg-white shadow-md h-full">
|
||||||
|
<div class="p-4 sm:px-6">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
<span v-if="auth.user.id !== form.user.id">
|
||||||
|
Urlop wypoczynkowy, dane dla: {{ form.user.name }}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
Twoje dane o urlopie wypoczynkowym
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<Listbox
|
<div class="border-t border-gray-200 px-6 pt-8">
|
||||||
v-if="can.createOnBehalfOfEmployee"
|
<VacationChart :stats="stats" />
|
||||||
v-model="form.user"
|
|
||||||
as="div"
|
|
||||||
class="sm:grid sm:grid-cols-3 py-4 items-center"
|
|
||||||
>
|
|
||||||
<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>
|
||||||
<div class="sm:grid sm:grid-cols-3 py-4 items-center">
|
</div>
|
||||||
<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 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>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -280,13 +327,15 @@ import {useForm} from '@inertiajs/inertia-vue3'
|
|||||||
import FlatPickr from 'vue-flatpickr-component'
|
import FlatPickr from 'vue-flatpickr-component'
|
||||||
import {Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions, Switch} from '@headlessui/vue'
|
import {Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions, Switch} from '@headlessui/vue'
|
||||||
import {CheckIcon, SelectorIcon, XCircleIcon} from '@heroicons/vue/solid'
|
import {CheckIcon, SelectorIcon, XCircleIcon} from '@heroicons/vue/solid'
|
||||||
import {reactive, ref} from 'vue'
|
import {reactive, ref, watch} from 'vue'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import useCurrentYearPeriodInfo from '@/Composables/yearPeriodInfo'
|
import useCurrentYearPeriodInfo from '@/Composables/yearPeriodInfo'
|
||||||
|
import VacationChart from '@/Shared/VacationChart'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'VacationRequestCreate',
|
name: 'VacationRequestCreate',
|
||||||
components: {
|
components: {
|
||||||
|
VacationChart,
|
||||||
Switch,
|
Switch,
|
||||||
FlatPickr,
|
FlatPickr,
|
||||||
Listbox,
|
Listbox,
|
||||||
@ -333,6 +382,13 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const estimatedDays = ref([])
|
const estimatedDays = ref([])
|
||||||
|
|
||||||
|
const stats = ref({
|
||||||
|
used: 0,
|
||||||
|
pending: 0,
|
||||||
|
remaining: 0,
|
||||||
|
})
|
||||||
|
|
||||||
const {minDate, maxDate} = useCurrentYearPeriodInfo()
|
const {minDate, maxDate} = useCurrentYearPeriodInfo()
|
||||||
|
|
||||||
const disableDates = [
|
const disableDates = [
|
||||||
@ -351,9 +407,15 @@ export default {
|
|||||||
disable: disableDates,
|
disable: disableDates,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(() => form.user, user => {
|
||||||
|
axios.post('/api/calculate-vacations-stats', {user: user.id})
|
||||||
|
.then(res => stats.value = res.data)
|
||||||
|
}, {immediate: true})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
estimatedDays,
|
estimatedDays,
|
||||||
|
stats,
|
||||||
fromInputConfig,
|
fromInputConfig,
|
||||||
toInputConfig,
|
toInputConfig,
|
||||||
}
|
}
|
||||||
@ -383,6 +445,5 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="min-h-full">
|
<div class="min-h-full">
|
||||||
<MainMenu />
|
<MainMenu />
|
||||||
<main class="lg:ml-64 flex flex-col flex-1 py-8">
|
<main class="lg:ml-64 flex flex-col flex-1 py-8">
|
||||||
<div>
|
<div class="px-4">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
@ -110,7 +110,7 @@
|
|||||||
:class="[$page.url === '/' ? 'bg-blumilk-800 text-white' : 'text-blumilk-100 hover:text-white hover:bg-blumilk-600', 'group flex items-center px-2 py-2 text-sm leading-6 font-medium rounded-md']"
|
:class="[$page.url === '/' ? 'bg-blumilk-800 text-white' : 'text-blumilk-100 hover:text-white hover:bg-blumilk-600', 'group flex items-center px-2 py-2 text-sm leading-6 font-medium rounded-md']"
|
||||||
>
|
>
|
||||||
<HomeIcon class="mr-4 flex-shrink-0 h-6 w-6 text-blumilk-200" />
|
<HomeIcon class="mr-4 flex-shrink-0 h-6 w-6 text-blumilk-200" />
|
||||||
Dashboard
|
Strona główna
|
||||||
</InertiaLink>
|
</InertiaLink>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4 pt-4">
|
<div class="mt-4 pt-4">
|
||||||
@ -337,8 +337,6 @@ export default {
|
|||||||
].filter(item => item.can))
|
].filter(item => item.can))
|
||||||
|
|
||||||
const userNavigation = [
|
const userNavigation = [
|
||||||
{name: 'Your Profile', href: '#'},
|
|
||||||
{name: 'Settings', href: '#'},
|
|
||||||
{name: 'Wyloguj się', href: '/logout', method: 'post', as: 'button'},
|
{name: 'Wyloguj się', href: '/logout', method: 'post', as: 'button'},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
93
resources/js/Shared/VacationChart.vue
Normal file
93
resources/js/Shared/VacationChart.vue
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<v-chart
|
||||||
|
style="height: 600px;"
|
||||||
|
:autoresize="true"
|
||||||
|
:option="option"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { use } from 'echarts/core'
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers'
|
||||||
|
import { PieChart } from 'echarts/charts'
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
} from 'echarts/components'
|
||||||
|
import VChart from 'vue-echarts'
|
||||||
|
import {computed} from 'vue'
|
||||||
|
|
||||||
|
use([
|
||||||
|
CanvasRenderer,
|
||||||
|
PieChart,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
])
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'VacationChart',
|
||||||
|
components: {
|
||||||
|
VChart,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
stats: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
used: 0,
|
||||||
|
pending: 0,
|
||||||
|
remaining: 0,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const option = computed(() => ({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{a} <br/>{b} : {c} ({d}%)',
|
||||||
|
},
|
||||||
|
color: [
|
||||||
|
'#2C466F',
|
||||||
|
'#AABDDD',
|
||||||
|
'#527ABA',
|
||||||
|
],
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left',
|
||||||
|
data: ['Wykorzystane', 'Rozpatrywane', 'Pozostałe'],
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Urlop wypoczynkowy',
|
||||||
|
type: 'pie',
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 2,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'inner',
|
||||||
|
formatter: param => param.value !== 0 ? param.value : '' ,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#FFFFFF',
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: props.stats.used, name: 'Wykorzystane' },
|
||||||
|
{ value: props.stats.pending, name: 'Rozpatrywane' },
|
||||||
|
{ value: props.stats.remaining, name: 'Pozostałe' },
|
||||||
|
],
|
||||||
|
radius: ['30%', '70%'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
|
||||||
|
return { option }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
@ -3,8 +3,10 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Toby\Infrastructure\Http\Controllers\Api\CalculateUserVacationStatsController;
|
||||||
use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController;
|
use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController;
|
||||||
|
|
||||||
Route::middleware("auth:sanctum")->group(function (): void {
|
Route::middleware("auth:sanctum")->group(function (): void {
|
||||||
Route::post("calculate-vacation-days", CalculateVacationDaysController::class);
|
Route::post("calculate-vacation-days", CalculateVacationDaysController::class);
|
||||||
|
Route::post("calculate-vacations-stats", CalculateUserVacationStatsController::class);
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Toby\Infrastructure\Http\Controllers\DashboardController;
|
||||||
use Toby\Infrastructure\Http\Controllers\GoogleController;
|
use Toby\Infrastructure\Http\Controllers\GoogleController;
|
||||||
use Toby\Infrastructure\Http\Controllers\HolidayController;
|
use Toby\Infrastructure\Http\Controllers\HolidayController;
|
||||||
use Toby\Infrastructure\Http\Controllers\LogoutController;
|
use Toby\Infrastructure\Http\Controllers\LogoutController;
|
||||||
@ -14,7 +15,7 @@ use Toby\Infrastructure\Http\Controllers\VacationLimitController;
|
|||||||
use Toby\Infrastructure\Http\Controllers\VacationRequestController;
|
use Toby\Infrastructure\Http\Controllers\VacationRequestController;
|
||||||
|
|
||||||
Route::middleware("auth")->group(function (): void {
|
Route::middleware("auth")->group(function (): void {
|
||||||
Route::get("/", fn() => inertia("Dashboard"))
|
Route::get("/", DashboardController::class)
|
||||||
->name("dashboard");
|
->name("dashboard");
|
||||||
Route::post("/logout", LogoutController::class);
|
Route::post("/logout", LogoutController::class);
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class VacationLimitTest extends FeatureTestCase
|
|||||||
->assertInertia(
|
->assertInertia(
|
||||||
fn(Assert $page) => $page
|
fn(Assert $page) => $page
|
||||||
->component("VacationLimits")
|
->component("VacationLimits")
|
||||||
->has("limits.data", 10),
|
->has("limits", 10),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user