Skip to content

Commit 051768d

Browse files
committed
Filter appointments by animal type
1 parent 1821df7 commit 051768d

File tree

6 files changed

+57
-21
lines changed

6 files changed

+57
-21
lines changed

app/Http/Controllers/AppointmentController.php

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,34 @@
44

55
use App\Http\Requests\ListAppointmentsRequest;
66
use App\Http\Resources\AppointmentResource;
7+
use App\Models\Animal;
78
use App\Models\Appointment;
9+
use Illuminate\Database\Eloquent\Builder;
810
use Illuminate\Http\Request;
911
use Inertia\Inertia;
1012

1113
class AppointmentController extends Controller
1214
{
1315
public function index(ListAppointmentsRequest $request)
1416
{
15-
$query = Appointment::with([
16-
'animal',
17-
'animal.client',
18-
'medic',
19-
])
20-
->orderBy('preferred_date', 'desc');
17+
$appointments = Appointment::with(['animal', 'animal.client', 'medic'])
18+
->orderBy('preferred_date', 'desc')
19+
// Date filters
20+
->when($request->start, fn (Builder $query) => $query->where('preferred_date', '>=', $request->start))
21+
->when($request->end, fn (Builder $query) => $query->where('preferred_date', '<=', $request->end))
22+
// Animal type filter
23+
->when($request->animalTypes, function (Builder $query) use ($request) {
24+
$query->whereHas('animal', fn (Builder $animal) => $animal->whereIn('type', $request->animalTypes));
25+
})
26+
// -------
27+
->paginate(15);
2128

22-
if ($request->start) {
23-
$query->where('preferred_date', '>=', $request->start);
24-
}
25-
if ($request->end) {
26-
$query->where('preferred_date', '<=', $request->end);
27-
}
28-
29-
$appointments = $query->paginate(15);
29+
// TODO Cache animal types
30+
$animalTypes = Animal::types(approved: false);
3031

3132
return Inertia::render('dashboard/Appointments', [
3233
'appointments' => AppointmentResource::collection($appointments),
34+
'animalTypes' => $animalTypes,
3335
]);
3436
}
3537

app/Http/Controllers/PublicController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ public function home()
1616
{
1717
return Inertia::render('client/ScheduleAppointment', [
1818
// TODO Cache animal types
19-
// TODO Only show approved (aka assigned appointments) animals
20-
'animalTypes' => Animal::distinct('type')->orderBy('type')->pluck('type'),
19+
'animalTypes' => Animal::types(approved: true),
2120
'timeOfDay' => TimeOfDay::selectable(),
2221
]);
2322
}

app/Http/Requests/ListAppointmentsRequest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ public function rules(): array
1515
{
1616
return [
1717
// Filters
18-
'start' => ['date'], // Date
19-
'end' => ['date'], // Date
18+
'start' => ['date'], // Date
19+
'end' => ['date'], // Date
20+
'animalTypes' => ['array'], // Animal types
2021
];
2122
}
2223
}

app/Models/Animal.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use Illuminate\Database\Eloquent\Model;
77
use Illuminate\Database\Eloquent\Relations\BelongsTo;
88
use Illuminate\Database\Eloquent\Relations\HasMany;
9+
use Illuminate\Database\Query\Builder;
10+
use Illuminate\Support\Facades\DB;
911

1012
class Animal extends Model
1113
{
@@ -25,4 +27,15 @@ public function appointments(): HasMany
2527
{
2628
return $this->hasMany(Appointment::class);
2729
}
30+
31+
public static function types(bool $approved): array
32+
{
33+
return DB::table('animals')
34+
->join('appointments', 'animals.id', '=', 'appointments.animal_id')
35+
->when($approved, fn (Builder $query) => $query->whereNotNull('appointments.medic_id'))
36+
->select('animals.type')
37+
->distinct()
38+
->pluck('animals.type')
39+
->toArray();
40+
}
2841
}

app/Models/Appointment.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace App\Models;
44

55
use App\TimeOfDay;
6+
use Illuminate\Database\Eloquent\Attributes\Scope;
7+
use Illuminate\Database\Eloquent\Builder;
68
use Illuminate\Database\Eloquent\Casts\Attribute;
79
use Illuminate\Database\Eloquent\Factories\HasFactory;
810
use Illuminate\Database\Eloquent\Model;
@@ -51,6 +53,12 @@ public function client(): HasOneThrough
5153
);
5254
}
5355

56+
#[Scope]
57+
protected function assigned(Builder $query): Builder
58+
{
59+
return $query->whereNotNull('medic_id');
60+
}
61+
5462
public function preferredDateFormatted(): Attribute
5563
{
5664
return Attribute::make(

resources/js/pages/dashboard/Appointments.vue

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface AppointmentsDataManager {
1212
start: CalendarDate | undefined;
1313
end: CalendarDate | undefined;
1414
};
15+
animalTypes: string[] | undefined;
1516
};
1617
pagination: {
1718
pageIndex: number;
@@ -42,6 +43,7 @@ const dataManager = ref<AppointmentsDataManager>({
4243
start: params.start ? parseDate(params.start as string) : undefined,
4344
end: params.end ? parseDate(params.end as string) : undefined,
4445
},
46+
animalTypes: params?.animalTypes,
4547
},
4648
pagination: {
4749
pageIndex: parseInt(meta.value.current_page),
@@ -58,11 +60,12 @@ watch(
5860
);
5961
6062
const urlFilters = computed(() => {
61-
const preferredDate = dataManager.value.filters.preferredDate;
63+
const { preferredDate, animalTypes } = dataManager.value.filters;
6264
6365
return {
6466
start: preferredDate?.start?.toString(),
6567
end: preferredDate?.end?.toString(),
68+
animalTypes: animalTypes,
6669
};
6770
});
6871
@@ -95,10 +98,10 @@ function updateData() {
9598
<UCard>
9699
<div class="space-y-4">
97100
<!-- Filters -->
98-
<div class="flex items-center gap-2">
101+
<div class="flex items-center gap-3">
99102
<!-- Date filter -->
100103
<UPopover>
101-
<UButton variant="subtle" icon="i-lucide-calendar" size="sm">
104+
<UButton variant="soft" icon="i-lucide-calendar" size="sm">
102105
<template v-if="datesFilter.start">
103106
{{ formatDate(datesFilter.start) }}
104107

@@ -118,6 +121,16 @@ function updateData() {
118121
</div>
119122
</template>
120123
</UPopover>
124+
125+
<!-- Animal type list -->
126+
<UInputMenu
127+
v-model="dataManager.filters.animalTypes"
128+
:items="page.props.animalTypes as string[]"
129+
variant="soft"
130+
size="sm"
131+
multiple
132+
placeholder="Select animal types"
133+
/>
121134
</div>
122135

123136
<USeparator />

0 commit comments

Comments
 (0)