From 1c632d673e85524c7b728a7a2a4e3ef6bf7839f5 Mon Sep 17 00:00:00 2001 From: Iosif Chatzimichail Date: Thu, 28 Nov 2024 23:56:34 +0200 Subject: [PATCH] Add tests and advanced availability support --- .../components/availability-dates.blade.php | 50 ++++++++++------ .../Traits/HandlesAvailabilityQueries.php | 4 +- tests/Livewire/AvailabilityResultsTest.php | 2 +- tests/Livewire/AvailabilitySearchTest.php | 57 ++++++++++++++++++- 4 files changed, 93 insertions(+), 20 deletions(-) diff --git a/resources/views/livewire/components/availability-dates.blade.php b/resources/views/livewire/components/availability-dates.blade.php index 1278838..0e58dd6 100644 --- a/resources/views/livewire/components/availability-dates.blade.php +++ b/resources/views/livewire/components/availability-dates.blade.php @@ -52,6 +52,8 @@ class="absolute inset-y-0 end-0 flex z-1 items-center pe-3.5 cursor-pointer" Alpine.data('datepicker', () => ({ mode: $wire.calendar, dates: $wire.data.dates, + advanced: $wire.advanced, + advancedSelected: $wire.entangle('data.advanced'), calendar: null, minPeriod: {{ config('resrv-config.minimum_reservation_period_in_days', 0) }}, maxPeriod: {{ config('resrv-config.maximum_reservation_period_in_days', 30) }}, @@ -67,8 +69,23 @@ class="absolute inset-y-0 end-0 flex z-1 items-center pe-3.5 cursor-pointer" const minDate = dayjs().add({{ config('resrv-config.minimum_days_before') }}, 'day').format('YYYY-MM-DD'); if (this.showAvailaiblityOnCalendar !== false) { - this.availabilityCalendar = await $wire.availabilityCalendar(); + if (this.advanced !== false && this.advancedSelected === null) { + this.availabilityCalendar = []; + } else { + this.availabilityCalendar = await $wire.availabilityCalendar(); + } } + + this.$watch('advancedSelected', async (value, oldValue) => { + if (this.showAvailaiblityOnCalendar !== false && value !== null) { + this.availabilityCalendar = await $wire.availabilityCalendar(); + } else if (this.showAvailaiblityOnCalendar !== false && value === null) { + this.availabilityCalendar = []; + } + this.calendar.update({ + dates: false, + }); + }); this.calendar = new window.calendar(this.$refs.dateInput, { type: this.mode === 'range' ? 'multiple' : 'default', @@ -83,7 +100,7 @@ class="absolute inset-y-0 end-0 flex z-1 items-center pe-3.5 cursor-pointer" onCreateDateEls: (self, dateEl) => { if (this.showAvailaiblityOnCalendar !== false) { - this.addPriceToEachDate(self, dateEl); + this.addPriceToEachDate(dateEl); } if (this.disabledDays !== false) { this.disableDays(dateEl); @@ -111,8 +128,8 @@ class="absolute inset-y-0 end-0 flex z-1 items-center pe-3.5 cursor-pointer" this.dateChanged(self.context.selectedDates); }, - onUpdate(self, event) { - self.set({ selectedDates: [] }); + onUpdate(self) { + //self.set({ selectedDates: [] }); } }); @@ -154,20 +171,21 @@ class="absolute inset-y-0 end-0 flex z-1 items-center pe-3.5 cursor-pointer" } }, - addPriceToEachDate(self, dateEl) { + addPriceToEachDate(dateEl) { const button = dateEl.querySelector('button'); const date = dateEl.dataset.vcDate; - if (this.availabilityCalendar[date] === undefined) return; - if (this.availabilityCalendar[date]?.available === 0) { - button.style.cssText = 'cursor: default; opacity: 0.5; text-decoration: line-through;'; - button.onclick = (event) => event.stopPropagation(); - return; - } - button.insertAdjacentHTML( - 'beforeend', - `{{ config('resrv-config.currency_symbol') }}${Math.round(this.availabilityCalendar[date]?.price)}` - ); + if (Object.values(this.availabilityCalendar).length > 0) { + if (this.availabilityCalendar[date] === undefined || this.availabilityCalendar[date]?.available === 0) { + button.style.cssText = 'cursor: default; opacity: 0.5; text-decoration: line-through;'; + button.onclick = (event) => event.stopPropagation(); + return; + } + button.insertAdjacentHTML( + 'beforeend', + `{{ config('resrv-config.currency_symbol') }}${Math.round(this.availabilityCalendar[date]?.price)}` + ); + } }, disableDays(dateEl) { @@ -205,6 +223,7 @@ class="absolute inset-y-0 end-0 flex z-1 items-center pe-3.5 cursor-pointer" }, resetDates() { + this.calendar.set({ selectedDates: [] }); this.calendar.update({ dates: true, }); @@ -212,7 +231,6 @@ class="absolute inset-y-0 end-0 flex z-1 items-center pe-3.5 cursor-pointer" $wire.clearDates(); $dispatch('availability-search-cleared'); }, - })); @endscript \ No newline at end of file diff --git a/src/Livewire/Traits/HandlesAvailabilityQueries.php b/src/Livewire/Traits/HandlesAvailabilityQueries.php index 254c3b6..2ece8e8 100644 --- a/src/Livewire/Traits/HandlesAvailabilityQueries.php +++ b/src/Livewire/Traits/HandlesAvailabilityQueries.php @@ -126,9 +126,9 @@ public function getAvailabilityCalendar(): array return app(Availability::class) ->where('statamic_id', $entry) - ->where('date', '>=', now()) + ->where('date', '>=', now()->startOfDay()) ->when($this->advanced && $this->data->advanced, function ($query) { - return $query->where('advanced', $this->data->advanced); + return $query->where('property', $this->data->advanced); }) ->get(['date', 'available', 'price', 'property']) ->groupBy('date') diff --git a/tests/Livewire/AvailabilityResultsTest.php b/tests/Livewire/AvailabilityResultsTest.php index a6c079a..c202d03 100644 --- a/tests/Livewire/AvailabilityResultsTest.php +++ b/tests/Livewire/AvailabilityResultsTest.php @@ -29,7 +29,7 @@ class AvailabilityResultsTest extends TestCase public $option; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->date = now()->add(1, 'day')->setTime(12, 0, 0); diff --git a/tests/Livewire/AvailabilitySearchTest.php b/tests/Livewire/AvailabilitySearchTest.php index 5677fe0..b5eb402 100644 --- a/tests/Livewire/AvailabilitySearchTest.php +++ b/tests/Livewire/AvailabilitySearchTest.php @@ -5,17 +5,27 @@ use Illuminate\Support\Facades\Config; use Livewire\Livewire; use Reach\StatamicResrv\Livewire\AvailabilitySearch; +use Reach\StatamicResrv\Tests\CreatesEntries; use Reach\StatamicResrv\Tests\TestCase; use Statamic\Facades; class AvailabilitySearchTest extends TestCase { + use CreatesEntries; + public $date; - public function setUp(): void + public $entries; + + public $advancedEntries; + + protected function setUp(): void { parent::setUp(); $this->date = now()->setTime(12, 0, 0); + $this->entries = $this->createEntries(); + $this->advancedEntries = $this->createAdvancedEntries(); + $this->travelTo(today()->setHour(12)); } public function test_renders_successfully() @@ -346,4 +356,49 @@ public function test_can_set_a_custom_value() ->set('data.customer.adults', 2) ->assertSet('data.customer', ['adults' => 2]); } + + // Test availability calendar returns data when enabled + public function test_availability_calendar_returns_data_when_enabled() + { + $component = Livewire::test(AvailabilitySearch::class, [ + 'entry' => $this->entries->first()->id(), + 'showAvailaiblityOnCalendar' => true, + ]) + ->assertSet('showAvailaiblityOnCalendar', true) + ->call('availabilityCalendar'); + + $calendar = $component->effects['returns'][0]; + + $key = $this->date->format('Y-m-d').' 00:00:00'; + + $this->assertIsArray($calendar); + $this->assertArrayHasKey($key, $calendar); + $this->assertEquals(50, $calendar[$key]['price']); + $this->assertEquals(1, $calendar[$key]['available']); + } + + // Test availability calendar returns data when enabled with advanced availability + public function test_availability_calendar_with_advanced_availability() + { + $component = Livewire::test(AvailabilitySearch::class, [ + 'entry' => $this->advancedEntries->first()->id(), + 'showAvailaiblityOnCalendar' => true, + ]) + ->assertSet('showAvailaiblityOnCalendar', true) + ->set('data.dates', [ + 'date_start' => $this->date, + 'date_end' => $this->date->copy()->add(1, 'day'), + ]) + ->set('data.advanced', 'test') + ->call('availabilityCalendar'); + + $calendar = $component->effects['returns'][0]; + + $key = $this->date->format('Y-m-d').' 00:00:00'; + + $this->assertIsArray($calendar); + $this->assertArrayHasKey($key, $calendar); + $this->assertEquals(50, $calendar[$key]['price']); + $this->assertEquals(1, $calendar[$key]['available']); + } }