Compare commits
	
		
			14 Commits
		
	
	
		
			style-upda
			...
			dashboard-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1d7b4da903 | |||
| 94f433de6e | |||
| a9c476cb8e | |||
| 5c3833d4cb | |||
| 6e627d11c8 | |||
| eb644fa494 | |||
| 4392b666e1 | |||
| e7c1028da1 | |||
| a7bc4695a7 | |||
| 4e16f363ac | |||
| 7893282385 | |||
| db874d4395 | |||
| dcc3808428 | |||
| 2a3e65ed5f | 
| @@ -12,8 +12,11 @@ use Toby\Domain\UserVacationStatsRetriever; | |||||||
| use Toby\Domain\VacationRequestStatesRetriever; | use Toby\Domain\VacationRequestStatesRetriever; | ||||||
| use Toby\Domain\VacationTypeConfigRetriever; | use Toby\Domain\VacationTypeConfigRetriever; | ||||||
| use Toby\Eloquent\Helpers\YearPeriodRetriever; | use Toby\Eloquent\Helpers\YearPeriodRetriever; | ||||||
|  | use Toby\Eloquent\Models\Holiday; | ||||||
|  | use Toby\Eloquent\Models\Vacation; | ||||||
| use Toby\Eloquent\Models\VacationRequest; | use Toby\Eloquent\Models\VacationRequest; | ||||||
| use Toby\Infrastructure\Http\Resources\HolidayResource; | use Toby\Infrastructure\Http\Resources\HolidayResource; | ||||||
|  | use Toby\Infrastructure\Http\Resources\SimpleVacationRequestResource; | ||||||
| use Toby\Infrastructure\Http\Resources\VacationRequestResource; | use Toby\Infrastructure\Http\Resources\VacationRequestResource; | ||||||
| use Toby\Infrastructure\Http\Resources\VacationResource; | use Toby\Infrastructure\Http\Resources\VacationResource; | ||||||
|  |  | ||||||
| @@ -54,6 +57,22 @@ class DashboardController extends Controller | |||||||
|             ->limit(3) |             ->limit(3) | ||||||
|             ->get(); |             ->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); |         $limit = $vacationStatsRetriever->getVacationDaysLimit($user, $yearPeriod); | ||||||
|         $used = $vacationStatsRetriever->getUsedVacationDays($user, $yearPeriod); |         $used = $vacationStatsRetriever->getUsedVacationDays($user, $yearPeriod); | ||||||
|         $pending = $vacationStatsRetriever->getPendingVacationDays($user, $yearPeriod); |         $pending = $vacationStatsRetriever->getPendingVacationDays($user, $yearPeriod); | ||||||
| @@ -66,6 +85,19 @@ class DashboardController extends Controller | |||||||
|             "remoteDays" => VacationResource::collection($remoteDays), |             "remoteDays" => VacationResource::collection($remoteDays), | ||||||
|             "vacationRequests" => VacationRequestResource::collection($vacationRequests), |             "vacationRequests" => VacationRequestResource::collection($vacationRequests), | ||||||
|             "holidays" => HolidayResource::collection($holidays), |             "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" => [ |             "stats" => [ | ||||||
|                 "limit" => $limit, |                 "limit" => $limit, | ||||||
|                 "remaining" => $remaining, |                 "remaining" => $remaining, | ||||||
|   | |||||||
| @@ -55,20 +55,18 @@ | |||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="overflow-x-auto"> |     <div class="overflow-x-auto"> | ||||||
|       <table class="w-full text-sm text-center border-y border-r border-gray-300"> |       <table class="w-full text-sm text-center border border-gray-300"> | ||||||
|         <thead> |         <thead> | ||||||
|           <tr> |           <tr> | ||||||
|             <th |             <th class="py-2 w-64 text-lg font-semibold text-gray-800 border border-gray-300"> | ||||||
|               class="py-2 w-64 text-lg font-semibold text-gray-800 border-y border-gray-300 bg-white sticky left-0 sticky-border" |  | ||||||
|             > |  | ||||||
|               <div class="flex justify-center items-center"> |               <div class="flex justify-center items-center"> | ||||||
|                 {{ selectedMonth.name }} |                 {{ selectedMonth.name }} {{ years.selected.year }} | ||||||
|               </div> |               </div> | ||||||
|             </th> |             </th> | ||||||
|             <th |             <th | ||||||
|               v-for="day in calendar" |               v-for="day in calendar" | ||||||
|               :key="day.dayOfMonth" |               :key="day.dayOfMonth" | ||||||
|               class="p-2 text-lg font-semibold text-gray-900 border second:border-l-0 border-gray-300" |               class="p-2 text-lg font-semibold text-gray-900 border border-gray-300" | ||||||
|               style="min-width: 46px;" |               style="min-width: 46px;" | ||||||
|               :class="{ 'bg-red-100 text-red-800': day.isWeekend || day.isHoliday, 'text-blumilk-600 bg-blumilk-25': day.isToday }" |               :class="{ 'bg-red-100 text-red-800': day.isWeekend || day.isHoliday, 'text-blumilk-600 bg-blumilk-25': day.isToday }" | ||||||
|             > |             > | ||||||
| @@ -86,28 +84,22 @@ | |||||||
|             v-for="user in users.data" |             v-for="user in users.data" | ||||||
|             :key="user.id" |             :key="user.id" | ||||||
|           > |           > | ||||||
|             <th |             <th class="p-2 border border-gray-300"> | ||||||
|               class="p-2 border-y border-gray-300 bg-white sticky left-0 sticky-border" |  | ||||||
|             > |  | ||||||
|               <div class="flex justify-start items-center"> |               <div class="flex justify-start items-center"> | ||||||
|                 <span class="inline-flex justify-center items-center w-8 h-8 rounded-full"> |                 <span class="inline-flex justify-center items-center w-8 h-8 rounded-full"> | ||||||
|                   <img :src="user.avatar"> |                   <img :src="user.avatar"> | ||||||
|                 </span> |                 </span> | ||||||
|                 <div class="ml-3 flex items-start flex-col-reverse md:flex-row"> |                 <div class="ml-3"> | ||||||
|                   <span |                   <div class="text-sm font-medium text-gray-900 truncate"> | ||||||
|                     v-for="split in user.name.split(' ', 2)" |                     {{ user.name }} | ||||||
|                     :key="split" |                   </div> | ||||||
|                     class="text-sm first:text-xs md:first:text-sm font-medium text-gray-900 truncate first:mr-1" |  | ||||||
|                   > |  | ||||||
|                     {{ split }} |  | ||||||
|                   </span> |  | ||||||
|                 </div> |                 </div> | ||||||
|               </div> |               </div> | ||||||
|             </th> |             </th> | ||||||
|             <td |             <td | ||||||
|               v-for="day in calendar" |               v-for="day in calendar" | ||||||
|               :key="day.dayOfMonth" |               :key="day.dayOfMonth" | ||||||
|               class="border second:border-l-0 border-gray-300" |               class="border border-gray-300" | ||||||
|               :class="{ 'bg-blumilk-25': day.isToday, 'bg-red-100': day.isWeekend || day.isHoliday }" |               :class="{ 'bg-blumilk-25': day.isToday, 'bg-red-100': day.isWeekend || day.isHoliday }" | ||||||
|               @mouseover="setActiveDay(user.id + '+' + day.date)" |               @mouseover="setActiveDay(user.id + '+' + day.date)" | ||||||
|               @mouseleave="unsetActiveDay" |               @mouseleave="unsetActiveDay" | ||||||
| @@ -184,10 +176,3 @@ function linkParameters(user, day) { | |||||||
|   return props.can.createOnBehalfOfEmployee ? { user: user.id, from_date: day.date } : { from_date: day.date } |   return props.can.createOnBehalfOfEmployee ? { user: user.id, from_date: day.date } : { from_date: day.date } | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="css"> |  | ||||||
| .sticky-border { |  | ||||||
|   box-shadow: inset -1px 0 rgb(209 213 219 / 1), |  | ||||||
|               inset 1px 0 rgb(209 213 219 / 1); |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|   | |||||||
| @@ -3,11 +3,14 @@ | |||||||
|   <div class="grid grid-cols-1 gap-4 items-start xl:grid-cols-3 xl:gap-8"> |   <div class="grid grid-cols-1 gap-4 items-start xl:grid-cols-3 xl:gap-8"> | ||||||
|     <div class="grid grid-cols-1 gap-4 xl:col-span-2"> |     <div class="grid grid-cols-1 gap-4 xl:col-span-2"> | ||||||
|       <Welcome :user="auth.user" /> |       <Welcome :user="auth.user" /> | ||||||
|       <VacationCalendar /> |       <VacationCalendar | ||||||
|  |         :holidays="allHolidays" | ||||||
|  |         :approved-vacations="approvedVacations" | ||||||
|  |         :pending-vacations="pendingVacations" | ||||||
|  |       /> | ||||||
|       <VacationStats :stats="stats" /> |       <VacationStats :stats="stats" /> | ||||||
|     </div> |     </div> | ||||||
|     <div class="grid grid-cols-1 gap-4"> |     <div class="grid grid-cols-1 gap-4"> | ||||||
|       <VacationCalendar /> |  | ||||||
|       <PendingVacationRequests |       <PendingVacationRequests | ||||||
|         v-if="can.listAllVacationRequests" |         v-if="can.listAllVacationRequests" | ||||||
|         :requests="vacationRequests.data" |         :requests="vacationRequests.data" | ||||||
| @@ -51,5 +54,8 @@ defineProps({ | |||||||
|   can: Object, |   can: Object, | ||||||
|   stats: Object, |   stats: Object, | ||||||
|   years: Object, |   years: Object, | ||||||
|  |   allHolidays: Object, | ||||||
|  |   approvedVacations: Object, | ||||||
|  |   pendingVacations: Object, | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
|   | |||||||
| @@ -9,11 +9,11 @@ | |||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="border-t border-gray-200"> |     <div class="border-t border-gray-200"> | ||||||
|       <div class="overflow-x-auto xl:overflow-x-visible"> |       <div class="overflow-x-auto overflow-y-hidden xl:overflow-x-visible"> | ||||||
|         <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 class="py-3 px-6 w-64 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase bg-gray-50 sticky -left-1"> |               <th class="py-3 px-6 w-64 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase"> | ||||||
|                 Pracownik |                 Pracownik | ||||||
|               </th> |               </th> | ||||||
|               <th |               <th | ||||||
| @@ -38,7 +38,7 @@ | |||||||
|               :key="item.user.id" |               :key="item.user.id" | ||||||
|               class="hover:bg-blumilk-25" |               class="hover:bg-blumilk-25" | ||||||
|             > |             > | ||||||
|               <th class="p-4 text-sm font-semibold text-gray-500 capitalize whitespace-nowrap bg-white sticky -left-1"> |               <th class="p-4 text-sm font-semibold text-gray-500 capitalize whitespace-nowrap"> | ||||||
|                 <div class="flex justify-start items-center"> |                 <div class="flex justify-start items-center"> | ||||||
|                   <span class="inline-flex justify-center items-center w-10 h-10 rounded-full"> |                   <span class="inline-flex justify-center items-center w-10 h-10 rounded-full"> | ||||||
|                     <img |                     <img | ||||||
| @@ -46,14 +46,12 @@ | |||||||
|                       :src="item.user.avatar" |                       :src="item.user.avatar" | ||||||
|                     > |                     > | ||||||
|                   </span> |                   </span> | ||||||
|                   <div class="ml-3 flex items-start flex-col-reverse md:flex-row"> |                   <div class="ml-3"> | ||||||
|                     <span |                     <div | ||||||
|                       v-for="split in item.user.name.split(' ', 2)" |                       class="text-sm font-medium text-gray-900 whitespace-nowrap" | ||||||
|                       :key="split" |  | ||||||
|                       class="text-sm first:text-xs md:first:text-sm font-medium text-gray-900 truncate first:mr-1" |  | ||||||
|                     > |                     > | ||||||
|                       {{ split }} |                       {{ item.user.name }} | ||||||
|                     </span> |                     </div> | ||||||
|                   </div> |                   </div> | ||||||
|                 </div> |                 </div> | ||||||
|               </th> |               </th> | ||||||
|   | |||||||
| @@ -242,12 +242,46 @@ | |||||||
|         <thead class="bg-gray-50"> |         <thead class="bg-gray-50"> | ||||||
|           <tr> |           <tr> | ||||||
|             <th |             <th | ||||||
|               v-for="head in headers" |  | ||||||
|               :key="head" |  | ||||||
|               scope="col" |               scope="col" | ||||||
|               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" |               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|             > |             > | ||||||
|               {{ head }} |               Numer | ||||||
|  |             </th> | ||||||
|  |             <th | ||||||
|  |               scope="col" | ||||||
|  |               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |             > | ||||||
|  |               Pracownik | ||||||
|  |             </th> | ||||||
|  |             <th | ||||||
|  |               scope="col" | ||||||
|  |               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |             > | ||||||
|  |               Rodzaj wniosku | ||||||
|  |             </th> | ||||||
|  |             <th | ||||||
|  |               scope="col" | ||||||
|  |               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |             > | ||||||
|  |               Od | ||||||
|  |             </th> | ||||||
|  |             <th | ||||||
|  |               scope="col" | ||||||
|  |               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |             > | ||||||
|  |               Do | ||||||
|  |             </th> | ||||||
|  |             <th | ||||||
|  |               scope="col" | ||||||
|  |               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |             > | ||||||
|  |               Dni urlopu | ||||||
|  |             </th> | ||||||
|  |             <th | ||||||
|  |               scope="col" | ||||||
|  |               class="py-3 px-4 text-xs font-semibold tracking-wider text-left text-gray-500 uppercase whitespace-nowrap" | ||||||
|  |             > | ||||||
|  |               Status | ||||||
|             </th> |             </th> | ||||||
|             <th scope="col" /> |             <th scope="col" /> | ||||||
|           </tr> |           </tr> | ||||||
| @@ -347,8 +381,6 @@ const props = defineProps({ | |||||||
|   types: Object, |   types: Object, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| const headers = ['Numer', 'Pracownik', 'Rodzaj wniosku', 'Od', 'Do', 'Dni urlopu', 'Status'] |  | ||||||
|  |  | ||||||
| const statuses = [ | const statuses = [ | ||||||
|   { |   { | ||||||
|     name: 'Wszystkie', |     name: 'Wszystkie', | ||||||
|   | |||||||
							
								
								
									
										104
									
								
								resources/js/Shared/Widgets/Calendar/DayComponent.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								resources/js/Shared/Widgets/Calendar/DayComponent.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | |||||||
|  | <template> | ||||||
|  |   <div | ||||||
|  |     :class="[ (day.isVacation || day.isPendingVacation) && `border-b-2 border-dashed ${getVacationBorder(day)}` ]" | ||||||
|  |   > | ||||||
|  |     <Popper | ||||||
|  |       v-if="day.isHoliday" | ||||||
|  |       as="div" | ||||||
|  |       open-delay="200" | ||||||
|  |       hover | ||||||
|  |       offset-distance="0" | ||||||
|  |       @mouseover.passive="onMouseover" | ||||||
|  |       @mouseleave="onMouseleave" | ||||||
|  |     > | ||||||
|  |       <time | ||||||
|  |         :datetime="day.date" | ||||||
|  |         :class="[ day.isToday && 'flex h-6 w-6 items-center justify-center rounded-full bg-blumilk-500 font-semibold text-white', 'text-red-600' ]" | ||||||
|  |       > | ||||||
|  |         {{ day.dayNumber }} | ||||||
|  |       </time> | ||||||
|  |       <template #content> | ||||||
|  |         <div class="py-2 px-6 text-sm font-semibold text-left text-gray-700 bg-white rounded-lg border border-gray-400"> | ||||||
|  |           {{ getHolidayDescription(day) }} | ||||||
|  |         </div> | ||||||
|  |       </template> | ||||||
|  |     </Popper> | ||||||
|  |     <Popper | ||||||
|  |       v-else-if="day.isPendingVacation" | ||||||
|  |       as="div" | ||||||
|  |       open-delay="200" | ||||||
|  |       hover | ||||||
|  |       offset-distance="0" | ||||||
|  |       @mouseover.passive="onMouseover" | ||||||
|  |       @mouseleave="onMouseleave" | ||||||
|  |     > | ||||||
|  |       <time | ||||||
|  |         :datetime="day.date" | ||||||
|  |         :class="[ day.isToday && 'flex h-6 w-6 items-center justify-center rounded-full bg-blumilk-500 font-semibold text-white' ]" | ||||||
|  |       > | ||||||
|  |         {{ day.dayNumber }} | ||||||
|  |       </time> | ||||||
|  |       <template #content> | ||||||
|  |         <VacationPopup :vacation="getVacationInfo(day)" /> | ||||||
|  |       </template> | ||||||
|  |     </Popper> | ||||||
|  |     <div | ||||||
|  |       v-else-if="day.isWeekend" | ||||||
|  |     > | ||||||
|  |       <time | ||||||
|  |         :datetime="day.date" | ||||||
|  |         :class="{ 'flex h-6 w-6 items-center justify-center rounded-full bg-blumilk-500 font-semibold text-white': day.isToday }" | ||||||
|  |       > | ||||||
|  |         {{ day.dayNumber }} | ||||||
|  |       </time> | ||||||
|  |     </div> | ||||||
|  |     <InertiaLink | ||||||
|  |       v-else | ||||||
|  |       href="/vacation/requests/create" | ||||||
|  |       :data="{ 'from_date': day.date }" | ||||||
|  |       @mouseover.passive="onMouseover" | ||||||
|  |       @mouseleave="onMouseleave" | ||||||
|  |     > | ||||||
|  |       <time | ||||||
|  |         :datetime="day.date" | ||||||
|  |         :class="{ 'flex h-6 w-6 items-center justify-center rounded-full bg-blumilk-500 font-semibold text-white': day.isToday }" | ||||||
|  |       > | ||||||
|  |         {{ day.dayNumber }} | ||||||
|  |       </time> | ||||||
|  |     </InertiaLink> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script setup> | ||||||
|  | import Popper from 'vue3-popper' | ||||||
|  | import { defineProps, ref } from 'vue' | ||||||
|  | import VacationPopup from '@/Shared/VacationPopup' | ||||||
|  |  | ||||||
|  | defineProps({ | ||||||
|  |   day: { | ||||||
|  |     type: Object, | ||||||
|  |     required: true, | ||||||
|  |   }, | ||||||
|  |   getHolidayDescription: { | ||||||
|  |     type: Function, | ||||||
|  |   }, | ||||||
|  |   getVacationBorder: { | ||||||
|  |     type: Function, | ||||||
|  |   }, | ||||||
|  |   getVacationInfo: { | ||||||
|  |     type: Function, | ||||||
|  |   }, | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | const isActive = ref(false) | ||||||
|  |  | ||||||
|  | function onMouseover() { | ||||||
|  |   if (!isActive.value) | ||||||
|  |     isActive.value = true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function onMouseleave() { | ||||||
|  |   if (isActive.value) | ||||||
|  |     isActive.value = false | ||||||
|  | } | ||||||
|  | </script> | ||||||
| @@ -120,19 +120,16 @@ | |||||||
|           class="w-full grid grid-cols-7 gap-px" |           class="w-full grid grid-cols-7 gap-px" | ||||||
|           :class="{ 'grid-rows-1': calendarState.viewMode.isWeek }" |           :class="{ 'grid-rows-1': calendarState.viewMode.isWeek }" | ||||||
|         > |         > | ||||||
|           <div |           <DayComponent | ||||||
|             v-for="(day, index) in days" |             v-for="(day, index) in days" | ||||||
|             :key="index" |             :key="index" | ||||||
|             class="flex flex-col" |             :day="day" | ||||||
|             :class="[day.isCurrentMonth ? 'bg-white' : 'bg-gray-50 text-gray-500', calendarState.viewMode.isWeek && index !== 0 && (index % 5 === 0 || index % 6 === 0) ? 'bg-red-100' : undefined, calendarState.viewMode.isWeek ? 'day' : 'month-day', 'relative py-2 px-3']" |             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 }]" | ||||||
|             <time |             :get-holiday-description="getHolidayDescription" | ||||||
|               :datetime="day.date" |             :get-vacation-border="getVacationBorder" | ||||||
|               :class="day.isToday ? 'flex h-6 w-6 items-center justify-center rounded-full bg-indigo-600 font-semibold text-white' : undefined" |             :get-vacation-info="getVacationInfo" | ||||||
|             > |           /> | ||||||
|               {{ day.date.split('-').pop().replace(/^0/, '') }} |  | ||||||
|             </time> |  | ||||||
|           </div> |  | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
| @@ -144,19 +141,30 @@ import { CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from '@ | |||||||
| import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue' | import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue' | ||||||
| import { ref, watch, computed, reactive } from 'vue' | import { ref, watch, computed, reactive } from 'vue' | ||||||
| import { DateTime } from 'luxon' | import { DateTime } from 'luxon' | ||||||
|  | import useVacationTypeInfo from '@/Composables/vacationTypeInfo' | ||||||
| import useCurrentYearPeriodInfo from '@/Composables/yearPeriodInfo' | import useCurrentYearPeriodInfo from '@/Composables/yearPeriodInfo' | ||||||
| import { useMonthInfo } from '@/Composables/monthInfo' | import { useMonthInfo } from '@/Composables/monthInfo' | ||||||
| import { viewModes, find as findViewMode } from '@/Shared/Widgets/Calendar/ViewModeOptions' | 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([]) | let days = ref([]) | ||||||
| const months = useMonthInfo().getMonths() |  | ||||||
| function getCurrentDate() { | function getCurrentDate() { | ||||||
|   const { year, month, weekNumber } = DateTime.now() |   const { year, month, weekNumber } = DateTime.now() | ||||||
|   return { year, month, week: weekNumber } |   return { year, month, week: weekNumber } | ||||||
| } | } | ||||||
| const selectedYear = useCurrentYearPeriodInfo().year.value |  | ||||||
| const currentDate = getCurrentDate() | const currentDate = getCurrentDate() | ||||||
|  |  | ||||||
|  | const months = useMonthInfo().getMonths() | ||||||
|  | const { findType } = useVacationTypeInfo() | ||||||
|  | const selectedYear = useCurrentYearPeriodInfo().year.value | ||||||
|  |  | ||||||
| const calendar = { | const calendar = { | ||||||
|   viewMode: ref('week'), |   viewMode: ref('week'), | ||||||
|   currents: reactive({ |   currents: reactive({ | ||||||
| @@ -179,7 +187,7 @@ const calendarState = reactive({ | |||||||
| }) | }) | ||||||
|  |  | ||||||
| const customCalendar = { | const customCalendar = { | ||||||
|   generateCalendar() { |   loadCalendar() { | ||||||
|     const date = DateTime.fromObject({ |     const date = DateTime.fromObject({ | ||||||
|       year: calendar.currents.year, |       year: calendar.currents.year, | ||||||
|       month: calendarState.viewMode.isMonth ? calendar.currents.month : 1, |       month: calendarState.viewMode.isMonth ? calendar.currents.month : 1, | ||||||
| @@ -221,33 +229,38 @@ const customCalendar = { | |||||||
|     return days |     return days | ||||||
|   }, |   }, | ||||||
|   prepareDay(day) { |   prepareDay(day) { | ||||||
|  |     const isCurrentMonth = isInCurrentMonth(day) | ||||||
|     return { |     return { | ||||||
|       date: day.toISODate(), |       date: day.toISODate(), | ||||||
|       dayNumber: day.day, |       dayNumber: day.day, | ||||||
|       isCurrentMonth: isInCurrentMonth(day), |       isCurrentMonth: isCurrentMonth, | ||||||
|       isToday: isToday(day), |       isToday: isToday(day), | ||||||
|  |       isWeekend: isWeekend(day), | ||||||
|  |       isHoliday: isHoliday(day), | ||||||
|  |       isVacation: isCurrentMonth && isVacation(day), | ||||||
|  |       isPendingVacation: isCurrentMonth && isPendingVacation(day), | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
| } | } | ||||||
|  |  | ||||||
| watch([calendar.viewMode, calendar.currents], () => { | watch([calendar.viewMode, calendar.currents], () => { | ||||||
|   customCalendar.generateCalendar() |   customCalendar.loadCalendar() | ||||||
| }) | }) | ||||||
|  |  | ||||||
| customCalendar.generateCalendar() | customCalendar.loadCalendar() | ||||||
|  |  | ||||||
| function toLast() { | function toLast() { | ||||||
|   if (calendar.viewMode.value === 'week') |   if (calendar.viewMode.value === 'week') | ||||||
|     minusWeek() |     minusWeek() | ||||||
|   else |   else | ||||||
|     addMonths(-1) |     minusMonth() | ||||||
| } | } | ||||||
|  |  | ||||||
| function toNext() { | function toNext() { | ||||||
|   if (calendar.viewMode.value === 'week') { |   if (calendar.viewMode.value === 'week') | ||||||
|     addWeek() |     addWeek() | ||||||
|   } else |   else | ||||||
|     addMonths() |     addMonth() | ||||||
| } | } | ||||||
|  |  | ||||||
| function resetCalendar(config = {}) { | function resetCalendar(config = {}) { | ||||||
| @@ -256,7 +269,7 @@ function resetCalendar(config = {}) { | |||||||
|  |  | ||||||
|   calendar.currents.year = isUndefined(config.year) ? selectedYear : config.month |   calendar.currents.year = isUndefined(config.year) ? selectedYear : config.month | ||||||
|   calendar.currents.month = calendarState.isActualYear || !isUndefined(config.year) ? currentMonth : 1 |   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) { | function isUndefined(value) { | ||||||
| @@ -275,15 +288,10 @@ function addWeek(minus = false) { | |||||||
|  |  | ||||||
|   const startWeekDay = date.startOf('week'), endWeekDay = date.endOf('week') |   const startWeekDay = date.startOf('week'), endWeekDay = date.endOf('week') | ||||||
|   nextMonth = howMany > 0 ? startWeekDay.month : endWeekDay.month |   nextMonth = howMany > 0 ? startWeekDay.month : endWeekDay.month | ||||||
|   if (howMany < 0 && endWeekDay.day === endWeekDay.daysInMonth) { |   if (howMany < 0 && endWeekDay.day === endWeekDay.daysInMonth) | ||||||
|     console.log('pre', endWeekDay.day, endWeekDay.daysInMonth) |  | ||||||
|     calendar.currents.week-- |     calendar.currents.week-- | ||||||
|   } else if (howMany > 0 && startWeekDay.day === 1) { |   else if (howMany > 0 && startWeekDay.day === 1) | ||||||
|     console.log('next', endWeekDay.day, endWeekDay.daysInMonth) |  | ||||||
|     calendar.currents.week++ |     calendar.currents.week++ | ||||||
|   } else { |  | ||||||
|     console.log('else', endWeekDay.day, endWeekDay.daysInMonth) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (nextMonth !== calendar.currents.month) { |   if (nextMonth !== calendar.currents.month) { | ||||||
|     calendar.currents.month = calendar.currents.week > 1 ? nextMonth : 1 |     calendar.currents.month = calendar.currents.week > 1 ? nextMonth : 1 | ||||||
| @@ -298,8 +306,12 @@ function minusWeek() { | |||||||
|   addWeek(true) |   addWeek(true) | ||||||
| } | } | ||||||
|  |  | ||||||
| function addMonths(howMany = 1) { | function addMonth(minus = false) { | ||||||
|   calendar.currents.month += howMany |   calendar.currents.month += minus ? -1 : 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function minusMonth() { | ||||||
|  |   addMonth(true) | ||||||
| } | } | ||||||
|  |  | ||||||
| function goToToday() { | function goToToday() { | ||||||
| @@ -308,7 +320,7 @@ function goToToday() { | |||||||
|  |  | ||||||
| function updateViewMode(type) { | function updateViewMode(type) { | ||||||
|   if (type === 'month') |   if (type === 'month') | ||||||
|     resetCalendar({ week: 1 }) |     resetCalendar({ week: 0 }) | ||||||
|   else |   else | ||||||
|     resetCalendar() |     resetCalendar() | ||||||
|   calendar.viewMode.value = type |   calendar.viewMode.value = type | ||||||
| @@ -318,9 +330,37 @@ function isInCurrentMonth(date) { | |||||||
|   return calendar.currents.month === date.month |   return calendar.currents.month === date.month | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function isWeekend(date) { | ||||||
|  |   return date.weekday === 6 || date.weekday === 7 | ||||||
|  | } | ||||||
|  |  | ||||||
| function isToday(date) { | function isToday(date) { | ||||||
|   return date.toISODate() === DateTime.local().toISODate() |   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] | ||||||
|  | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="css"> | <style lang="css"> | ||||||
| @@ -344,11 +384,6 @@ function isToday(date) { | |||||||
|   content: "Pt"; |   content: "Pt"; | ||||||
| } | } | ||||||
|  |  | ||||||
| .day:nth-of-type(7n - 1):before, |  | ||||||
| .day:nth-of-type(7n):before { |  | ||||||
|   color: #991b1b; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .day:nth-of-type(7n - 1):before { | .day:nth-of-type(7n - 1):before { | ||||||
|   content: "Sb"; |   content: "Sb"; | ||||||
| } | } | ||||||
| @@ -356,8 +391,4 @@ function isToday(date) { | |||||||
| .day:nth-of-type(7n):before { | .day:nth-of-type(7n):before { | ||||||
|   content: "Nd"; |   content: "Nd"; | ||||||
| } | } | ||||||
|  |  | ||||||
| .month-day:nth-of-type(7n - 1), .month-day:nth-of-type(7n) { |  | ||||||
|   background-color: #fee2e2; |  | ||||||
| } |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| const defaultTheme = require('tailwindcss/defaultTheme') | const defaultTheme = require('tailwindcss/defaultTheme') | ||||||
| const plugin = require('tailwindcss/plugin') |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|   content: [ |   content: [ | ||||||
| @@ -32,12 +31,5 @@ module.exports = { | |||||||
|     require('@tailwindcss/forms'), |     require('@tailwindcss/forms'), | ||||||
|     require('@tailwindcss/typography'), |     require('@tailwindcss/typography'), | ||||||
|     require('@tailwindcss/line-clamp'), |     require('@tailwindcss/line-clamp'), | ||||||
|     plugin(function({ addVariant, e }) { |  | ||||||
|       addVariant('second', ({ modifySelectors, separator }) => { |  | ||||||
|         modifySelectors(({ className }) => { |  | ||||||
|           return `.${e(`second${separator}${className}`)}:nth-child(2)` |  | ||||||
|         }) |  | ||||||
|       }) |  | ||||||
|     }), |  | ||||||
|   ], |   ], | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user