104 lines
No EOL
3.5 KiB
TypeScript
104 lines
No EOL
3.5 KiB
TypeScript
"use client";
|
|
import { useEffect, useState } from "react";
|
|
|
|
type Org = { id: string; name: string; structure_api: string | null };
|
|
|
|
type Props = {
|
|
visible: boolean;
|
|
};
|
|
|
|
export function OrganizationSwitcher({ visible }: Props) {
|
|
const [orgs, setOrgs] = useState<Org[]>([]);
|
|
const [activeId, setActiveId] = useState<string>("");
|
|
|
|
useEffect(() => {
|
|
if (!visible) return;
|
|
(async () => {
|
|
try {
|
|
const res = await fetch("/api/organizations", { credentials: "include", cache: "no-store" });
|
|
const raw = await res.text();
|
|
if (!res.ok) {
|
|
console.error("/api/organizations error", res.status, raw);
|
|
setOrgs([]);
|
|
return;
|
|
}
|
|
const json: any = raw ? JSON.parse(raw) : { items: [] };
|
|
const items: Org[] = json.items || [];
|
|
setOrgs(items);
|
|
|
|
// Déterminer l'org active au chargement via /api/me
|
|
if (!activeId && items.length) {
|
|
try {
|
|
const meRes = await fetch("/api/me", { credentials: "include", cache: "no-store" });
|
|
if (meRes.ok) {
|
|
const meData = await meRes.json();
|
|
if (meData.active_org_id && items.some(o => o.id === meData.active_org_id)) {
|
|
setActiveId(meData.active_org_id);
|
|
// Mirror in localStorage so client-side fetcher can include header immediately
|
|
if (typeof window !== "undefined") {
|
|
try { localStorage.setItem("active_org_id", meData.active_org_id); } catch {}
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.warn("Could not fetch current org from /api/me", err);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error("Failed to load organizations", err);
|
|
setOrgs([]);
|
|
}
|
|
})();
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [visible]);
|
|
|
|
async function onChange(id: string) {
|
|
const org = orgs.find(o => o.id === id);
|
|
if (!org) return;
|
|
|
|
// Utiliser l'API pour mettre à jour l'organisation active
|
|
try {
|
|
const response = await fetch("/api/active-org", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ org_id: org.id }),
|
|
credentials: "include",
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text();
|
|
console.error("Failed to set active org:", response.status, errorText);
|
|
return;
|
|
}
|
|
|
|
// Mettre à jour l'état local
|
|
setActiveId(id);
|
|
|
|
// Mettre à jour le localStorage pour l'affichage UI et pour que
|
|
// lib/fetcher puisse envoyer immédiatement le header x-active-org-id
|
|
if (typeof window !== "undefined") {
|
|
try {
|
|
localStorage.setItem("company_name", org.structure_api || org.name);
|
|
localStorage.setItem("active_org_id", org.id);
|
|
} catch {}
|
|
}
|
|
|
|
// Recharger pour que toutes les pages voient le changement côté serveur
|
|
window.location.reload();
|
|
} catch (error) {
|
|
console.error("Error setting active organization:", error);
|
|
}
|
|
}
|
|
|
|
if (!visible) return null;
|
|
return (
|
|
<select
|
|
value={activeId}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
className="px-3 py-1.5 rounded-lg border text-sm"
|
|
>
|
|
<option value="" disabled>Sélectionner un client…</option>
|
|
{orgs.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}
|
|
</select>
|
|
);
|
|
} |