89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import { api } from "@/lib/api";
|
|
import type { TenantWithRole } from "@/lib/types";
|
|
import { ChevronsUpDown } from "lucide-react";
|
|
import { useEffect, useRef, useState } from "react";
|
|
|
|
export function TenantSwitcher() {
|
|
const [tenants, setTenants] = useState<TenantWithRole[]>([]);
|
|
const [current, setCurrent] = useState<TenantWithRole | null>(null);
|
|
const [open, setOpen] = useState(false);
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
api
|
|
.get<TenantWithRole[]>("/tenants")
|
|
.then((data) => {
|
|
if (!Array.isArray(data)) return;
|
|
setTenants(data);
|
|
const savedId = localStorage.getItem("kanzlai_tenant_id");
|
|
const match = data.find((t) => t.id === savedId) || data[0];
|
|
if (match) {
|
|
setCurrent(match);
|
|
localStorage.setItem("kanzlai_tenant_id", match.id);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
// Not authenticated or no tenants
|
|
});
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
function handleClick(e: MouseEvent) {
|
|
if (ref.current && !ref.current.contains(e.target as Node)) {
|
|
setOpen(false);
|
|
}
|
|
}
|
|
document.addEventListener("mousedown", handleClick);
|
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
}, []);
|
|
|
|
function switchTenant(tenant: TenantWithRole) {
|
|
setCurrent(tenant);
|
|
localStorage.setItem("kanzlai_tenant_id", tenant.id);
|
|
setOpen(false);
|
|
window.location.reload();
|
|
}
|
|
|
|
if (!current) return null;
|
|
|
|
return (
|
|
<div ref={ref} className="relative">
|
|
<button
|
|
onClick={() => setOpen(!open)}
|
|
className="flex items-center gap-1.5 rounded-md border border-neutral-200 bg-white px-2.5 py-1.5 text-sm text-neutral-700 transition-colors hover:bg-neutral-50"
|
|
>
|
|
<span className="max-w-[200px] truncate sm:max-w-[280px]">
|
|
{current.name}
|
|
</span>
|
|
<ChevronsUpDown className="h-3.5 w-3.5 text-neutral-400" />
|
|
</button>
|
|
|
|
{open && (
|
|
<div className="animate-fade-in absolute right-0 top-full z-50 mt-1 w-64 rounded-md border border-neutral-200 bg-white py-1 shadow-lg">
|
|
{tenants.map((tenant) => (
|
|
<button
|
|
key={tenant.id}
|
|
onClick={() => switchTenant(tenant)}
|
|
className={`flex w-full items-center px-3 py-2 text-left text-sm transition-colors ${
|
|
tenant.id === current.id
|
|
? "bg-neutral-50 font-medium text-neutral-900"
|
|
: "text-neutral-600 hover:bg-neutral-50"
|
|
}`}
|
|
>
|
|
<span className="truncate">{tenant.name}</span>
|
|
<span className="ml-auto shrink-0 text-xs text-neutral-400">
|
|
{tenant.role}
|
|
</span>
|
|
</button>
|
|
))}
|
|
{tenants.length <= 1 && (
|
|
<p className="px-3 py-2 text-xs text-neutral-400">Einzige Kanzlei</p>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|