diff --git a/app/Infrastructure/Http/Controllers/DashboardController.php b/app/Infrastructure/Http/Controllers/DashboardController.php index 9f164a9..317fd22 100644 --- a/app/Infrastructure/Http/Controllers/DashboardController.php +++ b/app/Infrastructure/Http/Controllers/DashboardController.php @@ -12,8 +12,11 @@ use Toby\Domain\UserVacationStatsRetriever; use Toby\Domain\VacationRequestStatesRetriever; use Toby\Domain\VacationTypeConfigRetriever; use Toby\Eloquent\Helpers\YearPeriodRetriever; +use Toby\Eloquent\Models\Holiday; +use Toby\Eloquent\Models\Vacation; use Toby\Eloquent\Models\VacationRequest; use Toby\Infrastructure\Http\Resources\HolidayResource; +use Toby\Infrastructure\Http\Resources\SimpleVacationRequestResource; use Toby\Infrastructure\Http\Resources\VacationRequestResource; use Toby\Infrastructure\Http\Resources\VacationResource; @@ -54,6 +57,22 @@ class DashboardController extends Controller ->limit(3) ->get(); + $allHolidays = $yearPeriod->holidays; + + $approvedVacations = $request->user() + ->vacations() + ->with("vacationRequest.vacations") + ->whereBelongsTo($yearPeriod) + ->approved() + ->get(); + + $pendingVacations = $request->user() + ->vacations() + ->with("vacationRequest.vacations") + ->whereBelongsTo($yearPeriod) + ->pending() + ->get(); + $limit = $vacationStatsRetriever->getVacationDaysLimit($user, $yearPeriod); $used = $vacationStatsRetriever->getUsedVacationDays($user, $yearPeriod); $pending = $vacationStatsRetriever->getPendingVacationDays($user, $yearPeriod); @@ -66,6 +85,19 @@ class DashboardController extends Controller "remoteDays" => VacationResource::collection($remoteDays), "vacationRequests" => VacationRequestResource::collection($vacationRequests), "holidays" => HolidayResource::collection($holidays), + "allHolidays" => $allHolidays->mapWithKeys( + fn(Holiday $holiday): array => [$holiday->date->toDateString() => $holiday->name], + ), + "approvedVacations" => $approvedVacations->mapWithKeys( + fn(Vacation $vacation): array => [ + $vacation->date->toDateString() => new SimpleVacationRequestResource($vacation->vacationRequest), + ], + ), + "pendingVacations" => $pendingVacations->mapWithKeys( + fn(Vacation $vacation): array => [ + $vacation->date->toDateString() => new SimpleVacationRequestResource($vacation->vacationRequest), + ], + ), "stats" => [ "limit" => $limit, "remaining" => $remaining, diff --git a/resources/js/Pages/Dashboard.vue b/resources/js/Pages/Dashboard.vue index 1188c6d..b6968ba 100644 --- a/resources/js/Pages/Dashboard.vue +++ b/resources/js/Pages/Dashboard.vue @@ -3,7 +3,11 @@
- +
@@ -50,5 +54,8 @@ defineProps({ can: Object, stats: Object, years: Object, + allHolidays: Object, + approvedVacations: Object, + pendingVacations: Object, }) diff --git a/resources/js/Shared/Widgets/Calendar/DayComponent.vue b/resources/js/Shared/Widgets/Calendar/DayComponent.vue new file mode 100644 index 0000000..712b8d0 --- /dev/null +++ b/resources/js/Shared/Widgets/Calendar/DayComponent.vue @@ -0,0 +1,104 @@ + + + \ No newline at end of file diff --git a/resources/js/Shared/Widgets/VacationCalendar.vue b/resources/js/Shared/Widgets/VacationCalendar.vue index 7d9de57..d834fd2 100644 --- a/resources/js/Shared/Widgets/VacationCalendar.vue +++ b/resources/js/Shared/Widgets/VacationCalendar.vue @@ -120,19 +120,16 @@ class="w-full grid grid-cols-7 gap-px" :class="{ 'grid-rows-1': calendarState.viewMode.isWeek }" > -
- -
+ :day="day" + class="flex flex-col relative py-2 px-3" + :class="[day.isCurrentMonth ? 'bg-white' : 'bg-gray-50 text-gray-500', { 'hover:bg-blumilk-25': day.isCurrentMonth && !day.isWeekend }, { 'day': calendarState.viewMode.isWeek }, { 'bg-red-100': day.isCurrentMonth && day.isWeekend }, { 'bg-red-50': !day.isCurrentMonth && day.isWeekend }, { 'text-red-800': day.isWeekend }]" + :get-holiday-description="getHolidayDescription" + :get-vacation-border="getVacationBorder" + :get-vacation-info="getVacationInfo" + />
@@ -144,19 +141,30 @@ import { CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from '@ import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue' import { ref, watch, computed, reactive } from 'vue' import { DateTime } from 'luxon' +import useVacationTypeInfo from '@/Composables/vacationTypeInfo' import useCurrentYearPeriodInfo from '@/Composables/yearPeriodInfo' import { useMonthInfo } from '@/Composables/monthInfo' import { viewModes, find as findViewMode } from '@/Shared/Widgets/Calendar/ViewModeOptions' +import DayComponent from '@/Shared/Widgets/Calendar/DayComponent' + +const props = defineProps({ + holidays: Object, + approvedVacations: Object, + pendingVacations: Object, +}) let days = ref([]) -const months = useMonthInfo().getMonths() + function getCurrentDate() { const { year, month, weekNumber } = DateTime.now() return { year, month, week: weekNumber } } -const selectedYear = useCurrentYearPeriodInfo().year.value const currentDate = getCurrentDate() +const months = useMonthInfo().getMonths() +const { findType } = useVacationTypeInfo() +const selectedYear = useCurrentYearPeriodInfo().year.value + const calendar = { viewMode: ref('week'), currents: reactive({ @@ -221,11 +229,16 @@ const customCalendar = { return days }, prepareDay(day) { + const isCurrentMonth = isInCurrentMonth(day) return { date: day.toISODate(), dayNumber: day.day, - isCurrentMonth: isInCurrentMonth(day), + isCurrentMonth: isCurrentMonth, isToday: isToday(day), + isWeekend: isWeekend(day), + isHoliday: isHoliday(day), + isVacation: isCurrentMonth && isVacation(day), + isPendingVacation: isCurrentMonth && isPendingVacation(day), } }, } @@ -256,7 +269,7 @@ function resetCalendar(config = {}) { calendar.currents.year = isUndefined(config.year) ? selectedYear : config.month calendar.currents.month = calendarState.isActualYear || !isUndefined(config.year) ? currentMonth : 1 - calendar.currents.week = calendarState.isActualYear || !isUndefined(config.year) ? currentWeek : 1 + calendar.currents.week = calendarState.isActualYear || !isUndefined(config.week) ? currentWeek : 0 } function isUndefined(value) { @@ -307,7 +320,7 @@ function goToToday() { function updateViewMode(type) { if (type === 'month') - resetCalendar({ week: 1 }) + resetCalendar({ week: 0 }) else resetCalendar() calendar.viewMode.value = type @@ -317,9 +330,37 @@ function isInCurrentMonth(date) { return calendar.currents.month === date.month } +function isWeekend(date) { + return date.weekday === 6 || date.weekday === 7 +} + function isToday(date) { return date.toISODate() === DateTime.local().toISODate() } + +function isHoliday(date) { + return props.holidays[date.toISODate()] !== undefined +} + +function getHolidayDescription(day) { + return props.holidays[day.date] +} + +function isVacation(date) { + return props.approvedVacations[date.toISODate()] !== undefined +} + +function isPendingVacation(date) { + return props.pendingVacations[date.toISODate()] !== undefined +} + +function getVacationBorder(day) { + return findType(getVacationInfo(day).type)?.border +} + +function getVacationInfo(day) { + return day.isVacation ? props.approvedVacations[day.date] : props.pendingVacations[day.date] +}