Fix PayPal billing flow and mobile admin UX
This commit is contained in:
128
AGENTS.md
128
AGENTS.md
@@ -623,6 +623,134 @@ export default () => (
|
||||
| overflow-ellipsis | text-ellipsis |
|
||||
| decoration-slice | box-decoration-slice |
|
||||
| decoration-clone | box-decoration-clone |
|
||||
|
||||
=== filament/filament rules ===
|
||||
|
||||
## Filament
|
||||
|
||||
- Filament is used by this application. Follow existing conventions for how and where it's implemented.
|
||||
- Filament is a Server-Driven UI (SDUI) framework for Laravel that lets you define user interfaces in PHP using structured configuration objects. Built on Livewire, Alpine.js, and Tailwind CSS.
|
||||
- Use the `search-docs` tool for official documentation on Artisan commands, code examples, testing, relationships, and idiomatic practices.
|
||||
|
||||
### Artisan
|
||||
|
||||
- Use Filament-specific Artisan commands to create files. Find them with `list-artisan-commands` or `php artisan --help`.
|
||||
- Inspect required options and always pass `--no-interaction`.
|
||||
|
||||
### Patterns
|
||||
|
||||
Use static `make()` methods to initialize components. Most configuration methods accept a `Closure` for dynamic values.
|
||||
|
||||
Use `Get $get` to read other form field values for conditional logic:
|
||||
|
||||
<code-snippet name="Conditional form field" lang="php">
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Components\Utilities\Get;
|
||||
|
||||
Select::make('type')
|
||||
->options(CompanyType::class)
|
||||
->required()
|
||||
->live(),
|
||||
|
||||
TextInput::make('company_name')
|
||||
->required()
|
||||
->visible(fn (Get $get): bool => $get('type') === 'business'),
|
||||
</code-snippet>
|
||||
|
||||
Use `state()` with a `Closure` to compute derived column values:
|
||||
|
||||
<code-snippet name="Computed table column" lang="php">
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
|
||||
TextColumn::make('full_name')
|
||||
->state(fn (User $record): string => "{$record->first_name} {$record->last_name}"),
|
||||
</code-snippet>
|
||||
|
||||
Actions encapsulate a button with optional modal form and logic:
|
||||
|
||||
<code-snippet name="Action with modal form" lang="php">
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Action::make('updateEmail')
|
||||
->form([
|
||||
TextInput::make('email')->email()->required(),
|
||||
])
|
||||
->action(fn (array $data, User $record): void => $record->update($data)),
|
||||
</code-snippet>
|
||||
|
||||
### Testing
|
||||
|
||||
Authenticate before testing panel functionality. Filament uses Livewire, so use `livewire()` or `Livewire::test()`:
|
||||
|
||||
<code-snippet name="Filament Table Test" lang="php">
|
||||
livewire(ListUsers::class)
|
||||
->assertCanSeeTableRecords($users)
|
||||
->searchTable($users->first()->name)
|
||||
->assertCanSeeTableRecords($users->take(1))
|
||||
->assertCanNotSeeTableRecords($users->skip(1));
|
||||
</code-snippet>
|
||||
|
||||
<code-snippet name="Filament Create Resource Test" lang="php">
|
||||
livewire(CreateUser::class)
|
||||
->fillForm([
|
||||
'name' => 'Test',
|
||||
'email' => 'test@example.com',
|
||||
])
|
||||
->call('create')
|
||||
->assertNotified()
|
||||
->assertRedirect();
|
||||
|
||||
assertDatabaseHas(User::class, [
|
||||
'name' => 'Test',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
</code-snippet>
|
||||
|
||||
<code-snippet name="Testing Validation" lang="php">
|
||||
livewire(CreateUser::class)
|
||||
->fillForm([
|
||||
'name' => null,
|
||||
'email' => 'invalid-email',
|
||||
])
|
||||
->call('create')
|
||||
->assertHasFormErrors([
|
||||
'name' => 'required',
|
||||
'email' => 'email',
|
||||
])
|
||||
->assertNotNotified();
|
||||
</code-snippet>
|
||||
|
||||
<code-snippet name="Calling Actions" lang="php">
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\Testing\TestAction;
|
||||
|
||||
livewire(EditUser::class, ['record' => $user->id])
|
||||
->callAction(DeleteAction::class)
|
||||
->assertNotified()
|
||||
->assertRedirect();
|
||||
|
||||
livewire(ListUsers::class)
|
||||
->callAction(TestAction::make('promote')->table($user), [
|
||||
'role' => 'admin',
|
||||
])
|
||||
->assertNotified();
|
||||
</code-snippet>
|
||||
|
||||
### Common Mistakes
|
||||
|
||||
**Commonly Incorrect Namespaces:**
|
||||
- Form fields (TextInput, Select, etc.): `Filament\Forms\Components\`
|
||||
- Infolist entries (for read-only views) (TextEntry, IconEntry, etc.): `Filament\Forms\Components\`
|
||||
- Layout components (Grid, Section, Fieldset, Tabs, Wizard, etc.): `Filament\Schemas\Components\`
|
||||
- Schema utilities (Get, Set, etc.): `Filament\Schemas\Components\Utilities\`
|
||||
- Actions: `Filament\Actions\` (no `Filament\Tables\Actions\` etc.)
|
||||
- Icons: `Filament\Support\Icons\Heroicon` enum (e.g., `Heroicon::PencilSquare`)
|
||||
|
||||
**Recent breaking changes to Filament:**
|
||||
- File visibility is `private` by default. Use `->visibility('public')` for public access.
|
||||
- `Grid`, `Section`, and `Fieldset` no longer span all columns by default.
|
||||
</laravel-boost-guidelines>
|
||||
|
||||
## Issue Tracking
|
||||
|
||||
Reference in New Issue
Block a user