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/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..267f480 --- /dev/null +++ b/resources/js/Composables/vacationTypeInfo.js @@ -0,0 +1,139 @@ +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', + outline: { + icon: WhiteBalanceSunnyIcon, + background: 'bg-white', + foreground: 'text-amber-500', + }, + solid: { + icon: WhiteBalanceSunnyIcon, + color: 'text-amber-500', + }, + }, + { + text: 'Urlop na żądanie', + value: 'vacation_on_request', + outline: { + icon: CommentAlertIcon, + background: 'bg-white', + foreground: 'text-slate-500', + }, + solid: { + icon: CommentAlertIcon, + color: 'text-slate-500', + }, + }, + { + text: 'Urlop okolicznościowy', + value: 'special_vacation', + outline: { + icon: StarShootingIcon, + background: 'bg-white', + foreground: 'text-orange-500', + }, + solid: { + icon: StarShootingIcon, + color: 'text-orange-500', + }, + }, + { + text: 'Opieka nad dzieckiem art 188 kp', + value: 'childcare_vacation', + outline: { + icon: BabyCarriageIcon, + background: 'bg-white', + foreground: 'text-purple-500', + }, + solid: { + icon: BabyCarriageIcon, + color: 'text-purple-500', + }, + }, + { + text: 'Urlop szkoleniowy', + value: 'training_vacation', + outline: { + icon: HumanMaleBoardIcon, + background: 'bg-white', + foreground: 'text-blumilk-500', + }, + solid: { + icon: HumanMaleBoardIcon, + color: 'text-blumilk-500', + }, + }, + { + text: 'Urlop bezpłatny', + value: 'unpaid_vacation', + outline: { + icon: CurrencyUsdOffIcon, + background: 'bg-white', + foreground: 'text-emerald-500', + }, + solid: { + icon: CurrencyUsdOffIcon, + color: 'text-emerald-500', + }, + }, + { + text: 'Wolontariat', + value: 'volunteering_vacation', + outline: { + icon: HandHeartOutlineIcon, + background: 'bg-white', + foreground: 'text-pink-500', + }, + solid: { + icon: HandHeartOutlineIcon, + color: 'text-pink-500', + }, + }, + { + text: 'Odbiór za święto', + value: 'time_in_lieu', + outline: { + icon: CalendarCheckIcon, + background: 'bg-white', + foreground: 'text-stone-500', + }, + solid: { + icon: CalendarCheckIcon, + color: 'text-stone-500', + }, + }, + { + text: 'Zwolnienie lekarskie', + value: 'sick_vacation', + outline: { + icon: MedicalBagIcon, + background: 'bg-white', + foreground: 'text-rose-500', + }, + solid: { + 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 20ae66a..dfeee4e 100644 --- a/resources/js/Pages/Calendar.vue +++ b/resources/js/Pages/Calendar.vue @@ -117,16 +117,7 @@ v-if="day.vacations.includes(user.id)" class="flex justify-center items-center" > - - - + @@ -141,10 +132,12 @@ import {Menu, MenuButton, MenuItem, MenuItems} from '@headlessui/vue' import {CheckIcon, ChevronDownIcon} from '@heroicons/vue/solid' import {computed} from 'vue' import {useMonthInfo} from '@/Composables/monthInfo' +import VacationTypeCalendarIcon from '@/Shared/VacationTypeCalendarIcon' export default { name: 'VacationCalendar', components: { + VacationTypeCalendarIcon, Menu, MenuButton, MenuItem, diff --git a/resources/js/Pages/Dashboard.vue b/resources/js/Pages/Dashboard.vue index caced10..2f2793f 100644 --- a/resources/js/Pages/Dashboard.vue +++ b/resources/js/Pages/Dashboard.vue @@ -119,7 +119,7 @@ class="hover:underline focus:outline-none" > - Wniosek o {{ request.type.toLowerCase() }} + Wniosek o {{ findType(request.type).text.toLowerCase() }} [{{ request.name }}] @@ -185,7 +185,7 @@ class="hover:underline focus:outline-none" > - Wniosek o {{ request.type.toLowerCase() }} + Wniosek o {{ findType(request.type).text.toLowerCase() }} [{{ request.name }}] @@ -302,6 +302,7 @@ import {computed} from 'vue' import {usePage} from '@inertiajs/inertia-vue3' import Status from '@/Shared/Status' import VacationChart from '@/Shared/VacationChart' +import {useVacationTypeInfo} from '@/Composables/vacationTypeInfo' export default { name: 'DashboardPage', @@ -335,8 +336,11 @@ export default { setup() { const user = computed(() => usePage().props.value.auth.user) + const { findType } = useVacationTypeInfo() + return { user, + findType, } }, } diff --git a/resources/js/Pages/VacationRequest/Index.vue b/resources/js/Pages/VacationRequest/Index.vue index 600dec2..5b7d0bc 100644 --- a/resources/js/Pages/VacationRequest/Index.vue +++ b/resources/js/Pages/VacationRequest/Index.vue @@ -1,10 +1,10 @@ @@ -249,10 +249,12 @@ import {PaperClipIcon} from '@heroicons/vue/outline' import Activity from '@/Shared/Activity' import Status from '@/Shared/Status' +import VacationType from '@/Shared/VacationType' export default { name: 'VacationRequestShow', components: { + VacationType, Activity, PaperClipIcon, Status, diff --git a/resources/js/Shared/VacationType.vue b/resources/js/Shared/VacationType.vue new file mode 100644 index 0000000..4bc7162 --- /dev/null +++ b/resources/js/Shared/VacationType.vue @@ -0,0 +1,38 @@ + + + diff --git a/resources/js/Shared/VacationTypeCalendarIcon.vue b/resources/js/Shared/VacationTypeCalendarIcon.vue new file mode 100644 index 0000000..0d92605 --- /dev/null +++ b/resources/js/Shared/VacationTypeCalendarIcon.vue @@ -0,0 +1,51 @@ + + +