Search by

whilesmart / eloquent-admin

whilesmart

Shared measurements, user directory and automatic email templates for Laravel applications.

Package info

github.com/whilesmartphp/eloquent-admin

pkg:composer/whilesmart/eloquent-admin

Statistics

Installs: 334

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.3.0 2026-10-23 08:51 UTC

README

Shared administration APIs for Laravel applications. It provides measurements, a user directory, and a registry-backed automatic email template system while leaving authorization, user fields, and product-specific sections to the host.

Host configuration

return [
    'route_prefix' => 'api/v1/admin',
    'route_middleware' => ['api', 'auth:sanctum', 'role:admin'],
    'user_model' => App\Models\User::class,
    'owner' => ['type' => 'platform', 'id' => 0],
    'templates' => [
        'welcome' => [
            'name' => 'Welcome email',
            'description' => 'Sent after registration.',
            'subject' => 'Welcome, {{first_name}}',
            'body' => 'Your account is ready.',
        ],
    ],
];

The host binds OwnerAuthorizer to protect the configured admin owner. Product-specific user fields belong in a custom API resource or user provider.

Measurements are registered through whilesmart/eloquent-engagement. Every registered metric provider is returned by the admin metrics endpoint and can be rendered by the companion Nuxt layer.

use App\Engagement\OrdersMetricProvider;

return [
    'providers' => [
        OrdersMetricProvider::class,
    ],
];

Each provider implements Whilesmart\Engagement\Contracts\MetricProvider and returns count, sum, ratio, series, or ranking metrics. Adding a provider automatically adds its measurements to the shared admin page.

PostHog

Share a PostHog dashboard publicly (Share, then turn on sharing) and set its embed address, https://us.posthog.com/embedded/<id>, and the console shows it on its PostHog page. Anyone holding that address can read the dashboard, so it is returned only to the configured owner, and only when it is the https address of a shared dashboard.

return [
    'posthog' => ['dashboard_url' => env('ADMIN_POSTHOG_DASHBOARD_URL')],
];

Optional pages

GET features tells the console which optional pages this host serves, so it offers only pages that load. Feedback is on once whilesmart/eloquent-feedback serves its routes under the console's prefix; PostHog is on once a shared dashboard is set.

Offers

A discount is stored differently in every product, so the console asks a provider rather than a table. Register one and the discounts page lists what it holds and renders a form from the fields it declares.

return [
    'offer_providers' => [
        App\Billing\CouponOfferProvider::class,
    ],
];
use Whilesmart\Admin\Contracts\OfferField;
use Whilesmart\Admin\Contracts\OfferProvider;
use Whilesmart\Admin\Support\Offer;

class CouponOfferProvider implements OfferProvider
{
    public function key(): string
    {
        return 'coupons';
    }

    public function label(): string
    {
        return 'Coupons';
    }

    public function fields(): array
    {
        return [
            new OfferField('code', 'Code', required: true),
            new OfferField('percent_off', 'Percent off', 'number', required: true),
            new OfferField('expires_at', 'Expires', 'date'),
        ];
    }

    public function all(): array { /* Offer[] */ }

    public function create(array $attributes): Offer { /* ... */ }

    public function revoke(string $id): void { /* ... */ }
}

Offer::$value is already formatted, because only the provider knows whether 20 means a percentage, pennies or seats. Revoking stops an offer being redeemed again and leaves redemptions already made standing.

Registering no provider is a supported state: the endpoint answers with an empty list and the page says so.

Two providers ship with the console, each needing its billing package:

Provider Package What revoking does
Whilesmart\Admin\Offers\StripePromotionCodes whilesmart/entitlements-cashier Stops the code and takes it off subscriptions already carrying it
Whilesmart\Admin\Offers\FreePasses whilesmart/eloquent-entitlements Ends the person's free plan at once

The page heads its table for discount codes. A provider whose offers are something else, such as a plan given to a person, names the columns it fills with a columns() method, and the ones it leaves out are hidden:

public function columns(): array
{
    return ['code' => 'Person', 'value' => 'Plan', 'until' => 'Until'];
}