-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8024176
commit 86f02dd
Showing
7 changed files
with
310 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
app/Infrastructure/Http/Controllers/EmployeesMilestonesController.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Toby\Infrastructure\Http\Controllers; | ||
|
||
use Illuminate\Http\Request; | ||
use Inertia\Response; | ||
use Toby\Eloquent\Models\User; | ||
use Toby\Infrastructure\Http\Resources\EmployeeMilestoneResource; | ||
|
||
class EmployeesMilestonesController extends Controller | ||
{ | ||
public function index(Request $request): Response | ||
{ | ||
$searchText = $request->query("search"); | ||
$sort = $request->query("sort"); | ||
|
||
$users = User::query() | ||
->sortForEmployeesMilestones($sort) | ||
->search($searchText) | ||
->orderByProfileField("last_name") | ||
->orderByProfileField("first_name") | ||
->paginate() | ||
->withQueryString(); | ||
|
||
return inertia("EmployeesMilestones", [ | ||
"users" => EmployeeMilestoneResource::collection($users), | ||
"filters" => [ | ||
"search" => $searchText, | ||
], | ||
]); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
app/Infrastructure/Http/Resources/EmployeeMilestoneResource.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Toby\Infrastructure\Http\Resources; | ||
|
||
use Carbon\CarbonInterface; | ||
use Illuminate\Http\Resources\Json\JsonResource; | ||
use Illuminate\Support\Carbon; | ||
|
||
class EmployeeMilestoneResource extends JsonResource | ||
{ | ||
public static $wrap = null; | ||
|
||
public function toArray($request): array | ||
{ | ||
$upcomingBirthday = $this->upcomingBirthday(); | ||
$seniority = $this->seniority(); | ||
|
||
return [ | ||
"user" => new SimpleUserResource($this->resource), | ||
"birthdayDisplayDate" => $upcomingBirthday?->toDisplayString(), | ||
"birthdayRelativeDate" => $upcomingBirthday?->isToday() | ||
? __("today") | ||
: $upcomingBirthday?->diffForHumans( | ||
Carbon::today(), | ||
["options" => CarbonInterface::ONE_DAY_WORDS, "syntax" => CarbonInterface::DIFF_RELATIVE_TO_NOW], | ||
), | ||
"seniorityDisplayDate" => $seniority, | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
<script setup> | ||
import Pagination from '@/Shared/Pagination.vue' | ||
import EmptyState from '@/Shared/Feedbacks/EmptyState.vue' | ||
import { MagnifyingGlassIcon, ChevronDownIcon } from '@heroicons/vue/24/outline' | ||
import { reactive, watch } from 'vue' | ||
import { debounce } from 'lodash' | ||
import { Inertia } from '@inertiajs/inertia' | ||
import { CheckIcon, ChevronUpDownIcon } from '@heroicons/vue/24/solid' | ||
import { Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions } from '@headlessui/vue' | ||
const sortOptions = [ | ||
{ | ||
name: 'Sortowanie domyślne', | ||
value: null, | ||
}, | ||
{ | ||
name: 'Urodziny od najbliższej daty', | ||
value: 'birthday-asc', | ||
}, | ||
{ | ||
name: 'Urodziny od najdalszej daty', | ||
value: 'birthday-desc', | ||
}, | ||
{ | ||
name: 'Najdłuższy staż pracy', | ||
value: 'seniority-asc', | ||
}, | ||
{ | ||
name: 'Najkrótszy staż pracy', | ||
value: 'seniority-desc', | ||
}, | ||
] | ||
const props = defineProps({ | ||
users: Object, | ||
filters: Object, | ||
}) | ||
const form = reactive({ | ||
search: props.filters.search, | ||
sort: sortOptions.find(item => item.value === props.filters.sort) ?? sortOptions[0], | ||
}) | ||
watch(form, debounce(() => { | ||
Inertia.get('/employees-milestones', { | ||
search: form.search, | ||
sort: form.sort?.value ?? undefined, | ||
}, { | ||
preserveState: true, | ||
replace: true, | ||
}) | ||
}, 300)) | ||
</script> | ||
<template> | ||
<InertiaHead title="Jubileusze" /> | ||
<div class="bg-white shadow-md"> | ||
<div class="flex justify-between items-center p-4 sm:px-6"> | ||
<div> | ||
<h2 class="text-lg font-medium leading-6 text-gray-900"> | ||
Jubileusze | ||
</h2> | ||
</div> | ||
</div> | ||
<div class="border-t border-gray-200"> | ||
<div class="flex-1 grid grid-cols-1 p-4 md:grid-cols-3 gap-4"> | ||
<div class="relative"> | ||
<div class="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center"> | ||
<MagnifyingGlassIcon class="w-5 h-5 text-gray-400" /> | ||
</div> | ||
<input | ||
v-model.trim="form.search" | ||
type="search" | ||
class="block py-2 pr-3 pl-10 w-full max-w-lg placeholder:text-gray-500 focus:text-gray-900 focus:placeholder:text-gray-400 bg-white rounded-md border border-gray-300 focus:border-blumilk-500 focus:outline-none focus:ring-1 focus:ring-blumilk-500 sm:text-sm" | ||
placeholder="Szukaj" | ||
> | ||
</div> | ||
<Listbox | ||
v-model="form.sort" | ||
as="div" | ||
> | ||
<div class="relative mt-1 sm:mt-0"> | ||
<ListboxButton | ||
class="relative py-2 pr-10 pl-3 w-full max-w-lg text-left bg-white rounded-md border border-gray-300 focus:border-blumilk-500 focus:outline-none focus:ring-1 focus:ring-blumilk-500 shadow-sm cursor-default sm:text-sm" | ||
> | ||
<span class="flex items-center"> | ||
{{ form.sort.name }} | ||
</span> | ||
<span class="flex absolute inset-y-0 right-0 items-center pr-2 pointer-events-none"> | ||
<ChevronUpDownIcon class="w-5 h-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="overflow-auto absolute z-10 py-1 mt-1 w-full max-w-lg max-h-60 text-base bg-white rounded-md focus:outline-none ring-1 ring-black ring-opacity-5 shadow-lg sm:text-sm" | ||
> | ||
<ListboxOption | ||
v-for="option in sortOptions" | ||
:key="option.value" | ||
v-slot="{ active, selected }" | ||
as="template" | ||
:value="option" | ||
> | ||
<li | ||
:class="[active ? 'bg-gray-100' : 'text-gray-900', 'cursor-default truncate select-none relative py-2 pl-3 pr-9']" | ||
> | ||
{{ option.name }} | ||
<span | ||
v-if="selected" | ||
:class="['text-blumilk-600 absolute inset-y-0 right-0 flex items-center pr-4']" | ||
> | ||
<CheckIcon class="w-5 h-5" /> | ||
</span> | ||
</li> | ||
</ListboxOption> | ||
</ListboxOptions> | ||
</transition> | ||
</div> | ||
</Listbox> | ||
</div> | ||
<div class="overflow-auto xl:overflow-visible relative"> | ||
<table class="min-w-full divide-y divide-gray-200"> | ||
<thead class="bg-gray-50"> | ||
<tr> | ||
<th | ||
scope="col" | ||
class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||
> | ||
<span> | ||
Imię i nazwisko | ||
</span> | ||
</th> | ||
<th | ||
scope="col" | ||
class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||
> | ||
Następne urodziny | ||
</th> | ||
<th | ||
scope="col" | ||
class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||
> | ||
Staż pracy | ||
</th> | ||
</tr> | ||
</thead> | ||
<tbody class="bg-white divide-y divide-gray-100"> | ||
<tr | ||
v-for="user in users.data" | ||
> | ||
<td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||
<div class="flex"> | ||
<span class="inline-flex justify-center items-center w-10 h-10 rounded-full"> | ||
<img | ||
class="w-10 h-10 rounded-full" | ||
:src="user.user.avatar" | ||
> | ||
</span> | ||
<div class="ml-3"> | ||
<p class="text-sm font-medium text-gray-900 break-all"> | ||
{{ user.user.name }} | ||
</p> | ||
<p class="text-sm text-gray-500 break-all"> | ||
{{ user.user.email }} | ||
</p> | ||
</div> | ||
</div> | ||
</td> | ||
<td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||
{{ user.birthdayDisplayDate }} - {{ user.birthdayRelativeDate }} | ||
</td> | ||
<td class="p-4 text-sm text-gray-500 whitespace-nowrap"> | ||
{{ user.seniorityDisplayDate }} | ||
</td> | ||
</tr> | ||
<tr | ||
v-if="! users.data.length" | ||
> | ||
<td | ||
colspan="100%" | ||
class="py-4 text-xl leading-5 text-center text-gray-700" | ||
> | ||
<EmptyState> | ||
<template #title> | ||
Nie znaleziono użytkownika | ||
</template> | ||
<template #text> | ||
Spróbuj sformułować zapytanie inaczej | ||
</template> | ||
</EmptyState> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</div> | ||
<Pagination :pagination="users.meta" /> | ||
</div> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters