Deploy 1: i18n + Notifications + Global Search + Tests
- SetLocale middleware (ro/ru/en, session-first, user-persisted)
- Lang switcher in topbar (Filament render hook USER_MENU_BEFORE)
- POST /locale/{lang} route persists to user.locale + session
- Database notifications enabled on tenant panel (30s polling)
- GlobalSearch (Cmd+K / Ctrl+K) on Client, Vehicle, WorkOrder, Lead, Part
- Tests: TenantIsolation (4), AuthFlow (2), WorkOrderCalc (3), MarkupRule (3)
This commit is contained in:
@@ -38,6 +38,9 @@ class TenantPanelProvider extends PanelProvider
|
||||
'primary' => Color::Blue,
|
||||
])
|
||||
->authGuard('web')
|
||||
->databaseNotifications()
|
||||
->databaseNotificationsPolling('30s')
|
||||
->globalSearchKeyBindings(['command+k', 'ctrl+k'])
|
||||
->discoverResources(in: app_path('Filament/Tenant/Resources'), for: 'App\\Filament\\Tenant\\Resources')
|
||||
->discoverPages(in: app_path('Filament/Tenant/Pages'), for: 'App\\Filament\\Tenant\\Pages')
|
||||
->pages([
|
||||
@@ -58,6 +61,7 @@ class TenantPanelProvider extends PanelProvider
|
||||
// unauthenticated → endless redirect to /app/login.
|
||||
ResolveTenant::class,
|
||||
CheckTenantStatus::class,
|
||||
\App\Http\Middleware\SetLocale::class,
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartSession::class,
|
||||
@@ -114,6 +118,68 @@ class TenantPanelProvider extends PanelProvider
|
||||
</style>
|
||||
BLADE)
|
||||
)
|
||||
->renderHook(
|
||||
PanelsRenderHook::USER_MENU_BEFORE,
|
||||
fn (): string => Blade::render(<<<'BLADE'
|
||||
@php
|
||||
$locale = app()->getLocale();
|
||||
$langs = ['ro' => 'RO', 'ru' => 'RU', 'en' => 'EN'];
|
||||
$csrf = csrf_token();
|
||||
@endphp
|
||||
<div class="al-locale" x-data="{ open: false }">
|
||||
<button type="button" class="al-locale-btn" @click="open = !open" @click.away="open = false">
|
||||
🌐 {{ $langs[$locale] ?? 'RO' }}
|
||||
<span class="al-locale-caret">▾</span>
|
||||
</button>
|
||||
<div x-show="open" x-cloak class="al-locale-menu">
|
||||
@foreach ($langs as $code => $label)
|
||||
<form method="POST" action="/locale/{{ $code }}">
|
||||
<input type="hidden" name="_token" value="{{ $csrf }}">
|
||||
<button type="submit" class="al-locale-item {{ $locale === $code ? 'active' : '' }}">
|
||||
{{ $label }} —
|
||||
<span style="opacity:.7;font-size:11px;">
|
||||
@switch($code)
|
||||
@case('ro') Română @break
|
||||
@case('ru') Русский @break
|
||||
@case('en') English @break
|
||||
@endswitch
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.al-locale { position: relative; margin-right: 8px; }
|
||||
.al-locale-btn {
|
||||
background: transparent; border: 1px solid rgba(0,0,0,.08);
|
||||
border-radius: 8px; padding: 6px 10px; font-size: 12px;
|
||||
cursor: pointer; color: inherit; display: flex; align-items: center; gap: 4px;
|
||||
}
|
||||
.dark .al-locale-btn { border-color: rgba(255,255,255,.1); }
|
||||
.al-locale-btn:hover { background: rgba(0,0,0,.04); }
|
||||
.dark .al-locale-btn:hover { background: rgba(255,255,255,.04); }
|
||||
.al-locale-caret { font-size: 10px; opacity: .6; }
|
||||
.al-locale-menu {
|
||||
position: absolute; top: 100%; right: 0; margin-top: 4px;
|
||||
background: #fff; border: 1px solid #e5e7eb; border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,.08);
|
||||
min-width: 160px; z-index: 50; overflow: hidden;
|
||||
}
|
||||
.dark .al-locale-menu { background: #1f2937; border-color: #374151; }
|
||||
.al-locale-menu form { margin: 0; }
|
||||
.al-locale-item {
|
||||
display: block; width: 100%; text-align: left;
|
||||
background: transparent; border: none; padding: 8px 12px;
|
||||
font-size: 13px; cursor: pointer; color: inherit;
|
||||
}
|
||||
.al-locale-item:hover { background: #f3f4f6; }
|
||||
.dark .al-locale-item:hover { background: #374151; }
|
||||
.al-locale-item.active { background: #eff6ff; color: #2563eb; font-weight: 600; }
|
||||
.dark .al-locale-item.active { background: #1e3a8a; color: #93c5fd; }
|
||||
</style>
|
||||
BLADE)
|
||||
)
|
||||
->renderHook(
|
||||
PanelsRenderHook::SIDEBAR_LOGO_BEFORE,
|
||||
fn (): string => Blade::render(<<<'BLADE'
|
||||
|
||||
Reference in New Issue
Block a user