Example application of property management and booking with Stripe payments. Inside the example, you will find three different panels: One for Tenants to manage their bookings, one for Owners to manage their properties and overview bookings and one for Super Admins to overview everything in the system.
On the frontend, we have a simple template made with Tailwind CSS. In the navigation bar, there's an option User area
. When a user isn't logged in, it shows as a dropdown with three filament panels that link to their login pages.
*resources/views/components/nav-dropdown.blade.php:
// ...<div class="absolute right-0 z-10 mt-2 w-48 rounded-lg bg-white py-2 shadow-lg"> <a href="{{ filament()->getPanel('tenant')->getLoginUrl() }}" class="block px-4 py-2 text-gray-700 hover:bg-gray-100">Tenant</a> <a href="{{ filament()->getPanel('owner')->getLoginUrl() }}" class="block px-4 py-2 text-gray-700 hover:bg-gray-100">Property Owner</a> <a href="{{ filament()->getPanel('admin')->getLoginUrl() }}" class="block px-4 py-2 text-gray-700 hover:bg-gray-100">Admin</a></div>// ...
When a user is logged in, instead of a dropdown, a direct link to the panel is shown based on the user's role. There's a method on the User
Model that returns a link to the panel.
app/Models/User.php:
use Illuminate\Support\Uri;use Illuminate\Database\Eloquent\Relations\BelongsTo; class User extends Authenticatable implements FilamentUser, MustVerifyEmail{ // ... public function role(): BelongsTo { return $this->belongsTo(Role::class); } public function getUserPanelLink(): string { $panelPath = match ($this->role->name) { 'tenant' => filament()->getPanel('tenant')->getPath(), 'owner' => filament()->getPanel('owner')->getPath(), 'admin' => filament()->getPanel('admin')->getPath(), }; return Uri::to($panelPath); } // ...}
resources/views/components/header.blade.php:
// ...<nav class="hidden md:block"> <ul class="flex space-x-8 items-center"> <x-nav-link href="{{ route('home') }}">Home</x-nav-link> <x-nav-link href="#">Listings</x-nav-link> <x-nav-link href="#">About</x-nav-link> <x-nav-link href="#">Contact</x-nav-link> @guest {{-- [tl! highlight:4 --}} <x-nav-dropdown /> @else <x-nav-link href="{{ auth()->user()->getUserPanelLink() }}">User area</x-nav-link> @endguest </ul></nav>// ...
Users cannot register for the admin
panel, but they can register for the owner
and tenant
panels. After registration, users must verify their email, and an admin must also verify owners. The profile page is enabled, and custom registration pages are used for both panels.
app/Providers/Filament/OwnerPanelProvider.php:
use App\Filament\Owner\Pages\Register; class OwnerPanelProvider extends PanelProvider{ public function panel(Panel $panel): Panel { return $panel // ... ->login() ->registration(Register::class) ->emailVerification() ->profile(isSimple: false) // ... }}
The tenant panel also has a custom profile class.
Next, we will implement: