From d3d6e3080cede45440cbbee26e75ea309fc9b2a7 Mon Sep 17 00:00:00 2001 From: Adrian Hopek Date: Mon, 14 Feb 2022 13:42:49 +0100 Subject: [PATCH] #22 - wip --- app/Domain/CalendarGenerator.php | 76 +++++++++++ .../VacationCalendarController.php | 49 ++----- resources/js/Composables/statusInfo.js | 128 ++++++++++++++++++ resources/js/Pages/Calendar.vue | 17 ++- resources/js/Pages/VacationRequest/Show.vue | 8 ++ resources/js/Shared/Activity.vue | 66 +-------- resources/js/Shared/Status.vue | 58 +------- 7 files changed, 239 insertions(+), 163 deletions(-) create mode 100644 app/Domain/CalendarGenerator.php create mode 100644 resources/js/Composables/statusInfo.js diff --git a/app/Domain/CalendarGenerator.php b/app/Domain/CalendarGenerator.php new file mode 100644 index 0000000..4ecb2ba --- /dev/null +++ b/app/Domain/CalendarGenerator.php @@ -0,0 +1,76 @@ +year, $this->monthNameToNumber($month)); + $period = CarbonPeriod::create($date->startOfMonth(), $date->endOfMonth()); + $holidays = $yearPeriod->holidays()->pluck("date"); + + return $this->generateCalendar($period, $holidays); + } + + protected function monthNameToNumber($name): int + { + return match ($name) { + default => CarbonInterface::JANUARY, + "february" => CarbonInterface::FEBRUARY, + "march" => CarbonInterface::MARCH, + "april" => CarbonInterface::APRIL, + "may" => CarbonInterface::MAY, + "june" => CarbonInterface::JUNE, + "july" => CarbonInterface::JULY, + "august" => CarbonInterface::AUGUST, + "september" => CarbonInterface::SEPTEMBER, + "october" => CarbonInterface::OCTOBER, + "november" => CarbonInterface::NOVEMBER, + "december" => CarbonInterface::DECEMBER, + }; + } + + protected function generateCalendar(CarbonPeriod $period, Collection $holidays): array + { + $calendar = []; + + foreach ($period as $day) { + $calendar[] = [ + "date" => $day->toDateString(), + "dayOfMonth" => $day->translatedFormat("j"), + "dayOfWeek" => $day->translatedFormat("D"), + "isToday" => $day->isToday(), + "isWeekend" => $day->isWeekend(), + "isHoliday" => $holidays->contains($day), + "vacations" => $this->getVacationsForDay($day), + ]; + } + + return $calendar; + } + + protected function getVacationsForDay(CarbonInterface $day): Collection + { + return Vacation::query() + ->whereDate("date", $day) + ->whereRelation("vacationRequest", "state", VacationRequestState::APPROVED->value) + ->pluck("user_id"); + } +} diff --git a/app/Infrastructure/Http/Controllers/VacationCalendarController.php b/app/Infrastructure/Http/Controllers/VacationCalendarController.php index 1b8ef75..c19c00d 100644 --- a/app/Infrastructure/Http/Controllers/VacationCalendarController.php +++ b/app/Infrastructure/Http/Controllers/VacationCalendarController.php @@ -4,63 +4,36 @@ declare(strict_types=1); namespace Toby\Infrastructure\Http\Controllers; -use Carbon\CarbonImmutable; use Carbon\CarbonInterface; -use Carbon\CarbonPeriod; use Illuminate\Http\Request; +use Illuminate\Support\Carbon; +use Illuminate\Support\Str; use Inertia\Response; -use Toby\Domain\Enums\VacationRequestState; +use Toby\Domain\CalendarGenerator; use Toby\Eloquent\Helpers\YearPeriodRetriever; use Toby\Eloquent\Models\User; -use Toby\Eloquent\Models\Vacation; use Toby\Infrastructure\Http\Resources\UserResource; class VacationCalendarController extends Controller { - public function index(Request $request, YearPeriodRetriever $yearPeriodRetriever): Response - { - $month = $request->query("month", "february"); + public function index( + Request $request, + YearPeriodRetriever $yearPeriodRetriever, + CalendarGenerator $calendarGenerator, + ): Response { + $month = Str::lower($request->query("month", Carbon::now()->englishMonth)); $yearPeriod = $yearPeriodRetriever->selected(); - $date = CarbonImmutable::create($yearPeriod->year, $this->monthNameToNumber($month)); - $period = CarbonPeriod::create($date->startOfMonth(), $date->endOfMonth()); - $holidays = $yearPeriod->holidays()->pluck("date"); $users = User::query() - ->with([ - "vacations" => fn($query) => $query - ->whereBetween("date", [$period->start, $period->end]) - ->whereRelation("vacationRequest", "state", VacationRequestState::APPROVED->value), - ]) ->orderBy("last_name") ->orderBy("first_name") ->get(); - $calendar = []; - - foreach ($period as $day) { - $calendar[] = [ - "date" => $day->toDateString(), - "dayOfMonth" => $day->translatedFormat("j"), - "dayOfWeek" => $day->translatedFormat("D"), - "isToday" => $day->isToday(), - "isWeekend" => $day->isWeekend(), - "isHoliday" => $holidays->contains($day), - ]; - } - - $userVacations = []; - - /** @var User $user */ - foreach ($users as $user) { - $userVacations[] = [ - "user" => new UserResource($user), - "vacations" => $user->vacations->map(fn(Vacation $vacation) => $vacation->date->toDateString()), - ]; - } + $calendar = $calendarGenerator->generate($yearPeriod, $month); return inertia("Calendar", [ "calendar" => $calendar, "currentMonth" => $month, - "userVacations" => $userVacations, + "users" => UserResource::collection($users), ]); } diff --git a/resources/js/Composables/statusInfo.js b/resources/js/Composables/statusInfo.js new file mode 100644 index 0000000..a56ed1e --- /dev/null +++ b/resources/js/Composables/statusInfo.js @@ -0,0 +1,128 @@ +import { + CheckIcon as OutlineCheckIcon, + ClockIcon as OutlineClockIcon, + DocumentTextIcon as OutlineDocumentTextIcon, + ThumbDownIcon as OutlineThumbDownIcon, + ThumbUpIcon as OutlineThumbUpIcon, + XIcon as OutlineXIcon, +} from '@heroicons/vue/outline' + +import { + CheckIcon as SolidCheckIcon, + ClockIcon as SolidClockIcon, + DocumentTextIcon as SolidDocumentTextIcon, + ThumbDownIcon as SolidThumbDownIcon, + ThumbUpIcon as SolidThumbUpIcon, + XIcon as SolidXIcon, +} from '@heroicons/vue/solid' + +const statuses = [ + { + text: 'Utworzony', + value: 'created', + outline: { + icon: OutlineDocumentTextIcon, + foreground: 'text-white', + background: 'bg-gray-400', + }, + solid: { + icon: SolidDocumentTextIcon, + color: 'text-gray-400', + }, + }, + { + text: 'Czeka na akceptację od technicznego', + value: 'waiting_for_technical', + outline: { + icon: OutlineClockIcon, + foreground: 'text-white', + background: 'bg-amber-400', + }, + solid: { + icon: SolidClockIcon, + color: 'text-amber-400', + }, + }, + { + text: 'Czeka na akceptację od administracyjnego', + value: 'waiting_for_administrative', + outline: { + icon: OutlineClockIcon, + foreground: 'text-white', + background: 'bg-amber-400', + }, + solid: { + icon: SolidClockIcon, + color: 'text-amber-400', + }, + }, + { + text: 'Odrzucony', + value: 'rejected', + outline: { + icon: OutlineThumbDownIcon, + foreground: 'text-white', + background: 'bg-rose-600', + }, + solid: { + icon: SolidThumbDownIcon, + color: 'text-rose-600', + }, + }, + { + text: 'Zaakceptowany przez technicznego', + value: 'accepted_by_technical', + outline: { + icon: OutlineThumbUpIcon, + foreground: 'text-white', + background: 'bg-green-500', + }, + solid: { + icon: SolidThumbUpIcon, + color: 'text-green-500', + }, + }, + { + text: 'Zaakceptowany przez administracyjnego', + value: 'accepted_by_administrative', + outline: { + icon: OutlineThumbUpIcon, + foreground: 'text-white', + background: 'bg-green-500', + }, + solid: { + icon: SolidThumbUpIcon, + color: 'text-green-500', + }, + }, + { + text: 'Zatwierdzony', + value: 'approved', + outline: { + icon: OutlineCheckIcon, + foreground: 'text-white', + background: 'bg-blumilk-500', + }, + solid: { + icon: SolidCheckIcon, + color: 'text-blumilk-500', + }, + }, + { + text: 'Anulowany', + value: 'canceled', + outline: { + icon: OutlineXIcon, + foreground: 'text-white', + background: 'bg-gray-900', + }, + solid: { + icon: SolidXIcon, + color: 'text-gray-900', + }, + }, +] + +export function useStatusInfo(status) { + return statuses.find(statusInfo => statusInfo.value === status) +} \ No newline at end of file diff --git a/resources/js/Pages/Calendar.vue b/resources/js/Pages/Calendar.vue index 6511e6b..ca0c8e5 100644 --- a/resources/js/Pages/Calendar.vue +++ b/resources/js/Pages/Calendar.vue @@ -62,7 +62,7 @@ v-for="day in calendar" :key="day.dayOfMonth" class="border border-gray-300 text-lg font-semibold text-gray-900 py-4 px-2" - :class="{ 'text-blumilk-600 bg-blumilk-25 font-black': day.isToday}" + :class="{ 'text-blumilk-600 bg-blumilk-25 font-black': day.isToday }" >
{{ day.dayOfMonth }} @@ -75,21 +75,20 @@
- {{ userVacation.user.name }} + {{ user.name }}
@@ -98,10 +97,10 @@ v-for="day in calendar" :key="day.dayOfMonth" class="border border-gray-300" - :class="{'bg-gray-100': day.isWeekend, 'bg-green-100': day.isHoliday, 'bg-blumilk-500': userVacation.vacations.includes(day.date) }" + :class="{'bg-red-100': day.isWeekend || day.isHoliday, 'bg-blumilk-500': day.vacations.includes(user.id) }" >
null, }, diff --git a/resources/js/Pages/VacationRequest/Show.vue b/resources/js/Pages/VacationRequest/Show.vue index 3f1a28e..1c4f519 100644 --- a/resources/js/Pages/VacationRequest/Show.vue +++ b/resources/js/Pages/VacationRequest/Show.vue @@ -18,6 +18,14 @@ {{ request.name }}
+
+
+ Pracownik +
+
+ {{ request.user.name }} +
+
Rodzaj urlopu diff --git a/resources/js/Shared/Activity.vue b/resources/js/Shared/Activity.vue index 8b74fc2..050889c 100644 --- a/resources/js/Shared/Activity.vue +++ b/resources/js/Shared/Activity.vue @@ -6,9 +6,9 @@ />
- + @@ -32,8 +32,8 @@