diff --git a/app/Domain/CalendarGenerator.php b/app/Domain/CalendarGenerator.php index 5409284..61313cb 100644 --- a/app/Domain/CalendarGenerator.php +++ b/app/Domain/CalendarGenerator.php @@ -44,6 +44,7 @@ class CalendarGenerator "isWeekend" => $day->isWeekend(), "isHoliday" => $holidays->contains($day), "vacations" => $vacationsForDay->pluck("user_id"), + "vacationTypes" => $vacationsForDay->pluck("vacationRequest.type", "user_id"), ]; } @@ -55,6 +56,7 @@ class CalendarGenerator return Vacation::query() ->whereBetween("date", [$period->start, $period->end]) ->whereRelation("vacationRequest", fn(Builder $query) => $query->states(VacationRequestStatesRetriever::successStates())) + ->with("vacationRequest") ->get() ->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString()); } diff --git a/app/Infrastructure/Http/Controllers/VacationCalendarController.php b/app/Infrastructure/Http/Controllers/VacationCalendarController.php index 95353b3..a347ee4 100644 --- a/app/Infrastructure/Http/Controllers/VacationCalendarController.php +++ b/app/Infrastructure/Http/Controllers/VacationCalendarController.php @@ -22,20 +22,25 @@ class VacationCalendarController extends Controller ?string $month = null, ): Response { $month = Month::fromNameOrCurrent((string)$month); + $currentUser = $request->user(); $yearPeriod = $yearPeriodRetriever->selected(); $carbonMonth = Carbon::create($yearPeriod->year, $month->toCarbonNumber()); $users = User::query() + ->where("id", "!=", $currentUser->id) ->orderBy("last_name") ->orderBy("first_name") ->get(); + $users->prepend($currentUser); + $calendar = $calendarGenerator->generate($carbonMonth); return inertia("Calendar", [ "calendar" => $calendar, - "currentMonth" => $month->value, + "current" => Month::current(), + "selected" => $month->value, "users" => UserResource::collection($users), "can" => [ "generateTimesheet" => $request->user()->can("generateTimesheet"), diff --git a/app/Infrastructure/Http/Resources/VacationRequestResource.php b/app/Infrastructure/Http/Resources/VacationRequestResource.php index 112d7a0..e7d5615 100644 --- a/app/Infrastructure/Http/Resources/VacationRequestResource.php +++ b/app/Infrastructure/Http/Resources/VacationRequestResource.php @@ -16,7 +16,7 @@ class VacationRequestResource extends JsonResource "id" => $this->id, "name" => $this->name, "user" => new UserResource($this->user), - "type" => $this->type->label(), + "type" => $this->type, "state" => $this->state, "from" => $this->from->toDisplayString(), "to" => $this->to->toDisplayString(), diff --git a/package-lock.json b/package-lock.json index eb8a495..929d686 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,9 @@ "vue-echarts": "^6.0.2", "vue-flatpickr-component": "^9.0.5", "vue-loader": "^17.0.0", - "vue-toastification": "^2.0.0-rc.5" + "vue-material-design-icons": "^5.0.0", + "vue-toastification": "^2.0.0-rc.5", + "vue3-popper": "^1.4.2" }, "devDependencies": { "eslint": "^8.10.0", @@ -1820,6 +1822,15 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", + "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@tailwindcss/forms": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.4.0.tgz", @@ -3794,6 +3805,11 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" + }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -8968,6 +8984,11 @@ "node": ">=8.9.0" } }, + "node_modules/vue-material-design-icons": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vue-material-design-icons/-/vue-material-design-icons-5.0.0.tgz", + "integrity": "sha512-lYSJFW/TyQqmg7MvUbEB8ua1mwWy/v8qve7QJuA/UWUAXC4/yVUdAm4pg/sM9+k5n7VLckBv6ucOROuGBsGPDQ==" + }, "node_modules/vue-style-loader": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", @@ -8990,6 +9011,21 @@ "vue": "^3.0.2" } }, + "node_modules/vue3-popper": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/vue3-popper/-/vue3-popper-1.4.2.tgz", + "integrity": "sha512-nc5vM//AJ8/DyNetjrrgkkLv7aKVdSsljvqlQ1tWhAV2lgA8tkn8xE6icDd0/kBt0Yo5Li8Pftf0H0C/hNmu1Q==", + "dependencies": { + "@popperjs/core": "^2.9.2", + "debounce": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "vue": "^3.2.20" + } + }, "node_modules/watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", @@ -10795,6 +10831,11 @@ "fastq": "^1.6.0" } }, + "@popperjs/core": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", + "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==" + }, "@tailwindcss/forms": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.4.0.tgz", @@ -12418,6 +12459,11 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==" }, + "debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" + }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -16166,6 +16212,11 @@ } } }, + "vue-material-design-icons": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vue-material-design-icons/-/vue-material-design-icons-5.0.0.tgz", + "integrity": "sha512-lYSJFW/TyQqmg7MvUbEB8ua1mwWy/v8qve7QJuA/UWUAXC4/yVUdAm4pg/sM9+k5n7VLckBv6ucOROuGBsGPDQ==" + }, "vue-style-loader": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", @@ -16188,6 +16239,15 @@ "integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==", "requires": {} }, + "vue3-popper": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/vue3-popper/-/vue3-popper-1.4.2.tgz", + "integrity": "sha512-nc5vM//AJ8/DyNetjrrgkkLv7aKVdSsljvqlQ1tWhAV2lgA8tkn8xE6icDd0/kBt0Yo5Li8Pftf0H0C/hNmu1Q==", + "requires": { + "@popperjs/core": "^2.9.2", + "debounce": "^1.2.1" + } + }, "watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", diff --git a/package.json b/package.json index 510146a..9aa5824 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,9 @@ "vue-echarts": "^6.0.2", "vue-flatpickr-component": "^9.0.5", "vue-loader": "^17.0.0", - "vue-toastification": "^2.0.0-rc.5" + "vue-material-design-icons": "^5.0.0", + "vue-toastification": "^2.0.0-rc.5", + "vue3-popper": "^1.4.2" }, "devDependencies": { "eslint": "^8.10.0", diff --git a/resources/js/Composables/vacationTypeInfo.js b/resources/js/Composables/vacationTypeInfo.js new file mode 100644 index 0000000..f2cdc6e --- /dev/null +++ b/resources/js/Composables/vacationTypeInfo.js @@ -0,0 +1,76 @@ +import WhiteBalanceSunnyIcon from 'vue-material-design-icons/WhiteBalanceSunny.vue' +import CommentAlertIcon from 'vue-material-design-icons/CommentAlert.vue' +import StarShootingIcon from 'vue-material-design-icons/StarShooting.vue' +import BabyCarriageIcon from 'vue-material-design-icons/BabyCarriage.vue' +import HumanMaleBoardIcon from 'vue-material-design-icons/HumanMaleBoard.vue' +import CurrencyUsdOffIcon from 'vue-material-design-icons/CurrencyUsdOff.vue' +import HandHeartOutlineIcon from 'vue-material-design-icons/HandHeartOutline.vue' +import CalendarCheckIcon from 'vue-material-design-icons/CalendarCheck.vue' +import MedicalBagIcon from 'vue-material-design-icons/MedicalBag.vue' + +const types = [ + { + text: 'Urlop wypoczynkowy', + value: 'vacation', + icon: WhiteBalanceSunnyIcon, + color: 'text-amber-500', + }, + { + text: 'Urlop na żądanie', + value: 'vacation_on_request', + icon: CommentAlertIcon, + color: 'text-slate-500', + }, + { + text: 'Urlop okolicznościowy', + value: 'special_vacation', + icon: StarShootingIcon, + color: 'text-orange-500', + }, + { + text: 'Opieka nad dzieckiem art 188 kp', + value: 'childcare_vacation', + icon: BabyCarriageIcon, + color: 'text-purple-500', + }, + { + text: 'Urlop szkoleniowy', + value: 'training_vacation', + icon: HumanMaleBoardIcon, + color: 'text-blumilk-500', + }, + { + text: 'Urlop bezpłatny', + value: 'unpaid_vacation', + icon: CurrencyUsdOffIcon, + color: 'text-emerald-500', + }, + { + text: 'Wolontariat', + value: 'volunteering_vacation', + icon: HandHeartOutlineIcon, + color: 'text-pink-500', + }, + { + text: 'Odbiór za święto', + value: 'time_in_lieu', + icon: CalendarCheckIcon, + color: 'text-stone-500', + }, + { + text: 'Zwolnienie lekarskie', + value: 'sick_vacation', + icon: MedicalBagIcon, + color: 'text-rose-500', + }, +] + +export function useVacationTypeInfo() { + const getTypes = () => types + const findType = value => types.find(type => type.value === value) + + return { + getTypes, + findType, + } +} diff --git a/resources/js/Pages/Calendar.vue b/resources/js/Pages/Calendar.vue index 4c0ade2..7e70980 100644 --- a/resources/js/Pages/Calendar.vue +++ b/resources/js/Pages/Calendar.vue @@ -2,10 +2,47 @@
-
+

Kalendarz urlopów

+
+ + + + + + + + + + + + + +
- +
- @@ -132,31 +123,36 @@ diff --git a/resources/js/Shared/VacationTypeCalendarIcon.vue b/resources/js/Shared/VacationTypeCalendarIcon.vue new file mode 100644 index 0000000..06f5d26 --- /dev/null +++ b/resources/js/Shared/VacationTypeCalendarIcon.vue @@ -0,0 +1,48 @@ + + +
- -
- - {{ selectedMonth.name }} {{ years.current }} - - -
- - - -
- - - {{ month.name }} - - - -
-
-
-
+
+
+ {{ selectedMonth.name }} {{ years.current }} +
{{ day.dayOfMonth }} @@ -87,7 +83,9 @@ v-for="user in users.data" :key="user.id" > -
+
-
+
{{ user.name }}
@@ -106,22 +106,13 @@ v-for="day in calendar" :key="day.dayOfMonth" class="border border-gray-300" - :class="{'bg-red-100': day.isWeekend || day.isHoliday, 'bg-blumilk-500': day.vacations.includes(user.id) }" + :class="{ 'bg-blumilk-25': day.isToday, 'bg-red-100': day.isWeekend || day.isHoliday}" >
- - - +