Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#456 - user profile #464

Merged
merged 4 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,18 @@
use Toby\Actions\CreateUserAction;
use Toby\Actions\SyncUserPermissionsWithRoleAction;
use Toby\Actions\UpdateUserAction;
use Toby\Domain\DashboardAggregator;
use Toby\Enums\EmploymentForm;
use Toby\Enums\Role;
use Toby\Helpers\YearPeriodRetriever;
use Toby\Http\Requests\UserRequest;
use Toby\Http\Resources\BirthdayResource;
use Toby\Http\Resources\EquipmentItemResource;
use Toby\Http\Resources\OvertimeRequestResource;
use Toby\Http\Resources\UserFormDataResource;
use Toby\Http\Resources\UserResource;
use Toby\Http\Resources\VacationRequestResource;
use Toby\Models\EquipmentItem;
use Toby\Models\User;

class UserController extends Controller
Expand Down Expand Up @@ -142,4 +149,42 @@ public function restore(User $user): RedirectResponse
return back()
->with("success", __("User restored."));
}

public function show(
User $user,
YearPeriodRetriever $yearPeriodRetriever,
DashboardAggregator $dashboardAggregator,
): Response {
$this->authorize("manageUsers");

$yearPeriod = $yearPeriodRetriever->selected();
$equipment = EquipmentItem::query()
->with("assignee")
->where("assignee_id", $user->id)
->get();
$vacationRequests = $user->vacationRequests()
->with(["user", "vacations", "vacations.user", "vacations.user.profile", "user.permissions", "user.profile"])
->whereBelongsTo($yearPeriod)
->latest("updated_at")
->limit(2)
->get();
$overtimeRequests = $user->overtimeRequests()
->with(["user", "user.profile", "user.permissions"])
->whereBelongsTo($yearPeriod)
->latest("updated_at")
->limit(2)
->get();

return inertia("Users/Show", [
"user" => new UserResource($user),
"vacationRequests" => VacationRequestResource::collection($vacationRequests),
"overtimeRequests" => OvertimeRequestResource::collection($overtimeRequests),
"benefits" => $dashboardAggregator->aggregateUserBenefits($user),
"calendar" => $dashboardAggregator->aggregateCalendarData($user, $yearPeriod),
"stats" => $dashboardAggregator->aggregateStats($user, $yearPeriod),
"equipmentItems" => EquipmentItemResource::collection($equipment),
"upcomingBirthday" => new BirthdayResource($user),
"seniority" => $user->seniority(),
]);
}
}
83 changes: 48 additions & 35 deletions resources/js/Pages/AssignedBenefits/AssignedBenefits.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TextArea from '@/Shared/Forms/TextArea.vue'
import { computed, ref, watch } from 'vue'
import { useForm } from '@inertiajs/inertia-vue3'
import { debounce } from 'lodash'
import UserProfileLink from '@/Shared/UserProfileLink.vue'

const props = defineProps({
current: String,
Expand All @@ -22,7 +23,10 @@ const currentMonth = computed(() => findMonth(props.current))

const form = useForm({
items: props.users.data.map((user) => {
const item = props.assignedBenefits.data ? props.assignedBenefits.data.find((assignedBenefit) => assignedBenefit.user === user.id) : { benefits: [], comment: null }
const item = props.assignedBenefits.data ? props.assignedBenefits.data.find((assignedBenefit) => assignedBenefit.user === user.id) : {
benefits: [],
comment: null,
}

return {
user: user,
Expand All @@ -32,8 +36,8 @@ const form = useForm({

return {
id: benefit.id,
employee: typeof assignedBenefit !== 'undefined' && assignedBenefit.employee ? assignedBenefit.employee/100 : null,
employer: typeof assignedBenefit !== 'undefined' && assignedBenefit.employer ? assignedBenefit.employer/100 : null,
employee: typeof assignedBenefit !== 'undefined' && assignedBenefit.employee ? assignedBenefit.employee / 100 : null,
employer: typeof assignedBenefit !== 'undefined' && assignedBenefit.employer ? assignedBenefit.employer / 100 : null,
}
}),
}
Expand All @@ -55,33 +59,37 @@ function submitAssignedBenefits() {
user: item.user.id,
benefits: item.benefits.map((benefit) => ({
id: benefit.id,
employee: benefit.employee ? benefit.employee*100 : null,
employer: benefit.employer ? benefit.employer*100 : null,
employee: benefit.employee ? benefit.employee * 100 : null,
employer: benefit.employer ? benefit.employer * 100 : null,
})),
comment: item.comment,
}
}),
}))
.put('/assigned-benefits')
}

function startCreatingBenefitsReport() {
formBenefitsReport.name = `${currentMonth.value.name} ${props.years.selected.year}`
creatingBenefitsReport.value = true
}

function submitCreateBenefitsReport() {
formBenefitsReport.post('/benefits-reports')
}

function calculateSumOfBenefits(benefits) {
let sum = 0

for(const benefit of benefits){
if(benefit.employer){
sum += benefit.employer*100
for (const benefit of benefits) {
if (benefit.employer) {
sum += benefit.employer * 100
}
}

return (new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN' })).format(sum / 100)
}

function isBenefitHasCompanion(benefitId) {
return props.benefits.data.find((benefit) => benefit.id === benefitId && benefit.companion === true)
}
Expand All @@ -98,10 +106,10 @@ function isBenefitHasCompanion(benefitId) {
</div>
<div v-if="auth.can.manageBenefits && benefits.data.length > 0">
<button
type="button"
class="inline-flex items-center py-3 px-4 text-sm font-medium leading-4 text-white bg-blumilk-600 rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-blumilk-500 focus:ring-offset-2 shadow-sm"
:class="[form.isDirty ? 'disabled:opacity-60' : 'hover:bg-blumilk-700']"
:disabled="form.isDirty"
class="inline-flex items-center py-3 px-4 text-sm font-medium leading-4 text-white bg-blumilk-600 rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-blumilk-500 focus:ring-offset-2 shadow-sm"
type="button"
@click="startCreatingBenefitsReport"
>
Utwórz raport
Expand All @@ -114,8 +122,8 @@ function isBenefitHasCompanion(benefitId) {
<thead class="divide-y divide-gray-300">
<tr class="divide-x divide-gray-300">
<th
rowspan="2"
class="py-2 w-64 text-lg font-semibold text-gray-800 sticky left-0 bg-white outline outline-1 outline-offset-0 outline-gray-300"
rowspan="2"
>
<div class="flex justify-center items-center">
{{ currentMonth.name }} {{ years.selected.year }}
Expand All @@ -133,14 +141,14 @@ function isBenefitHasCompanion(benefitId) {
</div>
</th>
<th
rowspan="2"
class="p-2 text-base font-semibold text-gray-900 even:bg-gray-100"
rowspan="2"
>
Wykorzystane dofinansowanie
</th>
<th
rowspan="2"
class="p-2 text-base font-semibold text-gray-900 even:bg-gray-100"
rowspan="2"
style="min-width: 150px;"
>
Notatki
Expand Down Expand Up @@ -175,14 +183,19 @@ function isBenefitHasCompanion(benefitId) {
>
<th class="group p-2 sticky left-0 outline outline-1 outline-offset-0 outline-gray-300 bg-white hover:bg-blumilk-25 group-hover:bg-blumilk-25">
<div class="flex justify-start items-center">
<span class="inline-flex justify-center items-center w-8 h-8 rounded-full">
<img :src="item.user.avatar">
</span>
<div class="ml-3">
<div class="text-sm font-medium text-gray-900 truncate">
{{ item.user.name }}
<UserProfileLink
:user="item.user"
class="flex justify-start items-center"
>
<span class="inline-flex justify-center items-center w-8 h-8 rounded-full">
<img :src="item.user.avatar">
</span>
<div class="ml-3">
<div class="text-sm font-medium text-gray-900 truncate">
{{ item.user.name }}
</div>
</div>
</div>
</UserProfileLink>
</div>
</th>
<template
Expand All @@ -196,22 +209,22 @@ function isBenefitHasCompanion(benefitId) {
<input
v-model.number="benefit.employer"
:name="`${benefit.id}-employer-${index}`"
type="number"
step="0.01"
class="w-full h-full sm:text-sm appearance-none border-none text-right p-0 px-3 m-0 ring-inset hover:bg-blumilk-25 group-hover:bg-blumilk-25 focus:bg-blumilk-25 focus:ring-2 focus:ring-blumilk-300"
title="Wprowadź kwotę."
min="0"
step="0.01"
title="Wprowadź kwotę."
type="number"
>
</td>
<td style="height: 40px">
<input
v-model.number="benefit.employee"
:name="`${benefit.id}-employee-${index}`"
type="number"
step="0.01"
class="w-full h-full sm:text-sm appearance-none border-none text-right p-0 px-3 m-0 ring-inset hover:bg-blumilk-25 group-hover:bg-blumilk-25 focus:bg-blumilk-25 focus:ring-2 focus:ring-blumilk-300"
title="Wprowadź kwotę."
min="0"
step="0.01"
title="Wprowadź kwotę."
type="number"
>
</td>
</template>
Expand All @@ -236,19 +249,19 @@ function isBenefitHasCompanion(benefitId) {
</div>
<div class="flex justify-end py-3 px-4 sm:px-6">
<button
type="submit"
class="inline-flex justify-center py-2 px-4 text-sm font-medium text-white bg-blumilk-600 rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-blumilk-500 focus:ring-offset-2 shadow-sm"
:class="[form.processing || !form.isDirty ? 'disabled:opacity-60' : 'hover:bg-blumilk-700']"
:disabled="form.processing || !form.isDirty"
class="inline-flex justify-center py-2 px-4 text-sm font-medium text-white bg-blumilk-600 rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-blumilk-500 focus:ring-offset-2 shadow-sm"
type="submit"
>
Zapisz
</button>
</div>
</form>
</div>
<TransitionRoot
as="template"
:show="creatingBenefitsReport"
as="template"
>
<Dialog
is="div"
Expand Down Expand Up @@ -292,18 +305,18 @@ function isBenefitHasCompanion(benefitId) {
</DialogTitle>
<div class="mt-5">
<label
for="name"
class="block text-sm font-medium text-gray-700 sm:mt-px"
for="name"
>
Nazwa
</label>
<div class="mt-2">
<input
id="name"
v-model="formBenefitsReport.name"
type="text"
class="block w-full max-w-lg rounded-md shadow-sm sm:text-sm"
:class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': formBenefitsReport.errors.name, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !formBenefitsReport.errors.name }"
class="block w-full max-w-lg rounded-md shadow-sm sm:text-sm"
type="text"
>
<p
v-if="formBenefitsReport.errors.name"
Expand All @@ -318,17 +331,17 @@ function isBenefitHasCompanion(benefitId) {
<div class="mt-5 sm:mt-6">
<div class="flex justify-end space-x-3">
<button
type="button"
class="py-2 px-4 text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blumilk-500 focus:ring-offset-2 shadow-sm"
type="button"
@click="creatingBenefitsReport = false"
>
Anuluj
</button>
<button
type="submit"
class="inline-flex justify-center py-2 px-4 text-base font-medium text-white bg-blumilk-600 rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-blumilk-500 focus:ring-offset-2 shadow-sm sm:text-sm"
:class="[formBenefitsReport.processing ? 'disabled:opacity-60' : 'hover:bg-blumilk-700']"
:disabled="formBenefitsReport.processing"
class="inline-flex justify-center py-2 px-4 text-base font-medium text-white bg-blumilk-600 rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-blumilk-500 focus:ring-offset-2 shadow-sm sm:text-sm"
type="submit"
>
Utwórz
</button>
Expand Down
Loading