Files
L-Ami-Fiduciaire/resources/js/components/WorkspaceSwitcher.vue

168 lines
6.4 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import { computed, ref } from 'vue';
import { router, usePage } from '@inertiajs/vue3';
import { BoxSelect, Check, ChevronsUpDown } from 'lucide-vue-next';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from '@/components/ui/sidebar';
const page = usePage();
const { isMobile } = useSidebar();
const workspaces = computed(() => page.props.auth?.workspaces ?? []);
const currentWorkspace = computed(
() => page.props.auth?.currentWorkspace ?? null,
);
const workspaceSwitchUrl = computed(
() => page.props.auth?.workspaceSwitchUrl ?? '',
);
const canSwitch = computed(() => workspaces.value.length > 1);
const isSwitching = ref(false);
function getInitial(name: string): string {
return name.charAt(0).toUpperCase();
}
function switchWorkspace(workspace: { id: number }) {
if (isSwitching.value || workspace.id === currentWorkspace.value?.id) {
return;
}
isSwitching.value = true;
router.post(
workspaceSwitchUrl.value,
{ workspace_id: workspace.id },
{
preserveState: false,
onFinish: () => {
isSwitching.value = false;
},
},
);
}
</script>
<template>
<SidebarMenu v-if="workspaces.length > 0">
<SidebarMenuItem>
<!-- Multi-workspace: show dropdown -->
<DropdownMenu v-if="canSwitch">
<DropdownMenuTrigger as-child :disabled="isSwitching">
<SidebarMenuButton
size="lg"
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<div
class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sm font-semibold text-sidebar-primary-foreground"
>
{{
currentWorkspace
? getInitial(currentWorkspace.name)
: '?'
}}
</div>
<div
class="grid flex-1 text-left text-sm leading-tight"
>
<span class="truncate font-medium">
{{
currentWorkspace?.name ?? 'Select workspace'
}}
</span>
<span
v-if="currentWorkspace"
class="truncate text-xs text-muted-foreground"
>
{{ currentWorkspace.slug }}
</span>
</div>
<ChevronsUpDown class="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
class="w-[--reka-dropdown-menu-trigger-width] min-w-56 rounded-lg"
align="start"
:side="isMobile ? 'bottom' : 'right'"
:side-offset="4"
>
<DropdownMenuLabel class="text-xs text-muted-foreground">
Workspaces
</DropdownMenuLabel>
<DropdownMenuItem
v-for="workspace in workspaces"
:key="workspace.id"
class="gap-2 p-2"
:disabled="isSwitching"
@click="switchWorkspace(workspace)"
>
<div
class="flex size-6 items-center justify-center rounded-sm border text-xs font-semibold"
>
{{ getInitial(workspace.name) }}
</div>
<div class="flex flex-1 flex-col">
<span>{{ workspace.name }}</span>
<span class="text-xs text-muted-foreground">{{
workspace.slug
}}</span>
</div>
<Check
v-if="currentWorkspace?.id === workspace.id"
class="ml-auto size-4 text-primary"
/>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<!-- Single workspace: static display -->
<SidebarMenuButton v-else size="lg">
<div
class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sm font-semibold text-sidebar-primary-foreground"
>
{{
currentWorkspace
? getInitial(currentWorkspace.name)
: '?'
}}
</div>
<div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-medium">
{{ currentWorkspace?.name ?? 'Select workspace' }}
</span>
<span
v-if="currentWorkspace"
class="truncate text-xs text-muted-foreground"
>
{{ currentWorkspace.slug }}
</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
<SidebarMenu v-else>
<SidebarMenuItem>
<SidebarMenuButton size="lg" as-child>
<div class="flex items-center gap-2 text-muted-foreground">
<div
class="flex aspect-square size-8 items-center justify-center rounded-lg border border-dashed"
>
<BoxSelect class="size-4" />
</div>
<span class="text-sm">No workspaces found</span>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</template>