From 34fa9399fb753ef35baa8ffb98b2acd35a7527a9 Mon Sep 17 00:00:00 2001 From: bernardhanna Date: Mon, 14 Sep 2026 12:12:10 +0100 Subject: [PATCH] List open online activities that are already under way. The calendar required a start date in the current month or later, so a long-running activity that began earlier was hidden even though it was still open to participants. Two such activities run into 2027. Gate the list on the end date instead, and treat an activity that has already begun as starting now so it appears under the current month rather than adding a past month to the filter. Co-authored-by: Cursor --- app/Livewire/OnlineCalendar.php | 43 ++++++++++---- tests/Feature/OnlineEventsWorkflowTest.php | 65 ++++++++++++++++++++++ 2 files changed, 97 insertions(+), 11 deletions(-) diff --git a/app/Livewire/OnlineCalendar.php b/app/Livewire/OnlineCalendar.php index 57e65d30f..1e9a7c03d 100644 --- a/app/Livewire/OnlineCalendar.php +++ b/app/Livewire/OnlineCalendar.php @@ -33,16 +33,14 @@ public function mount() ->orderBy('start_date') ->get(['start_date']) ->groupBy(function ($event) { - $date = Carbon::parse($event->start_date); - - return $date->month.'/'.$date->year; + return $this->effectiveStart($event->start_date)->format('n/Y'); }) ->map(function ($group, $id) { - $date = Carbon::parse($group->first()->start_date); + [$month, $year] = explode('/', $id); return [ 'id' => $id, - 'name' => $date->format('F').' '.$date->year, + 'name' => Carbon::createFromDate((int) $year, (int) $month, 1)->format('F Y'), ]; }) ->values() @@ -68,11 +66,22 @@ public function render() $this->selectedMonth = (int) ($parts[0] ?: $this->selectedMonth); $this->selectedYear = (int) ($parts[1] ?? $this->selectedYear); - $query->whereMonth('start_date', $this->selectedMonth) - ->whereYear('start_date', $this->selectedYear); + $monthStart = Carbon::createFromDate($this->selectedYear, $this->selectedMonth, 1)->startOfMonth(); + + $query->where(function ($monthQuery) use ($monthStart) { + $monthQuery->whereBetween('start_date', [$monthStart, $monthStart->copy()->endOfMonth()]); + + if ($monthStart->isSameMonth(Carbon::now())) { + $monthQuery->orWhere('start_date', '<', $monthStart); + } + }); } - $events = $query->get(); + $events = $query->get() + ->sortBy(function ($event) { + return $this->effectiveStart($event->start_date)->getTimestamp(); + }) + ->values(); $events->each(function ($event) { $event->title = str_limit($event->title, 50); @@ -124,12 +133,24 @@ public function render() private function baseQuery() { + // Only the end date gates the list: an activity that began earlier but has not + // finished is still open to participants. return Event::where([ 'activity_type' => 'open-online', 'status' => 'APPROVED', - ]) - ->where('start_date', '>=', Carbon::now()->firstOfMonth()) - ->where('end_date', '>=', Carbon::now()); + ])->where('end_date', '>=', Carbon::now()); + } + + /** + * Activities already under way are listed under the current month rather than the + * month they originally started in, which may be long past. + */ + private function effectiveStart($startDate): Carbon + { + $start = Carbon::parse($startDate); + $currentMonth = Carbon::now()->firstOfMonth(); + + return $start->lessThan($currentMonth) ? $currentMonth : $start; } private function eventMatchesLanguage($event, string $selectedLanguage): bool diff --git a/tests/Feature/OnlineEventsWorkflowTest.php b/tests/Feature/OnlineEventsWorkflowTest.php index 53c764c09..4d366262c 100644 --- a/tests/Feature/OnlineEventsWorkflowTest.php +++ b/tests/Feature/OnlineEventsWorkflowTest.php @@ -317,6 +317,71 @@ public function featured_activities_month_filter_only_shows_events_for_selected_ ->assertDontSee($novemberEvent->title); } + #[Test] + public function featured_activities_page_lists_activities_already_under_way(): void + { + $this->seed('RolesAndPermissionsSeeder'); + + $ongoing = \App\Event::factory()->create([ + 'start_date' => Carbon::now()->subMonths(4), + 'end_date' => Carbon::now()->addMonths(6), + 'status' => 'APPROVED', + 'activity_type' => 'open-online', + 'highlighted_status' => 'NONE', + 'language' => ['en'], + 'title' => 'Still Running Open Online Activity', + ]); + + $finished = \App\Event::factory()->create([ + 'start_date' => Carbon::now()->subMonths(4), + 'end_date' => Carbon::now()->subMonth(), + 'status' => 'APPROVED', + 'activity_type' => 'open-online', + 'highlighted_status' => 'NONE', + 'language' => ['en'], + 'title' => 'Already Finished Open Online Activity', + ]); + + $this->get('/featured-activities') + ->assertStatus(200) + ->assertSee($ongoing->title) + ->assertDontSee($finished->title); + } + + #[Test] + public function activities_already_under_way_are_listed_under_the_current_month(): void + { + $this->seed('RolesAndPermissionsSeeder'); + + $startedFourMonthsAgo = Carbon::now()->subMonths(4); + + $ongoing = \App\Event::factory()->create([ + 'start_date' => $startedFourMonthsAgo, + 'end_date' => Carbon::now()->addMonths(6), + 'status' => 'APPROVED', + 'activity_type' => 'open-online', + 'highlighted_status' => 'NONE', + 'language' => ['en'], + 'title' => 'Ongoing Grouped Under Current Month', + ]); + + $now = Carbon::now(); + + \Livewire\Livewire::test(\App\Livewire\OnlineCalendar::class) + ->set('selectedDate', $now->month.'/'.$now->year) + ->assertSee($ongoing->title); + + $monthIds = collect(\Livewire\Livewire::test(\App\Livewire\OnlineCalendar::class)->get('months')) + ->pluck('id'); + + $this->assertContains($now->month.'/'.$now->year, $monthIds); + $this->assertNotContains( + $startedFourMonthsAgo->month.'/'.$startedFourMonthsAgo->year, + $monthIds, + 'The month filter should not offer a past month just because an ongoing activity started then.' + ); + } + #[Test] public function promoted_event_creates_notification_for_administrators(): void {