Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget as BaseWidget;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\HtmlString;

Expand All @@ -30,6 +31,10 @@ class ReferToShelterWidget extends BaseWidget

public function table(Table $table): Table
{
$attributes = ShelterAttribute::query()
->with('shelterVariables')
->get();

return $table
->query(
fn () => Shelter::query()
Expand Down Expand Up @@ -76,6 +81,14 @@ public function table(Table $table): Table
SelectFilter::make('location')
->relationship('location', 'name'),

...$attributes->map(
fn (ShelterAttribute $shelterAttribute) => SelectFilter::make("attribute.{$shelterAttribute->id}")
->query(fn (Builder $query, array $state) => $query->whereHasShelterVariables($state))
->options($shelterAttribute->shelterVariables->pluck('name', 'id'))
->label($shelterAttribute->name)
->multiple()
),

], FiltersLayout::AboveContent)
->paginated(false);
}
Expand Down
15 changes: 15 additions & 0 deletions app/Forms/Components/RadioCard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\Forms\Components;

use Closure;
use Filament\Forms\Components\Radio;

class RadioCard extends Radio
{
protected string $view = 'forms.components.radio-card';

protected string | Closure | null $gridDirection = 'row';
}
68 changes: 63 additions & 5 deletions app/Livewire/RequestPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,32 @@
use App\Contracts\TranslatablePage;
use App\Enums\Gender;
use App\Enums\SpecialNeed;
use App\Forms\Components\RadioCard;
use App\Forms\Components\TableRepeater;
use App\Models\Country;
use App\Models\Location;
use App\Models\Request;
use App\Models\Shelter;
use App\Models\ShelterAttribute;
use Awcodes\TableRepeater\Header;
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
use DanHarrin\LivewireRateLimiting\WithRateLimiting;
use Filament\Actions\Action;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Radio;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\View;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Notifications\Notification;
use Filament\Pages\Concerns\InteractsWithFormActions;
use Filament\Pages\SimplePage;
use Filament\Support\Enums\MaxWidth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;

Expand Down Expand Up @@ -88,7 +93,21 @@ public function form(Form $form): Form
{
$shelters = Shelter::query()
->whereListed()
->get(['id', 'name', 'address']);
->with('shelterVariables')
->when(
data_get($this->data, 'filters.variables'),
fn (Builder $query, array $variables) => $query->whereHasShelterVariables($variables)
)
->when(
data_get($this->data, 'filters.locations'),
fn (Builder $query, array $locations) => $query->whereIn('location_id', $locations)
)
->get();

$attributes = ShelterAttribute::query()
->with('shelterVariables')
->whereListed()
->get();

return $form
->schema([
Expand All @@ -102,7 +121,6 @@ public function form(Form $form): Form
Checkbox::make('for_group')
->label(__('app.field.request_group'))
->live(),

]),

Section::make(__('app.field.requester'))
Expand Down Expand Up @@ -169,13 +187,52 @@ public function form(Form $form): Form

Section::make(__('app.field.request_shelter'))
->schema([
Radio::make('shelter_id')
Grid::make()
->statePath('filters')
->columns(3)
->schema([
Select::make('locations')
->label(__('app.field.location'))
->options(
Location::query()
->whereHas('shelters')
->get()
->pluck('name', 'id')
)
->searchable()
->multiple()
->lazy(),

...$attributes->map(
fn (ShelterAttribute $shelterAttribute) => Select::make("variables.{$shelterAttribute->id}")
->label($shelterAttribute->name)
->options($shelterAttribute->shelterVariables->pluck('name', 'id'))
->searchable()
->multiple()
->lazy(),
)->all(),
]),

RadioCard::make('shelter_id')
->label(__('app.field.request_shelter'))
->columns()
->hiddenLabel()
->options($shelters->mapWithKeys(fn (Shelter $shelter) => [$shelter->id => $shelter->name]))
->descriptions($shelters->mapWithKeys(fn (Shelter $shelter) => [$shelter->id => $shelter->address]))
->descriptions($shelters->mapWithKeys(fn (Shelter $shelter) => [
$shelter->id => view('forms.components.shelter-radio-card-content', [
'shelter' => $shelter,
'attributes' => $attributes,
]),
]))
->required(),

View::make('filament-tables::components.empty-state.index')
->visible($shelters->isEmpty())
->viewData([
'icon' => 'heroicon-o-magnifying-glass',
'heading' => __('app.shelter.empty_state.header'),
'description' => __('app.shelter.empty_state.description'),
]),
]),

Section::make(__('app.field.group'))
Expand Down Expand Up @@ -217,6 +274,7 @@ public function form(Form $form): Form
->schema([
DatePicker::make('start_date')
->label(__('app.field.start_date'))
->afterOrEqual('today')
->required(),

DatePicker::make('end_date')
Expand Down
4 changes: 2 additions & 2 deletions app/Models/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public static function typesenseModelSettings(): array
],
[
'name' => 'shelter_id',
'type' => 'int64',
'type' => 'string',
'optional' => true,
],
[
Expand All @@ -163,7 +163,7 @@ public function toSearchableArray(): array
return [
'id' => (string) $this->id,
'searchable_id' => (string) $this->id,
'shelter_id' => $this->shelter_id,
'shelter_id' => (string) $this->shelter_id,
'beneficiary_name' => $this->beneficiary->name,
];
}
Expand Down
15 changes: 15 additions & 0 deletions app/Models/Shelter.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ public function scopeWhereListed(Builder $query): Builder
});
}

public function scopeWhereHasShelterVariables(Builder $query, array $variables): Builder
{
$variables = collect($variables)
->filter(fn (array $value) => filled($value));

if ($variables->isEmpty()) {
return $query;
}

return $query
->whereHas('shelterVariables', function (Builder $query) use ($variables) {
$variables->each(fn (array $values) => $query->whereIn('shelter_variables.id', $values));
});
}

public function availableCapacity(): Attribute
{
return Attribute::make(
Expand Down
9 changes: 9 additions & 0 deletions app/Models/ShelterAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class ShelterAttribute extends Model
'name',
'type',
'is_enabled',
'is_listed',
];

public array $translatable = [
Expand All @@ -37,6 +38,7 @@ public function casts(): array
return [
'type' => AttributeType::class,
'is_enabled' => 'boolean',
'is_listed' => 'boolean',
];
}

Expand All @@ -58,4 +60,11 @@ public function scopeWhereAttribute(Builder $query): Builder
{
return $query->where('type', AttributeType::ATTRIBUTE);
}

public function scopeWhereListed(Builder $query): Builder
{
return $query
->where('is_enabled', true)
->where('is_listed', true);
}
}
1 change: 1 addition & 0 deletions database/factories/ShelterAttributeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public function definition(): array
'name' => fake()->word(),
'is_enabled' => true,
'type' => AttributeType::ATTRIBUTE,
'is_listed' => fake()->boolean(),
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::table('shelter_attributes', function (Blueprint $table) {
$table->boolean('is_listed')
->default(false)
->after('is_enabled');
});
}
};
4 changes: 4 additions & 0 deletions lang/en/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@
],
],
],
'empty_state' => [
'header' => 'No shelter found',
'description' => 'Please try again with a different filter.',
],
],
'user' => [
'label' => [
Expand Down
73 changes: 73 additions & 0 deletions resources/views/forms/components/radio-card.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
@php
$gridDirection = $getGridDirection() ?? 'column';
$id = $getId();
$isDisabled = $isDisabled();
$isInline = $isInline();
$statePath = $getStatePath();
@endphp

<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<x-filament::grid
:default="$getColumns('default')"
:sm="$getColumns('sm')"
:md="$getColumns('md')"
:lg="$getColumns('lg')"
:xl="$getColumns('xl')"
:two-xl="$getColumns('2xl')"
:is-grid="! $isInline"
:direction="$gridDirection"
:attributes="
\Filament\Support\prepare_inherited_attributes($attributes)
->merge($getExtraAttributes(), escape: false)
->class([
'fi-fo-radio gap-4',
'-mt-4' => (! $isInline) && ($gridDirection === 'column'),
'flex flex-wrap' => $isInline,
])
"
>
@foreach ($getOptions() as $value => $label)
<label @class([
'relative flex cursor-pointer rounded-lg border p-4 shadow-sm focus:outline-none',
'bg-white dark:bg-gray-900 dark:border-white/10',
'break-inside-avoid pt-4' => (! $isInline) && ($gridDirection === 'column'),
])>


<div class="flex items-start flex-1">
<div class="grid text-sm leading-6 gap-y-2">
<span class="block font-medium text-gray-900 dark:text-white">
{{ $label }}
</span>

@if ($hasDescription($value))
<div class="text-gray-500 dark:text-gray-400 contents">
{{ $getDescription($value) }}
</div>
@endif
</div>
</div>

<x-filament::input.radio
:valid="! $errors->has($statePath)"
:attributes="
\Filament\Support\prepare_inherited_attributes($getExtraInputAttributeBag())
->merge([
'disabled' => $isDisabled || $isOptionDisabled($value, $label),
'id' => $id . '-' . $value,
'name' => $id,
'value' => $value,
'wire:loading.attr' => 'disabled',
$applyStateBindingModifiers('wire:model') => $statePath,
], escape: false)
->class(['mt-1 sr-only peer'])
"
/>

<x-heroicon-s-check-circle class="invisible size-5 text-primary-600 peer-checked:visible" />

<span class="absolute border-2 border-transparent rounded-lg pointer-events-none -inset-px peer-checked:border-primary-600" aria-hidden="true"></span>
</label>
@endforeach
</x-filament::grid>
</x-dynamic-component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="text-sm leading-6 text-gray-600 dark:text-gray-400">
{{ $shelter->address }}
</div>

<dl class="grid grid-cols-2 gap-4">
@foreach ($attributes as $attribute)
@php
$variables = $shelter->shelterVariables->where('shelter_attribute_id', $attribute->id)->pluck('name');
@endphp

@continue($variables->isEmpty())

<div>
<dt class="text-sm font-medium leading-6 text-gray-950 dark:text-white">
{{ $attribute->name }}
</dt>
<dd>
{{ $variables->join(', ') }}
</dd>
</div>
@endforeach
</dl>
Loading