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
69 changes: 69 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Laravel package (`act-training/query-builder`) providing drop-in Livewire components for building query builders, tables, and reports on Eloquent models. Uses Spatie's `laravel-package-tools` for package scaffolding.

Namespace: `ACTTraining\QueryBuilder`

## Commands

```bash
composer test # Run tests (Pest)
vendor/bin/pest --filter="test name" # Run a single test
composer analyse # Static analysis (PHPStan, level 5)
composer format # Code formatting (Laravel Pint)
composer start # Build and serve via testbench
```

## Architecture

### Core Builder Classes (src/)

Three abstract Livewire components that consuming apps extend:

- **`QueryBuilder`** — Full-featured query builder with criteria-based filtering (AND/OR conditions). Users define `query()`, `columns()`, and `conditions()` methods. Renders `query-table` view.
- **`TableBuilder`** — Simpler table with URL-persisted filters and search. Users define `query()`, `columns()`, and `filters()` methods. Renders `table` view.
- **`ReportBuilder`** extends QueryBuilder — Adds report-specific features via `WithReportBuilder`. Renders `report-table` view.
- **`GroupsBuilder`** extends QueryBuilder — Adds grouping via `WithGroupBuilder`. Renders `group-table` view.

### Two Filtering Systems

**Criteria System** (used by QueryBuilder): Conditions → Criteria → CriteriaCollection pipeline.
- `Conditions` (src/Support/Conditions/) — Define available filter operations for the UI (TextCondition, DateCondition, BooleanCondition, etc.)
- `Criteria` (src/Support/Criteria/) — Implement the actual query logic (CompareCriteria, LikeCriteria, DateCriteria, BooleanCriteria, NullCriteria). All extend `BaseCriteria` implementing `CriteriaInterface`.
- `CriteriaCollection` (src/Support/Collection/) — Composes criteria with AND (`AllOfCriteriaCollection`) or OR (`OneOfCriteriaCollection`) logic.
- Models must `use AppliesCriteria` trait to gain the `->apply()` scope.

**Filter System** (used by TableBuilder): Simpler key/operator/value filters.
- `Filters` (src/Support/Filters/) — TextFilter, DateFilter, BooleanFilter, NumberFilter, SelectFilter, NullFilter. All extend `BaseFilter`.
- Filter codes use Blade-safe operator aliases (gte/lte/gt/lt instead of `>=`/`<=`/`>`/`<`) to avoid HTML encoding issues in `wire:model`.

### Columns (src/Support/Columns/)

Column types: `Column`, `BooleanColumn`, `DateColumn`, `ViewColumn`. All extend `BaseColumn`. Fluent API with `make()` static constructor. Support sorting, searching, hiding, custom components, justify alignment, subtitles, and value reformatting.

### Behavior Traits (src/Support/Concerns/)

All builder functionality is composed via traits: `WithActions`, `WithCaching`, `WithColumns`, `WithFilters`, `WithPagination`, `WithQueryBuilder`, `WithRowClick`, `WithRowInjection`, `WithSearch`, `WithSelecting`, `WithSorting`, `WithToolbar`, `WithViews`, `WithIdentifier`, `WithIndicator`, `WithMessage`.

### Relationship Handling

Dot-notation keys (e.g., `contract.job.name`) are used throughout columns, conditions, and filters to traverse Eloquent relationships. The pattern `explode('.', $key)` → `array_pop()` for column name → `implode('.')` for relationship path → `whereHas()` is used consistently across BaseCriteria, TableBuilder, and BaseColumn.

## Testing

Uses Pest with Orchestra Testbench. Tests are in `tests/`. The `TestCase` base class registers the service provider and configures factory resolution. Architecture tests enforce no debugging functions (`dd`, `dump`, `ray`).

## Views

Blade views in `resources/views/`. Four Blade components registered in the service provider for column rendering. View prefix is `query-builder::`.

## Conventions

- All public API classes use `static make($label, $key)` fluent constructors
- `$key` defaults to `Str::snake($label)` when not provided
- PHPStan level 5 with Octane compatibility and model property checks enabled
- PHP 8.2+, Livewire v3
2 changes: 1 addition & 1 deletion resources/views/report-editor.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class="m-4 block p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-g
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">
@foreach($columns as $columnKey => $column)
<div class="flex items-center mb-4">
<input wire:model.live.debounce="selectedColumns" id="{{$column['key']}}" type="checkbox"
<input wire:model.live.debounce.500ms="selectedColumns" id="{{$column['key']}}" type="checkbox"
value="{{ $column['key'] }}"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
<label for="{{$column['key']}}"
Expand Down
1 change: 0 additions & 1 deletion src/Support/Concerns/WithReportBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ private function findElementByKey(array $array, $targetValue): ?array
public function updatedSelectedColumns(): void
{
$this->resetPage();
$this->dispatch('refreshTable')->self();
}

public function availableColumns(): array
Expand Down
Loading