Skip to content

Admin Panel

Access the Panel Locally

The admin panel is available at https://conflux.local/admin. Credentials are read from .env:

Variable Default
ADMIN_EMAIL admin@conflux.local
ADMIN_PASSWORD conflux123!

If no admin user exists yet, seed one:

docker compose exec php php artisan db:seed --class=AdminSeeder

The seeder uses updateOrCreate and is safe to re-run.

Reset the Admin Password

Update ADMIN_PASSWORD in .env, then re-run the seeder:

docker compose exec php php artisan db:seed --class=AdminSeeder

Add a Filament Resource

docker compose exec php php artisan make:filament-resource ResourceName

The generated class is placed in app/Filament/Resources/ and is auto-discovered — no manual registration needed.

Add a Custom Page

docker compose exec php php artisan make:filament-page PageName

The generated class is placed in app/Filament/Pages/ and is auto-discovered.

Add a Date/Time Column or Entry

For any table column or infolist entry that renders ->dateTime() or ->since(), import App\Filament\Support\TextColumn (tables) or App\Filament\Support\TextEntry (infolists/schemas) in place of the plain Filament classes:

use App\Filament\Support\TextColumn;

TextColumn::make('created_at')->dateTime();

No other change is needed — ->dateTime() and ->since() keep their usual Filament signatures and behaviour, but the rendered value now carries a tooltip stating it is UTC. Use the plain Filament Filament\Tables\Columns\TextColumn / Filament\Infolists\Components\TextEntry instead for a bare calendar date (->date()), where a timezone label has no meaning — see CustomerView.php's date_of_birth for an example.

See ADR-0022 for why this is a subclass and not a Filament macro.

Add a Money Column or Entry

For any table column or infolist entry that displays an integer minor-unit amount (e.g. an order total stored in cents), use ->money() on App\Filament\Support\TextColumn / App\Filament\Support\TextEntry instead of a hand-written ->formatStateUsing() closure:

use App\Filament\Support\TextColumn;

TextColumn::make('total')->money();

Call it with no arguments. This money() intentionally shadows Filament's own native, currency/locale-aware money($currency, $divideBy, $locale, $decimalPlaces) method — the override keeps the same parameter signature for LSP compatibility but ignores every argument and always divides by 100 and formats to two decimal places, falling back to — for null. Passing $currency or $locale expecting Filament's native conversion has no effect. See Admin Panel reference — Currency Display.

Gate a Custom Action by Policy

Filament auto-authorizes the standard CRUD actions it generates (CreateAction, EditAction, DeleteAction, etc.) against the resource's policy. A hand-written Action::make() — a header action like ConnectSystemConnectionAction, or a row action like the Users table's Deactivate/Activate toggles — gets none of that for free. Its visibility has to be wired to the policy explicitly, or it is visible to anyone who can see the page it lives on, regardless of what permission it actually requires:

use Filament\Actions\Action;

Action::make('connect')
    ->visible(fn (): bool => (bool) auth()->user()?->can('create', SystemConnection::class))
    // ...

For a row action, pass the record through so the check is per-record rather than per-page:

Action::make('deactivate')
    ->visible(fn (User $record): bool => (bool) auth()->user()?->can('update', $record))
    // ...

A missing ->visible() check like this leaves the action reachable by any user who can see the underlying list, independent of the permission it actually requires — easy to miss, since Filament's page- and table-level authorization does not extend to individual header or row actions. See Policies for the gate signatures available to call.

See Also