151 lines
5.8 KiB
Svelte
151 lines
5.8 KiB
Svelte
<script lang="ts">
|
|
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
|
|
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
|
import { useSidebar } from '$lib/components/ui/sidebar/index.js';
|
|
import ChevronsUpDownIcon from '@lucide/svelte/icons/chevrons-up-down';
|
|
import BuildingIcon from '@lucide/svelte/icons/building';
|
|
import CheckIcon from '@lucide/svelte/icons/check';
|
|
import { companyStore } from '$lib/stores/company.svelte';
|
|
import { getBackendAssetUrl } from '$lib/utils';
|
|
|
|
const sidebar = useSidebar();
|
|
|
|
// Derivar la URL del logo usando el endpoint específico
|
|
let activeCompanyLogoUrl = $derived(
|
|
companyStore.activeCompany?.logo
|
|
? getBackendAssetUrl(
|
|
`v1/a76/company/${companyStore.activeCompany.id}/logo/image?t=${Date.now()}`
|
|
)
|
|
: null
|
|
);
|
|
|
|
// Iniciales de la compañía activa (2 primeras letras)
|
|
let activeCompanyInitials = $derived(
|
|
companyStore.activeCompany?.name?.slice(0, 2).toUpperCase() || 'CO'
|
|
);
|
|
|
|
// Fallback en degradé cuando no hay logo cargado
|
|
const fallbackBg =
|
|
'radial-gradient(circle at 30% 30%, rgba(0,0,0,0.08), rgba(0,0,0,0.12)), linear-gradient(135deg, rgba(99,102,241,0.12), rgba(14,165,233,0.18))';
|
|
|
|
const logoBg = $derived(activeCompanyLogoUrl ? `url(${activeCompanyLogoUrl})` : fallbackBg);
|
|
</script>
|
|
|
|
<Sidebar.Menu>
|
|
<Sidebar.MenuItem>
|
|
<DropdownMenu.Root>
|
|
<DropdownMenu.Trigger>
|
|
{#snippet child({ props })}
|
|
<Sidebar.MenuButton
|
|
{...props}
|
|
size="lg"
|
|
class="relative overflow-hidden group-has-data-[state=collapsed]/sidebar-wrapper:aspect-square group-has-data-[state=collapsed]/sidebar-wrapper:h-10 group-has-data-[state=collapsed]/sidebar-wrapper:w-10 group-has-data-[state=collapsed]/sidebar-wrapper:justify-center group-has-data-[state=collapsed]/sidebar-wrapper:gap-0 group-has-data-[state=collapsed]/sidebar-wrapper:rounded-lg data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
|
>
|
|
<div
|
|
class="flex aspect-square size-8 items-center justify-center overflow-hidden rounded-lg bg-sidebar-primary text-sidebar-primary-foreground group-has-data-[state=collapsed]/sidebar-wrapper:hidden"
|
|
>
|
|
{#if activeCompanyLogoUrl}
|
|
<img
|
|
src={activeCompanyLogoUrl}
|
|
alt={companyStore.activeCompany?.name || 'Company'}
|
|
class="size-full object-cover"
|
|
onerror={(e) => {
|
|
(e.currentTarget as HTMLImageElement).style.display = 'none';
|
|
}}
|
|
/>
|
|
{:else}
|
|
<span class="text-sm font-semibold text-white">{activeCompanyInitials}</span>
|
|
{/if}
|
|
</div>
|
|
<div
|
|
class="grid min-w-0 flex-1 text-left text-sm leading-tight group-has-data-[state=collapsed]/sidebar-wrapper:hidden"
|
|
>
|
|
<span class="truncate font-medium">
|
|
{companyStore.activeCompany?.name || 'Seleccionar compañía'}
|
|
</span>
|
|
{#if companyStore.activeCompany?.rfc}
|
|
<span class="truncate text-xs text-muted-foreground">
|
|
{companyStore.activeCompany.rfc}
|
|
</span>
|
|
{/if}
|
|
</div>
|
|
<ChevronsUpDownIcon
|
|
class="ml-auto size-4 group-has-data-[state=collapsed]/sidebar-wrapper:hidden"
|
|
/>
|
|
|
|
<!-- Isotipo compacto visible solo en modo colapsado -->
|
|
<div
|
|
class="relative z-10 hidden size-8 items-center justify-center overflow-hidden rounded-md bg-sidebar-primary text-sm font-semibold text-sidebar-foreground shadow-sm ring-1 ring-sidebar-border/40 group-has-data-[state=collapsed]/sidebar-wrapper:flex"
|
|
>
|
|
{#if activeCompanyLogoUrl}
|
|
<img
|
|
src={activeCompanyLogoUrl}
|
|
alt={companyStore.activeCompany?.name || 'Company'}
|
|
class="size-full object-cover"
|
|
onerror={(e) => {
|
|
(e.currentTarget as HTMLImageElement).style.display = 'none';
|
|
}}
|
|
/>
|
|
{:else}
|
|
{activeCompanyInitials}
|
|
{/if}
|
|
</div>
|
|
</Sidebar.MenuButton>
|
|
{/snippet}
|
|
</DropdownMenu.Trigger>
|
|
<DropdownMenu.Content
|
|
class="w-(--bits-dropdown-menu-anchor-width) min-w-56 rounded-lg"
|
|
align="start"
|
|
side={sidebar.isMobile ? 'bottom' : 'right'}
|
|
sideOffset={4}
|
|
>
|
|
<DropdownMenu.Label class="text-xs text-muted-foreground">Mis Compañías</DropdownMenu.Label>
|
|
|
|
{#if companyStore.loading}
|
|
<DropdownMenu.Item disabled class="gap-2 p-2">
|
|
<span class="text-muted-foreground">Cargando...</span>
|
|
</DropdownMenu.Item>
|
|
{:else if companyStore.companies.length === 0}
|
|
<DropdownMenu.Item disabled class="gap-2 p-2">
|
|
<span class="text-muted-foreground">No hay compañías disponibles</span>
|
|
</DropdownMenu.Item>
|
|
{:else}
|
|
{#each companyStore.companies as company, index (company.id)}
|
|
<DropdownMenu.Item
|
|
onSelect={() => companyStore.setActiveCompany(company)}
|
|
class="cursor-pointer gap-2 p-2"
|
|
>
|
|
<div
|
|
class="flex size-6 items-center justify-center overflow-hidden rounded-md border"
|
|
>
|
|
{#if company.logo}
|
|
<img
|
|
src={getBackendAssetUrl(`v1/a76/company/${company.id}/logo/image`)}
|
|
alt={company.name}
|
|
class="size-full rounded object-cover"
|
|
/>
|
|
{:else}
|
|
<span class="text-xs font-semibold">{company.name.slice(0, 2).toUpperCase()}</span
|
|
>
|
|
{/if}
|
|
</div>
|
|
<div class="flex min-w-0 flex-1 flex-col">
|
|
<span class="truncate font-medium">{company.name}</span>
|
|
{#if company.rfc}
|
|
<span class="truncate text-xs text-muted-foreground">{company.rfc}</span>
|
|
{/if}
|
|
</div>
|
|
{#if companyStore.activeCompany?.id === company.id}
|
|
<CheckIcon class="ml-auto size-4 text-primary" />
|
|
{/if}
|
|
{#if index < 9}
|
|
<DropdownMenu.Shortcut>⌘{index + 1}</DropdownMenu.Shortcut>
|
|
{/if}
|
|
</DropdownMenu.Item>
|
|
{/each}
|
|
{/if}
|
|
</DropdownMenu.Content>
|
|
</DropdownMenu.Root>
|
|
</Sidebar.MenuItem>
|
|
</Sidebar.Menu>
|