import { useState, useEffect } from 'react'; import type { ReactElement } from 'react'; import { Layout } from '@/components/layout/Layout'; import { StatusBadge, ViewModuleModal, DataTable, Pagination, FilterDropdown, type Column, } from '@/components/shared'; import { Download, ArrowUpDown } from 'lucide-react'; import { moduleService } from '@/services/module-service'; import type { Module } from '@/types/module'; // 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 | null): 'success' | 'failure' | 'process' => { if (!status) return 'process'; switch (status.toLowerCase()) { case 'running': case 'active': case 'healthy': return 'success'; case 'stopped': case 'failed': case 'unhealthy': return 'failure'; default: return 'process'; } }; const Modules = (): ReactElement => { const [modules, setModules] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // 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); // View modal const [viewModalOpen, setViewModalOpen] = useState(false); const [selectedModuleId, setSelectedModuleId] = useState(null); const fetchModules = async ( page: number, itemsPerPage: number, status: string | null = null, sortBy: string[] | null = null ): Promise => { try { setIsLoading(true); setError(null); const response = await moduleService.getAll(page, itemsPerPage, status, sortBy); if (response.success) { setModules(response.data); setPagination(response.pagination); } else { setError('Failed to load modules'); } } catch (err: any) { setError(err?.response?.data?.error?.message || 'Failed to load modules'); } finally { setIsLoading(false); } }; // Fetch modules on mount and when pagination/filters change useEffect(() => { fetchModules(currentPage, limit, statusFilter, orderBy); }, [currentPage, limit, statusFilter, orderBy]); // View module handler const handleViewModule = (moduleId: string): void => { setSelectedModuleId(moduleId); setViewModalOpen(true); }; // Load module for view const loadModule = async (id: string): Promise => { const response = await moduleService.getById(id); return response.data; }; // Define table columns const columns: Column[] = [ { key: 'name', label: 'Module Name', render: (module) => (
{module.name.substring(0, 2).toUpperCase()}
{module.name} {module.module_id}
), mobileLabel: 'Name', }, { key: 'description', label: 'Description', render: (module) => ( {module.description} ), }, { key: 'version', label: 'Version', render: (module) => ( {module.version} ), }, { key: 'status', label: 'Status', render: (module) => ( {module.status || 'Unknown'} ), }, { key: 'health_status', label: 'Health Status', render: (module) => ( {module.health_status || 'N/A'} ), }, { key: 'runtime_language', label: 'Runtime', render: (module) => ( {module.runtime_language || 'N/A'} ), }, { key: 'created_at', label: 'Registered Date', render: (module) => ( {formatDate(module.created_at)} ), mobileLabel: 'Registered', }, { key: 'actions', label: 'Actions', align: 'right', render: (module) => (
), }, ]; // Mobile card renderer const mobileCardRenderer = (module: Module) => (
{module.name.substring(0, 2).toUpperCase()}

{module.name}

{module.module_id}

Status:
{module.status || 'Unknown'}
Health:
{module.health_status || 'N/A'}
Version:

{module.version}

Runtime:

{module.runtime_language || 'N/A'}

Registered:

{formatDate(module.created_at)}

Description:

{module.description}

); return ( {/* Table Container */}
{/* Table Header with Filters */}
{/* Filters */}
{/* Status Filter */} { setStatusFilter(value as string | null); setCurrentPage(1); }} placeholder="All" /> {/* Sort Filter */} { setOrderBy(value as string[] | null); setCurrentPage(1); }} placeholder="Default" showIcon icon={} />
{/* Actions */}
{/* Export Button */}
{/* Table */} module.id} isLoading={isLoading} error={error} mobileCardRenderer={mobileCardRenderer} emptyMessage="No modules found" /> {/* Pagination */} {pagination.total > 0 && (
setCurrentPage(page)} onLimitChange={(newLimit: number) => { setLimit(newLimit); setCurrentPage(1); }} />
)}
{/* View Module Modal */} { setViewModalOpen(false); setSelectedModuleId(null); }} moduleId={selectedModuleId} onLoadModule={loadModule} />
); }; export default Modules;