Feat(Fix): Multi Org, Suspension, User Detail

Multi Org switch, members suspend/unsuspend status, delete account, next serial, show email in user member search
This commit is contained in:
2026-03-02 23:55:47 +05:45
parent 6cab506603
commit b97937f080
16 changed files with 2011 additions and 298 deletions
-1
View File
@@ -56,7 +56,6 @@ const orgAdminNavItems = [
];
const adminNavItems = [
{ title: "Users", url: "/admin/users", icon: Users },
{ title: "Certificate Auth.", url: "/org/cas", icon: ShieldCheck },
{ title: "Org Audit Log", url: "/org/audit", icon: FileText },
{ title: "System Logs", url: "/admin/audit", icon: ScrollText },
+6 -14
View File
@@ -1,4 +1,3 @@
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Menu, ChevronDown, LogOut, User, Shield, Building2, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
@@ -13,28 +12,21 @@ import {
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { useAuth } from "@/contexts/AuthContext";
import { Organization } from "@/lib/api";
import { useOrg } from "@/contexts/OrgContext";
import { useOrganizations } from "@/hooks/useOrganizations";
import { ComplianceBanner } from "@/components/auth/ComplianceBanner";
export function TopBar() {
const navigate = useNavigate();
const { user, isAuthenticated, mfaCompliance, logout } = useAuth();
const [currentOrg, setCurrentOrg] = useState<Organization | null>(null);
const { user, mfaCompliance, logout } = useAuth();
const { selectedOrg, selectOrg } = useOrg();
// Use React Query hook for organizations with automatic caching and deduplication
const { data: organizations = [], isLoading: orgsLoading } = useOrganizations();
// Ensure organizations is always an array (defensive check)
const organizationsArray = Array.isArray(organizations) ? organizations : [];
// Set initial currentOrg when organizations are loaded
useEffect(() => {
if (organizationsArray.length > 0 && !currentOrg) {
setCurrentOrg(organizationsArray[0]);
}
}, [organizationsArray, currentOrg]);
const handleLogout = async () => {
await logout();
};
@@ -64,7 +56,7 @@ export function TopBar() {
<Building2 className="w-3.5 h-3.5 text-primary" />
</div>
<span className="text-sm font-medium hidden sm:inline">
{orgsLoading ? "Loading..." : (currentOrg?.name || "No Organization")}
{orgsLoading ? "Loading..." : (selectedOrg?.name || "No Organization")}
</span>
<ChevronDown className="w-4 h-4 text-muted-foreground" />
</Button>
@@ -86,7 +78,7 @@ export function TopBar() {
organizationsArray.map((org) => (
<DropdownMenuItem
key={org.id}
onClick={() => setCurrentOrg(org)}
onClick={() => selectOrg(org)}
className="flex items-center justify-between"
>
<div className="flex items-center gap-2">