Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
// Obtener datos del usuario desde el contexto (viene de Keycloak vía +layout.server.ts)
|
||||
const userData = getContext<any>('user');
|
||||
const userTenants = getContext<{ id: number; name: string; slug: string }[]>('userTenants') ?? [];
|
||||
|
||||
// Obtener datos del sidebar con traducciones
|
||||
const sidebarData = getSidebarData();
|
||||
@@ -42,7 +43,7 @@
|
||||
<NavProjects projects={data.projects} />
|
||||
</Sidebar.Content>
|
||||
<Sidebar.Footer>
|
||||
<NavUser user={data.user} />
|
||||
<NavUser user={data.user} tenants={userTenants} />
|
||||
</Sidebar.Footer>
|
||||
<Sidebar.Rail />
|
||||
</Sidebar.Root>
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
import LanguagesIcon from '@lucide/svelte/icons/languages';
|
||||
import MoonIcon from '@lucide/svelte/icons/moon';
|
||||
import SunIcon from '@lucide/svelte/icons/sun';
|
||||
import ArrowLeftRightIcon from '@lucide/svelte/icons/arrow-left-right';
|
||||
import BuildingIcon from '@lucide/svelte/icons/building';
|
||||
import CheckIcon from '@lucide/svelte/icons/check';
|
||||
import { logout } from '$lib/auth';
|
||||
import { cookieName } from '$lib/paraglide/runtime';
|
||||
import { page } from '$app/state';
|
||||
@@ -19,9 +22,18 @@
|
||||
import { getBackendAssetUrl } from '$lib/utils';
|
||||
import AppVersion from '$lib/components/app-version.svelte';
|
||||
|
||||
let { user }: { user: { name: string; email: string; avatar: string } } = $props();
|
||||
let { user, tenants = [] }: {
|
||||
user: { name: string; email: string; avatar: string };
|
||||
tenants: { id: number; name: string; slug: string }[];
|
||||
} = $props();
|
||||
const sidebar = useSidebar();
|
||||
|
||||
// Tenant activo (viene en el JWT como atributo tenant_slug)
|
||||
let currentTenantSlug = $derived((page.data.user as any)?.tenant_slug ?? '');
|
||||
|
||||
// Estado de cambio de tenant
|
||||
let switchingTenant = $state(false);
|
||||
|
||||
// URL completa del avatar
|
||||
let avatarUrl = $derived(getBackendAssetUrl(user.avatar) || '/avatars/default.jpg');
|
||||
|
||||
@@ -59,6 +71,26 @@
|
||||
await logout();
|
||||
}
|
||||
|
||||
async function switchTenant(slug: string) {
|
||||
if (slug === currentTenantSlug || switchingTenant) return;
|
||||
switchingTenant = true;
|
||||
try {
|
||||
const res = await fetch('/api-sveltekit/auth/switch-tenant', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ tenant_slug: slug })
|
||||
});
|
||||
if (res.ok) {
|
||||
// Recargar el dashboard con los nuevos tokens
|
||||
window.location.href = '/dashboard';
|
||||
} else {
|
||||
console.error('Error al cambiar de organización');
|
||||
}
|
||||
} finally {
|
||||
switchingTenant = false;
|
||||
}
|
||||
}
|
||||
|
||||
function navigateToAccount() {
|
||||
goto('/dashboard/account');
|
||||
}
|
||||
@@ -169,6 +201,40 @@
|
||||
{/if}
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator />
|
||||
{#if tenants.length > 1}
|
||||
<DropdownMenu.Sub>
|
||||
<DropdownMenu.SubTrigger class="gap-2">
|
||||
{#if switchingTenant}
|
||||
<svg class="animate-spin size-4 shrink-0" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
|
||||
</svg>
|
||||
{:else}
|
||||
<ArrowLeftRightIcon class="size-4" />
|
||||
{/if}
|
||||
Cambiar organización
|
||||
</DropdownMenu.SubTrigger>
|
||||
<DropdownMenu.SubContent class="min-w-44">
|
||||
<DropdownMenu.Label class="text-xs text-muted-foreground pb-1">
|
||||
Mis organizaciones
|
||||
</DropdownMenu.Label>
|
||||
{#each tenants as tenant (tenant.id)}
|
||||
<DropdownMenu.Item
|
||||
class="gap-2 cursor-pointer"
|
||||
disabled={switchingTenant}
|
||||
onclick={() => switchTenant(tenant.slug)}
|
||||
>
|
||||
<BuildingIcon class="size-4 shrink-0 text-muted-foreground" />
|
||||
<span class="flex-1 truncate">{tenant.name}</span>
|
||||
{#if tenant.slug === currentTenantSlug}
|
||||
<CheckIcon class="size-3.5 shrink-0 text-blue-600" />
|
||||
{/if}
|
||||
</DropdownMenu.Item>
|
||||
{/each}
|
||||
</DropdownMenu.SubContent>
|
||||
</DropdownMenu.Sub>
|
||||
{/if}
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Item onclick={handleLogout}>
|
||||
<LogOutIcon />
|
||||
Log out
|
||||
|
||||
Reference in New Issue
Block a user