import { useState, useEffect } from "react"; import type { ReactElement } from "react"; import { Layout } from "@/components/layout/Layout"; import { PrimaryButton, StatusBadge, ActionDropdown, // DeleteConfirmationModal, DataTable, Pagination, FilterDropdown, SearchBox, type Column, } from "@/components/shared"; // Note: NewTenantModal, ViewTenantModal, EditTenantModal are now in @/components/superadmin (commented out - using wizard/details/edit pages instead) import { Plus, ArrowUpDown } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { tenantService } from "@/services/tenant-service"; import type { Tenant } from "@/types/tenant"; // Helper function to get tenant initials const getTenantInitials = (name: string): string => { const words = name.trim().split(/\s+/); if (words.length >= 2) { return `${words[0][0]}${words[1][0]}`.toUpperCase(); } return name.substring(0, 2).toUpperCase(); }; // Helper function to format date const formatDate = (dateString: string): string => { const date = new Date(dateString); return date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", }); }; // Helper function to get status badge variant const getStatusVariant = ( status: string, ): "success" | "failure" | "process" => { switch (status.toLowerCase()) { case "active": return "success"; case "deleted": return "failure"; case "suspended": return "process"; default: return "success"; } }; // Helper function to format subscription tier const formatSubscriptionTier = (tier: string | null): string => { if (!tier) return "N/A"; return tier.charAt(0).toUpperCase() + tier.slice(1); }; const Tenants = (): ReactElement => { const navigate = useNavigate(); const [tenants, setTenants] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // const [isModalOpen, setIsModalOpen] = useState(false); // Commented out - using wizard instead // const [isCreating, setIsCreating] = useState(false); // Commented out - using wizard instead // Pagination state const [currentPage, setCurrentPage] = useState(1); const [limit, setLimit] = useState(5); const [pagination, setPagination] = useState<{ page: number; limit: number; total: number; totalPages: number; hasMore: boolean; }>({ page: 1, limit: 5, total: 0, totalPages: 1, hasMore: false, }); // Filter state const [statusFilter, setStatusFilter] = useState(null); const [orderBy, setOrderBy] = useState(null); // Search state const [search, setSearch] = useState(""); const [debouncedSearch, setDebouncedSearch] = useState(""); // View, Edit, Delete modals // const [viewModalOpen, setViewModalOpen] = useState(false); // Commented out - using details page instead // const [editModalOpen, setEditModalOpen] = useState(false); // Commented out - using edit page instead // const [deleteModalOpen, setDeleteModalOpen] = useState(false); // const [selectedTenantId, setSelectedTenantId] = useState(null); // const [selectedTenantName, setSelectedTenantName] = useState(""); // const [isDeleting, setIsDeleting] = useState(false); const fetchTenants = async ( page: number, itemsPerPage: number, status: string | null = null, sortBy: string[] | null = null, searchQuery: string | null = null, ): Promise => { try { setIsLoading(true); setError(null); const response = await tenantService.getAll( page, itemsPerPage, status, sortBy, searchQuery, ); if (response.success) { setTenants(response.data); setPagination(response.pagination); } else { setError("Failed to load tenants"); } } catch (err: any) { setError(err?.response?.data?.error?.message || "Failed to load tenants"); } finally { setIsLoading(false); } }; useEffect(() => { const timer = setTimeout(() => { setDebouncedSearch(search); // We only reset to first page if we are actively searching. if (search) setCurrentPage(1); }, 500); return () => clearTimeout(timer); }, [search]); useEffect(() => { fetchTenants(currentPage, limit, statusFilter, orderBy, debouncedSearch); }, [currentPage, limit, statusFilter, orderBy, debouncedSearch]); // Commented out - using wizard instead // const handleCreateTenant = async (data: { // name: string; // slug: string; // status: 'active' | 'suspended' | 'deleted'; // settings?: Record | null; // subscription_tier?: string | null; // max_users?: number | null; // max_modules?: number | null; // }): Promise => { // try { // setIsCreating(true); // const response = await tenantService.create(data); // const message = response.message || `Tenant created successfully`; // const description = response.message ? undefined : `${data.name} has been added`; // showToast.success(message, description); // // Close modal and refresh tenant list // setIsModalOpen(false); // await fetchTenants(currentPage, limit, statusFilter, orderBy); // } catch (err: any) { // throw err; // Let the modal handle the error display // } finally { // setIsCreating(false); // } // }; // View tenant handler const handleViewTenant = (tenantId: string): void => { navigate(`/tenants/${tenantId}`); }; // Edit tenant handler const handleEditTenant = (tenantId: string): void => { navigate(`/tenants/${tenantId}/edit`); }; // Update tenant handler - removed, now handled in EditTenant page // Delete tenant handler // const handleDeleteTenant = (tenantId: string, tenantName: string): void => { // setSelectedTenantId(tenantId); // setSelectedTenantName(tenantName); // setDeleteModalOpen(true); // }; // Confirm delete handler // const handleConfirmDelete = async (): Promise => { // if (!selectedTenantId) return; // try { // setIsDeleting(true); // await tenantService.delete(selectedTenantId); // setDeleteModalOpen(false); // setSelectedTenantId(null); // setSelectedTenantName(""); // await fetchTenants(currentPage, limit, statusFilter, orderBy); // } catch (err: any) { // throw err; // Let the modal handle the error display // } finally { // setIsDeleting(false); // } // }; // Define table columns const columns: Column[] = [ { key: "name", label: "Tenant Name", render: (tenant) => (
navigate(`/tenants/${tenant.id}`)} >
{tenant.name.substring(0, 2).toUpperCase()}
{tenant.name} {tenant?.slug}
//
//
// // {getTenantInitials(tenant.name)} // //
// // {tenant.name} // //
), mobileLabel: "Name", }, { key: "status", label: "Status", render: (tenant) => ( {tenant.status} ), }, { key: "user_count", label: "Users", render: (tenant) => ( {tenant.user_count ?? 0} ), }, { key: "subscription_tier", label: "Subscription Tier", render: (tenant) => ( {formatSubscriptionTier(tenant.subscription_tier)} ), }, { key: "module_count", label: "Modules", render: (tenant) => ( {tenant.module_count ?? 0} ), }, { key: "created_at", label: "Joined Date", render: (tenant) => ( {formatDate(tenant.created_at)} ), mobileLabel: "Joined", }, { key: "actions", label: "Actions", align: "right", render: (tenant) => (
handleViewTenant(tenant.id)} onEdit={() => handleEditTenant(tenant.id)} // onDelete={() => handleDeleteTenant(tenant.id, tenant.name)} />
), }, ]; // Mobile card renderer const mobileCardRenderer = (tenant: Tenant) => (
navigate(`/tenants/${tenant.id}`)} >
{getTenantInitials(tenant.name)}

{tenant.name}

{formatDate(tenant.created_at)}

handleViewTenant(tenant.id)} onEdit={() => handleEditTenant(tenant.id)} // onDelete={() => handleDeleteTenant(tenant.id, tenant.name)} />
Status:
{tenant.status}
Plan:

{formatSubscriptionTier(tenant.subscription_tier)}

Users:

{tenant.max_users ?? "N/A"}

Modules:

{tenant.max_modules ?? "N/A"}

); return ( {/* Table Container */}
{/* Table Header with Filters */}
{/* Search & Filters */}
{/* Global Search */} {/* Status Filter */} { setStatusFilter(value as string | null); setCurrentPage(1); // Reset to first page when filter changes }} placeholder="All" /> {/* Sort Filter */} { setOrderBy(value as string[] | null); setCurrentPage(1); // Reset to first page when sort changes }} placeholder="Default" showIcon icon={} />
{/* Actions */}
{/* Export Button */} {/* */} {/* New Tenant Button (Old) - Commented out, using wizard instead */} {/* setIsModalOpen(true)} > New Tenant */} {/* Add Tenant Button (New Wizard) */} navigate("/tenants/create-wizard")} > Add Tenant
{/* Data Table */} tenant.id} mobileCardRenderer={mobileCardRenderer} emptyMessage="No tenants found" isLoading={isLoading} error={error} /> {/* Table Footer with Pagination */} {pagination.total > 0 && ( { setCurrentPage(page); }} onLimitChange={(newLimit: number) => { setLimit(newLimit); setCurrentPage(1); // Reset to first page when limit changes }} /> )}
{/* Delete Confirmation Modal */} {/* { setDeleteModalOpen(false); setSelectedTenantId(null); setSelectedTenantName(""); }} onConfirm={handleConfirmDelete} title="Delete Tenant" message="Are you sure you want to delete this tenant" itemName={selectedTenantName} isLoading={isDeleting} /> */}
); }; export default Tenants;