TenantAtlas/resources/views/filament/pages/choose-workspace.blade.php
Ahmed Darrazi 051db1842d feat(107): implement Workspace Chooser v1 — all 40 tasks complete
Spec 107: Workspace Chooser v1 (Enterprise) + In-App Switch Entry Point

## Core changes
- Refactor EnsureWorkspaceSelected middleware: 7-step algorithm with
  auto-resume (single membership + last_workspace_id), stale session
  detection, ?choose=1 forced chooser, workspace-optional path bypass
- Create WorkspaceRedirectResolver for DRY tenant-count branching
  (0→managed-tenants, 1→tenant-dashboard, >1→choose-tenant)
- Add WorkspaceAutoSelected + WorkspaceSelected audit enum cases
- Rewrite ChooseWorkspace page: role badges, tenant counts,
  wire:click selection, audit logging, WorkspaceRedirectResolver
- Add 'Switch workspace' user menu item in AdminPanelProvider
- Rewrite SwitchWorkspaceController with audit + resolver
- Replace inline tenant branching in routes/web.php with resolver

## New test files (6)
- WorkspaceRedirectResolverTest (5 tests
Spec 107: Workspace Chooser v1 (Enterprise) + In-App Switch Entry Point

## Core changes
- Refactor EnsureWorkspaceSelected middleware: 7-step algorithmst
## Core changes
- Refactor EnsureWorkspaceSelected middleware: 7-stepes - Refactor Ensng  auto-resume (single membership + last_workspace_id), stale sessioid  detection, ?choose=1 forced chooser, w (security invariant preserve- Create WorkspaceRedirectResolver for DRY tenant-count branching

  (0→managed-tenants, 1→tenant-dashboapped (8163 assertions)
2026-02-22 17:19:19 +01:00

100 lines
4.8 KiB
PHP

<x-filament-panels::page>
<x-filament::section>
<div class="flex flex-col gap-4">
<div class="text-sm text-gray-600 dark:text-gray-300">
Select a workspace to continue.
</div>
@php
$workspaces = $this->getWorkspaces();
$workspaceRoles = $this->workspaceRoles;
$user = auth()->user();
$recommendedWorkspaceId = $user instanceof \App\Models\User ? (int) ($user->last_workspace_id ?? 0) : 0;
if ($recommendedWorkspaceId > 0) {
[$recommended, $other] = $workspaces->partition(fn ($workspace) => (int) $workspace->id === $recommendedWorkspaceId);
$workspaces = $recommended->concat($other)->values();
}
$roleColorMap = [
'owner' => 'primary',
'manager' => 'info',
'operator' => 'gray',
'readonly' => 'gray',
];
@endphp
@if ($workspaces->isEmpty())
<div class="rounded-md border border-gray-200 bg-gray-50 p-4 text-center text-sm text-gray-700 dark:border-gray-800 dark:bg-gray-900 dark:text-gray-200">
You don't have access to any workspace yet.
</div>
@else
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
@foreach ($workspaces as $workspace)
@php
$isRecommended = $recommendedWorkspaceId > 0 && (int) $workspace->id === $recommendedWorkspaceId;
$role = $workspaceRoles[(int) $workspace->id] ?? null;
$tenantCount = (int) ($workspace->tenants_count ?? 0);
@endphp
<div
wire:key="workspace-{{ $workspace->id }}"
wire:click="selectWorkspace({{ (int) $workspace->id }})"
class="cursor-pointer rounded-lg border p-4 transition hover:shadow-sm dark:border-gray-800 {{ $isRecommended ? 'border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30' : 'border-gray-200 hover:border-gray-300 dark:hover:border-gray-700' }}"
>
<div class="flex flex-col gap-3">
<div class="flex flex-col gap-2">
<div class="font-medium text-gray-900 dark:text-gray-100">
{{ $workspace->name }}
</div>
<div class="flex flex-wrap items-center gap-2">
@if ($isRecommended)
<x-filament::badge color="warning" size="sm">
Last used
</x-filament::badge>
@endif
@if ($role)
<x-filament::badge :color="$roleColorMap[$role] ?? 'gray'" size="sm">
{{ ucfirst($role) }}
</x-filament::badge>
@endif
</div>
</div>
<div class="text-xs text-gray-500 dark:text-gray-400">
{{ $tenantCount }} {{ \Illuminate\Support\Str::plural('tenant', $tenantCount) }}
</div>
</div>
</div>
@endforeach
</div>
@php
$canManageWorkspaces = false;
if ($user instanceof \App\Models\User && $workspaces->count() > 0) {
foreach ($workspaces as $ws) {
$wsRole = $workspaceRoles[(int) $ws->id] ?? null;
if ($wsRole === 'owner') {
$canManageWorkspaces = true;
break;
}
}
}
@endphp
@if ($canManageWorkspaces)
<div class="mt-2 text-center">
<a href="/admin/workspaces" class="text-sm text-primary-600 hover:underline dark:text-primary-400">
Manage workspaces
</a>
</div>
@endif
@endif
</div>
</x-filament::section>
</x-filament-panels::page>