Add a new condition
diff --git a/resources/views/filters.blade.php b/resources/views/filters.blade.php
new file mode 100644
index 0000000..33a94da
--- /dev/null
+++ b/resources/views/filters.blade.php
@@ -0,0 +1,11 @@
+
+ @foreach($this->filters() as $filter)
+ @include('query-builder::filters.' . $filter->component())
+ @endforeach
+
+
+
+
+ Reset
+
+
\ No newline at end of file
diff --git a/resources/views/filters/boolean.blade.php b/resources/views/filters/boolean.blade.php
new file mode 100644
index 0000000..ddab435
--- /dev/null
+++ b/resources/views/filters/boolean.blade.php
@@ -0,0 +1,8 @@
+
+ {{ $filter->label() }}
+
+ Choose an option
+ Yes
+ No
+
+
\ No newline at end of file
diff --git a/resources/views/filters/date.blade.php b/resources/views/filters/date.blade.php
new file mode 100644
index 0000000..9f0b91b
--- /dev/null
+++ b/resources/views/filters/date.blade.php
@@ -0,0 +1,10 @@
+
+ {{ $filter->label() }}
+
+
+
diff --git a/resources/views/filters/select.blade.php b/resources/views/filters/select.blade.php
new file mode 100644
index 0000000..63ead61
--- /dev/null
+++ b/resources/views/filters/select.blade.php
@@ -0,0 +1,11 @@
+
+ {{ $filter->label() }}
+
+ Choose an option
+ @foreach($filter->options() as $key => $value)
+ {{ $value }}
+ @endforeach
+
+
\ No newline at end of file
diff --git a/resources/views/filters/text.blade.php b/resources/views/filters/text.blade.php
new file mode 100644
index 0000000..0b1b73f
--- /dev/null
+++ b/resources/views/filters/text.blade.php
@@ -0,0 +1,4 @@
+
+ {{ $filter->label() }}
+
+
\ No newline at end of file
diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php
new file mode 100644
index 0000000..079a5f6
--- /dev/null
+++ b/resources/views/table.blade.php
@@ -0,0 +1,92 @@
+
+
+
+ @if ($this->areFiltersAvailable())
+
+ @include('query-builder::filters')
+
+ @endif
+
+
+
+ @if($this->rows->count())
+
+
+
+
+
+
+ @foreach ($this->columns() as $column)
+ isSortable()) wire:click="sort('{{ $column->key }}')" @endif>
+ @if ($column->showHeader)
+ justify,
+ 'cursor-pointer' => $column->isSortable(),
+ ])>
+ {{ $column->label }}
+
+ @if ($sortBy === $column->key)
+ @if ($sortDirection === 'asc')
+
+
+
+ @else
+
+
+
+ @endif
+ @endif
+
+
+ @endif
+
+ @endforeach
+
+
+
+
+ @foreach ($this->rows as $row)
+ isClickable())
+ wire:click="rowClick('{{ $row->id }}')"
+ @endif
+ wire:key="row-{{ $row->id }}"
+ @class([
+ 'bg-white border-b',
+ 'hover:bg-gray-50 cursor-pointer' => $this->isClickable(),
+ ])>
+
+ @foreach ($this->columns() as $column)
+
+
+
+
+
+
+ @endforeach
+
+ @endforeach
+
+
+
+
+ @if($this->rows->hasPages())
+
+
{{ $this->rows->links() }}
+
+ @endif
+ @endif
+
+
diff --git a/src/Http/Livewire/QueryBuilder/Concerns/WithFilters.php b/src/Http/Livewire/QueryBuilder/Concerns/WithFilters.php
new file mode 100644
index 0000000..0e32984
--- /dev/null
+++ b/src/Http/Livewire/QueryBuilder/Concerns/WithFilters.php
@@ -0,0 +1,52 @@
+displayFilters && count($this->filters()) > 0;
+ }
+
+ public function displayFilters(bool $displayFilters = true): static
+ {
+ $this->displayFilters = $displayFilters;
+
+ return $this;
+ }
+
+ public function filters(): array
+ {
+ return [
+ TextFilter::make('Name', 'full_name')->useOperator('like'),
+ SelectFilter::make('Location', 'contract.location.name')->withOptions([
+ 'ACT Skills Centre, Caerphilly' => 'ACT Skills Centre, Caerphilly',
+ 'Home Based' => 'Home Based',
+ ]),
+ BooleanFilter::make('Line Manager', 'contract.line_manager'),
+ DateFilter::make('Started on or after', 'contract.start_date')->useOperator('>='),
+ DateFilter::make('Started on or before', 'contract.start_date')->useOperator('<='),
+ ];
+ }
+
+ public function resetFilters(): void
+ {
+ $this->filterValues = [];
+ $this->resetPage();
+ }
+
+ public function updatedFilterValues(): void
+ {
+ $this->resetPage();
+ }
+}
diff --git a/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php b/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php
index d541310..0388ded 100644
--- a/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php
+++ b/src/Http/Livewire/QueryBuilder/Concerns/WithPagination.php
@@ -13,7 +13,7 @@ trait WithPagination
public function applyPagination($query)
{
if ($this->paginate) {
- return $query->paginate($this->perPage);
+ return $query->ray()->paginate($this->perPage);
} else {
return $query->get();
}
diff --git a/src/Http/Livewire/QueryBuilder/Filters/BaseFilter.php b/src/Http/Livewire/QueryBuilder/Filters/BaseFilter.php
new file mode 100644
index 0000000..ebcf556
--- /dev/null
+++ b/src/Http/Livewire/QueryBuilder/Filters/BaseFilter.php
@@ -0,0 +1,80 @@
+key = $key;
+ $this->label = $label;
+ $this->code = $label.':'.$this->operator;
+ }
+
+ public static function make($label, $key = null): static
+ {
+ if (is_null($key)) {
+ $key = Str::snake($label);
+ }
+
+ return new static($key, $label);
+ }
+
+ public function label(): string
+ {
+ return $this->label;
+ }
+
+ public function key(): string
+ {
+ return $this->key;
+ }
+
+ public function operator(): string
+ {
+ return $this->operator;
+ }
+
+ public function code(): string
+ {
+ return $this->code;
+ }
+
+ public function component(): string
+ {
+ return $this->component;
+ }
+
+ public function useOperator(string $operator): static
+ {
+ $this->operator = $operator;
+ $this->code = $this->label.':'.$this->operator;
+
+ return $this;
+ }
+
+ public function useComponent(string $component): static
+ {
+ $this->component = $component;
+
+ return $this;
+ }
+
+ public function parseValue($value)
+ {
+ return $value;
+ }
+}
diff --git a/src/Http/Livewire/QueryBuilder/Filters/BooleanFilter.php b/src/Http/Livewire/QueryBuilder/Filters/BooleanFilter.php
new file mode 100644
index 0000000..b4b23c3
--- /dev/null
+++ b/src/Http/Livewire/QueryBuilder/Filters/BooleanFilter.php
@@ -0,0 +1,21 @@
+startOfDay();
+ }
+}
diff --git a/src/Http/Livewire/QueryBuilder/Filters/NumberFilter.php b/src/Http/Livewire/QueryBuilder/Filters/NumberFilter.php
new file mode 100644
index 0000000..1acaa4b
--- /dev/null
+++ b/src/Http/Livewire/QueryBuilder/Filters/NumberFilter.php
@@ -0,0 +1,7 @@
+options;
+ }
+
+ public function withOptions(array $options = []): static
+ {
+ $this->options = $options;
+
+ return $this;
+ }
+}
diff --git a/src/Http/Livewire/QueryBuilder/Filters/TextFilter.php b/src/Http/Livewire/QueryBuilder/Filters/TextFilter.php
new file mode 100644
index 0000000..72351ef
--- /dev/null
+++ b/src/Http/Livewire/QueryBuilder/Filters/TextFilter.php
@@ -0,0 +1,15 @@
+operator() === 'like') {
+ return "%{$value}%";
+ }
+
+ return $value;
+ }
+}
diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php
index d91609d..3ed8281 100755
--- a/src/QueryBuilder.php
+++ b/src/QueryBuilder.php
@@ -8,6 +8,7 @@
use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithActions;
use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithCaching;
use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithColumns;
+use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithFilters;
use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithPagination;
use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithQueryBuilder;
use ACTTraining\QueryBuilder\Http\Livewire\QueryBuilder\Concerns\WithRowClick;
@@ -28,6 +29,7 @@ abstract class QueryBuilder extends Component
use WithActions;
use WithCaching;
use WithColumns;
+ use WithFilters;
use WithPagination;
use WithQueryBuilder;
use WithRowClick;
diff --git a/src/Table.php b/src/Table.php
new file mode 100755
index 0000000..9cfc0b9
--- /dev/null
+++ b/src/Table.php
@@ -0,0 +1,98 @@
+ '$refresh',
+ ];
+
+ abstract public function query(): Builder;
+
+ public function booted(): void
+ {
+ $this->config();
+
+ }
+
+ public function config(): void
+ {
+ //
+ }
+
+ public function getRowsQueryProperty()
+ {
+ $query = $this->query()->when($this->sortBy !== '', function ($query) {
+ $query->orderBy($this->sortBy, $this->sortDirection);
+ });
+
+ $dottedFilterValue = Arr::dot($this->filterValues);
+
+ foreach ($this->filters() as $filter) {
+ $value = $dottedFilterValue[$filter->code()] ?? null;
+
+ $query->when($value !== null, function ($query) use ($filter, $value) {
+ $value = $filter->parseValue($value);
+ if (Str::contains($filter->key(), '.')) {
+ $relation = Str::beforeLast($filter->key(), '.');
+ $column = Str::afterLast($filter->key(), '.');
+
+ $query->whereHas($relation, function ($query) use ($filter, $value, $column) {
+ $query->where($column, $filter->operator(), $value);
+ });
+ } else {
+ $query->where($filter->key(), $filter->operator(), $value);
+ }
+ });
+ }
+
+ return $query;
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function getRowsProperty()
+ {
+ return $this->applyPagination($this->rowsQuery);
+ }
+
+ protected function model(): Model
+ {
+ $model = $this->model;
+
+ return app($model);
+ }
+
+ public function render(): Factory|View
+ {
+ return view('query-builder::table');
+ }
+}