@iblai/iblai-js 1.17.3 → 1.17.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -87075,11 +87075,11 @@ function UsersTab({ tenant, currentPage, itemsPerPage, onInviteSuccess }) {
87075
87075
  return 'Accepted';
87076
87076
  };
87077
87077
  const isFormValid = !emailError && debouncedEmail.trim().length > 0;
87078
- return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "overflow-x-auto w-full scrollbar-hide", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "overflow-hidden rounded-lg border border-gray-200 w-full", children: jsxs("table", { className: "w-full divide-y divide-gray-200", children: [jsx("thead", { className: "bg-gray-50", children: jsxs("tr", { children: [jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[150px]", children: "Email" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: isLoadingInvitedUsers ? (
87078
+ return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingInvitedUsers ? (
87079
87079
  // Loading skeleton rows
87080
- Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
87080
+ Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
87081
87081
  // Empty state
87082
- jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-4 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(Mail, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by inviting users above or uploading a CSV file" })] }) }) })) : (currentUsers.map((user) => (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center", children: jsx(Mail, { className: "h-4 w-4 text-blue-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: user.email || 'No email' }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(user.active, user.expired)}`, children: [user.active && !user.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !user.active && !user.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), user.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(user.active, user.expired)] }) })] }, user.id)))) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
87082
+ jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(Mail, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by inviting users above or uploading a CSV file" })] }) }) })) : (currentUsers.map((user) => (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center", children: jsx(Mail, { className: "h-4 w-4 text-blue-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: user.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(user.active, user.expired)}`, children: [user.active && !user.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !user.active && !user.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), user.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(user.active, user.expired)] }) })] }, user.id)))) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
87083
87083
  }
87084
87084
 
87085
87085
  function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermission = false, }) {
@@ -87446,15 +87446,15 @@ function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissio
87446
87446
  else {
87447
87447
  setSelectedCourses(selectedCourses.filter((c) => c.id !== course.id));
87448
87448
  }
87449
- } }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "overflow-x-auto w-full scrollbar-hide", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "overflow-hidden rounded-lg border border-gray-200 w-full", children: jsxs("table", { className: "w-full divide-y divide-gray-200", children: [jsx("thead", { className: "bg-gray-50", children: jsxs("tr", { children: [jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[150px]", children: "Email" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[200px]", children: "Course" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: isLoadingData ? (
87449
+ } }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Course" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
87450
87450
  // Loading skeleton rows
87451
- Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
87451
+ Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
87452
87452
  // Empty state
87453
- jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-4 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(BookOpen, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No course invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and courses above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
87453
+ jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(BookOpen, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No course invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and courses above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
87454
87454
  var _a;
87455
- return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-green-100 flex items-center justify-center", children: jsx(BookOpen, { className: "h-4 w-4 text-green-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.course_id ||
87455
+ return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-green-100 flex items-center justify-center", children: jsx(BookOpen, { className: "h-4 w-4 text-green-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.course_id ||
87456
87456
  ((_a = invitation.course) === null || _a === void 0 ? void 0 : _a.name) ||
87457
- 'Unknown Course' }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
87457
+ 'Unknown Course' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
87458
87458
  })) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
87459
87459
  }
87460
87460
 
@@ -87823,15 +87823,15 @@ function ProgramsTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissi
87823
87823
  else {
87824
87824
  setSelectedPrograms(selectedPrograms.filter((p) => p.id !== program.id));
87825
87825
  }
87826
- } }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "overflow-x-auto w-full scrollbar-hide", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "overflow-hidden rounded-lg border border-gray-200 w-full", children: jsxs("table", { className: "w-full divide-y divide-gray-200", children: [jsx("thead", { className: "bg-gray-50", children: jsxs("tr", { children: [jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[150px]", children: "Email" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[200px]", children: "Program" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: isLoadingData ? (
87826
+ } }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Program" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
87827
87827
  // Loading skeleton rows
87828
- Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
87828
+ Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
87829
87829
  // Empty state
87830
- jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-4 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(GraduationCap, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No program invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and programs above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
87830
+ jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(GraduationCap, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No program invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and programs above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
87831
87831
  var _a;
87832
- return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-purple-100 flex items-center justify-center", children: jsx(GraduationCap, { className: "h-4 w-4 text-purple-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.program_key ||
87832
+ return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-purple-100 flex items-center justify-center", children: jsx(GraduationCap, { className: "h-4 w-4 text-purple-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.program_key ||
87833
87833
  ((_a = invitation.program) === null || _a === void 0 ? void 0 : _a.name) ||
87834
- 'Unknown Program' }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
87834
+ 'Unknown Program' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
87835
87835
  })) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
87836
87836
  }
87837
87837
 
@@ -87916,7 +87916,7 @@ function InviteUserDialog({ tenant, onClose, isOpen, enableCatalogInvite = false
87916
87916
  }
87917
87917
  };
87918
87918
  const headerContent = getHeaderContent();
87919
- return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-5xl w-[95vw] p-0 gap-0 mx-auto my-auto rounded-lg flex flex-col justify-between max-h-[90vh]", "aria-describedby": "invite-users-description", children: [jsxs(DialogHeader, { className: "p-4 pt-[30px] flex-shrink-0 border-b border-gray-200", children: [jsx(DialogTitle, { className: "text-xl sm:text-2xl font-bold text-gray-800", children: headerContent.title }), jsx(DialogDescription, { id: "invite-users-description", className: "mt-1 text-xs sm:text-sm text-gray-700", children: headerContent.description })] }), jsx("div", { className: "flex-grow overflow-y-auto scrollbar-hide p-2 sm:p-4 pb-20 max-h-[60vh]", children: enableCatalogInvite ? (jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [jsxs(TabsList, { className: "grid w-full grid-cols-3 mb-6", children: [jsxs(TabsTrigger, { value: "users", className: "flex items-center gap-2", children: [jsx(Users, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Users" })] }), jsxs(TabsTrigger, { value: "courses", className: "flex items-center gap-2", children: [jsx(BookOpen, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Courses" })] }), jsxs(TabsTrigger, { value: "programs", className: "flex items-center gap-2", children: [jsx(GraduationCap, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Programs" })] })] }), jsx(TabsContent, { value: "users", children: jsx(UsersTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess }) }), jsx(TabsContent, { value: "courses", children: jsx(CoursesTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) }), jsx(TabsContent, { value: "programs", children: jsx(ProgramsTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) })] })) : (jsx(UsersTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess })) }), currentData && currentData.count > 0 && (jsx("div", { className: "flex items-center justify-between border-t border-gray-200 px-3 sm:px-6 py-3 sm:py-4 bg-gray-50 flex-shrink-0", children: jsxs("div", { className: "flex flex-1 items-center justify-between", children: [jsx("div", { className: "hidden sm:block", children: jsxs("p", { className: "text-sm text-gray-700", children: ["Showing", ' ', jsx("span", { className: "font-medium", children: (currentPage - 1) * itemsPerPage + 1 }), " to", ' ', jsx("span", { className: "font-medium", children: Math.min(currentPage * itemsPerPage, currentData.count) }), ' ', "of ", jsx("span", { className: "font-medium", children: currentData.count }), " invites"] }) }), jsxs("div", { className: "flex items-center justify-center gap-1 sm:gap-2", children: [jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(1), disabled: currentPage === 1, "aria-label": "Go to first page", children: jsx(ChevronFirst, { className: "h-4 w-4" }) }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: [jsx(ChevronLeft, { className: "h-4 w-4 mr-1 sm:mr-0" }), jsx("span", { className: "sm:hidden", children: "Prev" })] }), jsxs("span", { className: "text-xs sm:text-sm text-gray-700 mx-1 sm:mx-2 px-2", children: [jsx("span", { className: "hidden sm:inline", children: "Page " }), currentPage, " ", jsx("span", { className: "hidden sm:inline", children: "of " }), jsx("span", { className: "inline sm:hidden", children: " / " }), totalPages] }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: [jsx("span", { className: "sm:hidden", children: "Next" }), jsx(ChevronRight, { className: "h-4 w-4 ml-1 sm:ml-0" })] }), jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(totalPages), disabled: currentPage === totalPages, "aria-label": "Go to last page", children: jsx(ChevronLast, { className: "h-4 w-4" }) })] })] }) }))] }) }) }));
87919
+ return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-7xl w-[95vw] p-0 gap-0 mx-auto my-auto rounded-lg flex flex-col justify-between max-h-[90vh]", "aria-describedby": "invite-users-description", children: [jsxs(DialogHeader, { className: "p-4 pt-[30px] flex-shrink-0 border-b border-gray-200", children: [jsx(DialogTitle, { className: "text-lg font-medium text-gray-900 dark:text-gray-100", children: headerContent.title }), jsx(DialogDescription, { id: "invite-users-description", className: "text-sm text-gray-600 leading-relaxed", children: headerContent.description })] }), jsx("div", { className: "flex-grow overflow-y-auto scrollbar-hide p-2 sm:p-4 pb-20 max-h-[60vh]", children: enableCatalogInvite ? (jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [jsxs(TabsList, { className: "grid w-full grid-cols-3 mb-6", children: [jsxs(TabsTrigger, { value: "users", className: "flex items-center gap-2", children: [jsx(Users, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Users" })] }), jsxs(TabsTrigger, { value: "courses", className: "flex items-center gap-2", children: [jsx(BookOpen, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Courses" })] }), jsxs(TabsTrigger, { value: "programs", className: "flex items-center gap-2", children: [jsx(GraduationCap, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Programs" })] })] }), jsx(TabsContent, { value: "users", children: jsx(UsersTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess }) }), jsx(TabsContent, { value: "courses", children: jsx(CoursesTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) }), jsx(TabsContent, { value: "programs", children: jsx(ProgramsTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) })] })) : (jsx(UsersTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess })) }), currentData && currentData.count > 0 && (jsx("div", { className: "flex items-center justify-between border-t border-gray-200 px-3 sm:px-6 py-3 sm:py-4 bg-gray-50 flex-shrink-0", children: jsxs("div", { className: "flex flex-1 items-center justify-between", children: [jsx("div", { className: "hidden sm:block", children: jsxs("p", { className: "text-sm text-gray-700", children: ["Showing", ' ', jsx("span", { className: "font-medium", children: (currentPage - 1) * itemsPerPage + 1 }), " to", ' ', jsx("span", { className: "font-medium", children: Math.min(currentPage * itemsPerPage, currentData.count) }), ' ', "of ", jsx("span", { className: "font-medium", children: currentData.count }), " invites"] }) }), jsxs("div", { className: "flex items-center justify-center gap-1 sm:gap-2", children: [jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(1), disabled: currentPage === 1, "aria-label": "Go to first page", children: jsx(ChevronFirst, { className: "h-4 w-4" }) }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: [jsx(ChevronLeft, { className: "h-4 w-4 mr-1 sm:mr-0" }), jsx("span", { className: "sm:hidden", children: "Prev" })] }), jsxs("span", { className: "text-xs sm:text-sm text-gray-700 mx-1 sm:mx-2 px-2", children: [jsx("span", { className: "hidden sm:inline", children: "Page " }), currentPage, " ", jsx("span", { className: "hidden sm:inline", children: "of " }), jsx("span", { className: "inline sm:hidden", children: " / " }), totalPages] }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: [jsx("span", { className: "sm:hidden", children: "Next" }), jsx(ChevronRight, { className: "h-4 w-4 ml-1 sm:ml-0" })] }), jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(totalPages), disabled: currentPage === totalPages, "aria-label": "Go to last page", children: jsx(ChevronLast, { className: "h-4 w-4" }) })] })] }) }))] }) }) }));
87920
87920
  }
87921
87921
 
87922
87922
  function InvitedUsersDialog({ tenant, onClose, }) {
@@ -124782,11 +124782,11 @@ function UsersTab$1({ tenant, currentPage, itemsPerPage, onInviteSuccess }) {
124782
124782
  return 'Accepted';
124783
124783
  };
124784
124784
  const isFormValid = !emailError && debouncedEmail.trim().length > 0;
124785
- return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "overflow-x-auto w-full scrollbar-hide", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "overflow-hidden rounded-lg border border-gray-200 w-full", children: jsxs("table", { className: "w-full divide-y divide-gray-200", children: [jsx("thead", { className: "bg-gray-50", children: jsxs("tr", { children: [jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[150px]", children: "Email" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: isLoadingInvitedUsers ? (
124785
+ return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingInvitedUsers ? (
124786
124786
  // Loading skeleton rows
124787
- Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
124787
+ Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
124788
124788
  // Empty state
124789
- jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-4 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(Mail, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by inviting users above or uploading a CSV file" })] }) }) })) : (currentUsers.map((user) => (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center", children: jsx(Mail, { className: "h-4 w-4 text-blue-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: user.email || 'No email' }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(user.active, user.expired)}`, children: [user.active && !user.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !user.active && !user.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), user.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(user.active, user.expired)] }) })] }, user.id)))) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
124789
+ jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(Mail, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by inviting users above or uploading a CSV file" })] }) }) })) : (currentUsers.map((user) => (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center", children: jsx(Mail, { className: "h-4 w-4 text-blue-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: user.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(user.active, user.expired)}`, children: [user.active && !user.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !user.active && !user.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), user.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(user.active, user.expired)] }) })] }, user.id)))) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
124790
124790
  }
124791
124791
 
124792
124792
  function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermission = false, }) {
@@ -125153,15 +125153,15 @@ function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissio
125153
125153
  else {
125154
125154
  setSelectedCourses(selectedCourses.filter((c) => c.id !== course.id));
125155
125155
  }
125156
- } }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "overflow-x-auto w-full scrollbar-hide", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "overflow-hidden rounded-lg border border-gray-200 w-full", children: jsxs("table", { className: "w-full divide-y divide-gray-200", children: [jsx("thead", { className: "bg-gray-50", children: jsxs("tr", { children: [jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[150px]", children: "Email" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[200px]", children: "Course" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: isLoadingData ? (
125156
+ } }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Course" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
125157
125157
  // Loading skeleton rows
125158
- Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
125158
+ Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
125159
125159
  // Empty state
125160
- jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-4 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(BookOpen, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No course invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and courses above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
125160
+ jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(BookOpen, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No course invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and courses above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
125161
125161
  var _a;
125162
- return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-green-100 flex items-center justify-center", children: jsx(BookOpen, { className: "h-4 w-4 text-green-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.course_id ||
125162
+ return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-green-100 flex items-center justify-center", children: jsx(BookOpen, { className: "h-4 w-4 text-green-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.course_id ||
125163
125163
  ((_a = invitation.course) === null || _a === void 0 ? void 0 : _a.name) ||
125164
- 'Unknown Course' }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
125164
+ 'Unknown Course' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
125165
125165
  })) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
125166
125166
  }
125167
125167
 
@@ -125530,15 +125530,15 @@ function ProgramsTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissi
125530
125530
  else {
125531
125531
  setSelectedPrograms(selectedPrograms.filter((p) => p.id !== program.id));
125532
125532
  }
125533
- } }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "overflow-x-auto w-full scrollbar-hide", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "overflow-hidden rounded-lg border border-gray-200 w-full", children: jsxs("table", { className: "w-full divide-y divide-gray-200", children: [jsx("thead", { className: "bg-gray-50", children: jsxs("tr", { children: [jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[150px]", children: "Email" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[200px]", children: "Program" }), jsx("th", { className: "px-4 py-3.5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wider min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: isLoadingData ? (
125533
+ } }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Program" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
125534
125534
  // Loading skeleton rows
125535
- Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
125535
+ Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
125536
125536
  // Empty state
125537
- jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-4 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(GraduationCap, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No program invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and programs above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
125537
+ jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(GraduationCap, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No program invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and programs above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
125538
125538
  var _a;
125539
- return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-purple-100 flex items-center justify-center", children: jsx(GraduationCap, { className: "h-4 w-4 text-purple-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.program_key ||
125539
+ return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-purple-100 flex items-center justify-center", children: jsx(GraduationCap, { className: "h-4 w-4 text-purple-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.program_key ||
125540
125540
  ((_a = invitation.program) === null || _a === void 0 ? void 0 : _a.name) ||
125541
- 'Unknown Program' }) }), jsx("td", { className: "px-4 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
125541
+ 'Unknown Program' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
125542
125542
  })) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
125543
125543
  }
125544
125544
 
@@ -125623,7 +125623,7 @@ function InviteUserDialog({ tenant, onClose, isOpen, enableCatalogInvite = false
125623
125623
  }
125624
125624
  };
125625
125625
  const headerContent = getHeaderContent();
125626
- return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-5xl w-[95vw] p-0 gap-0 mx-auto my-auto rounded-lg flex flex-col justify-between max-h-[90vh]", "aria-describedby": "invite-users-description", children: [jsxs(DialogHeader, { className: "p-4 pt-[30px] flex-shrink-0 border-b border-gray-200", children: [jsx(DialogTitle, { className: "text-xl sm:text-2xl font-bold text-gray-800", children: headerContent.title }), jsx(DialogDescription, { id: "invite-users-description", className: "mt-1 text-xs sm:text-sm text-gray-700", children: headerContent.description })] }), jsx("div", { className: "flex-grow overflow-y-auto scrollbar-hide p-2 sm:p-4 pb-20 max-h-[60vh]", children: enableCatalogInvite ? (jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [jsxs(TabsList, { className: "grid w-full grid-cols-3 mb-6", children: [jsxs(TabsTrigger, { value: "users", className: "flex items-center gap-2", children: [jsx(Users, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Users" })] }), jsxs(TabsTrigger, { value: "courses", className: "flex items-center gap-2", children: [jsx(BookOpen, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Courses" })] }), jsxs(TabsTrigger, { value: "programs", className: "flex items-center gap-2", children: [jsx(GraduationCap, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Programs" })] })] }), jsx(TabsContent, { value: "users", children: jsx(UsersTab$1, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess }) }), jsx(TabsContent, { value: "courses", children: jsx(CoursesTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) }), jsx(TabsContent, { value: "programs", children: jsx(ProgramsTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) })] })) : (jsx(UsersTab$1, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess })) }), currentData && currentData.count > 0 && (jsx("div", { className: "flex items-center justify-between border-t border-gray-200 px-3 sm:px-6 py-3 sm:py-4 bg-gray-50 flex-shrink-0", children: jsxs("div", { className: "flex flex-1 items-center justify-between", children: [jsx("div", { className: "hidden sm:block", children: jsxs("p", { className: "text-sm text-gray-700", children: ["Showing", ' ', jsx("span", { className: "font-medium", children: (currentPage - 1) * itemsPerPage + 1 }), " to", ' ', jsx("span", { className: "font-medium", children: Math.min(currentPage * itemsPerPage, currentData.count) }), ' ', "of ", jsx("span", { className: "font-medium", children: currentData.count }), " invites"] }) }), jsxs("div", { className: "flex items-center justify-center gap-1 sm:gap-2", children: [jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(1), disabled: currentPage === 1, "aria-label": "Go to first page", children: jsx(ChevronFirst, { className: "h-4 w-4" }) }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: [jsx(ChevronLeft, { className: "h-4 w-4 mr-1 sm:mr-0" }), jsx("span", { className: "sm:hidden", children: "Prev" })] }), jsxs("span", { className: "text-xs sm:text-sm text-gray-700 mx-1 sm:mx-2 px-2", children: [jsx("span", { className: "hidden sm:inline", children: "Page " }), currentPage, " ", jsx("span", { className: "hidden sm:inline", children: "of " }), jsx("span", { className: "inline sm:hidden", children: " / " }), totalPages] }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: [jsx("span", { className: "sm:hidden", children: "Next" }), jsx(ChevronRight, { className: "h-4 w-4 ml-1 sm:ml-0" })] }), jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(totalPages), disabled: currentPage === totalPages, "aria-label": "Go to last page", children: jsx(ChevronLast, { className: "h-4 w-4" }) })] })] }) }))] }) }) }));
125626
+ return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-7xl w-[95vw] p-0 gap-0 mx-auto my-auto rounded-lg flex flex-col justify-between max-h-[90vh]", "aria-describedby": "invite-users-description", children: [jsxs(DialogHeader, { className: "p-4 pt-[30px] flex-shrink-0 border-b border-gray-200", children: [jsx(DialogTitle, { className: "text-lg font-medium text-gray-900 dark:text-gray-100", children: headerContent.title }), jsx(DialogDescription, { id: "invite-users-description", className: "text-sm text-gray-600 leading-relaxed", children: headerContent.description })] }), jsx("div", { className: "flex-grow overflow-y-auto scrollbar-hide p-2 sm:p-4 pb-20 max-h-[60vh]", children: enableCatalogInvite ? (jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [jsxs(TabsList, { className: "grid w-full grid-cols-3 mb-6", children: [jsxs(TabsTrigger, { value: "users", className: "flex items-center gap-2", children: [jsx(Users, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Users" })] }), jsxs(TabsTrigger, { value: "courses", className: "flex items-center gap-2", children: [jsx(BookOpen, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Courses" })] }), jsxs(TabsTrigger, { value: "programs", className: "flex items-center gap-2", children: [jsx(GraduationCap, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Programs" })] })] }), jsx(TabsContent, { value: "users", children: jsx(UsersTab$1, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess }) }), jsx(TabsContent, { value: "courses", children: jsx(CoursesTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) }), jsx(TabsContent, { value: "programs", children: jsx(ProgramsTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) })] })) : (jsx(UsersTab$1, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess })) }), currentData && currentData.count > 0 && (jsx("div", { className: "flex items-center justify-between border-t border-gray-200 px-3 sm:px-6 py-3 sm:py-4 bg-gray-50 flex-shrink-0", children: jsxs("div", { className: "flex flex-1 items-center justify-between", children: [jsx("div", { className: "hidden sm:block", children: jsxs("p", { className: "text-sm text-gray-700", children: ["Showing", ' ', jsx("span", { className: "font-medium", children: (currentPage - 1) * itemsPerPage + 1 }), " to", ' ', jsx("span", { className: "font-medium", children: Math.min(currentPage * itemsPerPage, currentData.count) }), ' ', "of ", jsx("span", { className: "font-medium", children: currentData.count }), " invites"] }) }), jsxs("div", { className: "flex items-center justify-center gap-1 sm:gap-2", children: [jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(1), disabled: currentPage === 1, "aria-label": "Go to first page", children: jsx(ChevronFirst, { className: "h-4 w-4" }) }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: [jsx(ChevronLeft, { className: "h-4 w-4 mr-1 sm:mr-0" }), jsx("span", { className: "sm:hidden", children: "Prev" })] }), jsxs("span", { className: "text-xs sm:text-sm text-gray-700 mx-1 sm:mx-2 px-2", children: [jsx("span", { className: "hidden sm:inline", children: "Page " }), currentPage, " ", jsx("span", { className: "hidden sm:inline", children: "of " }), jsx("span", { className: "inline sm:hidden", children: " / " }), totalPages] }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: [jsx("span", { className: "sm:hidden", children: "Next" }), jsx(ChevronRight, { className: "h-4 w-4 ml-1 sm:ml-0" })] }), jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(totalPages), disabled: currentPage === totalPages, "aria-label": "Go to last page", children: jsx(ChevronLast, { className: "h-4 w-4" }) })] })] }) }))] }) }) }));
125627
125627
  }
125628
125628
 
125629
125629
  function InvitedUsersDialog({ tenant, onClose, }) {
@@ -198403,6 +198403,12 @@ function DeleteApiModal$1({ isOpen, onClose, apiKey, tenantKey }) {
198403
198403
  return (jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { "aria-describedby": "delete-api-key-description", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "ibl-dialog-title", children: "Delete API Key" }) }), jsx("div", { className: "my-5", children: jsxs("p", { className: "text-sm text-[#646464]", children: ["Are you sure you want to delete the API Key with the name", ' ', jsx("span", { className: "font-bold italic", children: apiKey.name }), "? This action cannot be undone."] }) }), jsxs(DialogFooter, { className: "gap-3", children: [jsx(Button$1, { variant: "outline", onClick: onClose, children: "Cancel" }), jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", onClick: handleDeleteApiKey, disabled: isLoading, children: isLoading ? 'Deleting...' : 'Delete' })] })] }) }));
198404
198404
  }
198405
198405
 
198406
+ /**
198407
+ * Blue informational banner used to describe a section, matching the RBAC
198408
+ * management tab styling (see `admin.tsx`).
198409
+ */
198410
+ const InfoBanner = ({ icon, title, id, children, className }) => (jsxs("div", { className: `flex gap-3 items-center border rounded-lg p-4 bg-blue-50/60 border-blue-100 ${className !== null && className !== void 0 ? className : ''}`, children: [icon && (jsx("div", { className: "shrink-0 w-9 h-9 rounded-md flex items-center justify-center bg-blue-100 text-blue-600", children: icon })), jsxs("div", { className: "flex-1 min-w-0", children: [title && jsx("h3", { className: "text-sm font-semibold mb-1 text-blue-900", children: title }), jsx("p", { id: id, className: "text-sm text-gray-600 leading-relaxed", children: children })] })] }));
198411
+
198406
198412
  function IntegrationAutogeneratedTab({ tenantKey }) {
198407
198413
  const { data: apiKeys, isLoading: isApiKeysLoading } = useGetApiKeysQuery({
198408
198414
  platformKey: tenantKey,
@@ -198414,7 +198420,7 @@ function IntegrationAutogeneratedTab({ tenantKey }) {
198414
198420
  function openDeleteApiModal(apiKey) {
198415
198421
  setApiKeyToDelete(apiKey);
198416
198422
  }
198417
- return (jsxs(Fragment$1, { children: [jsxs(Card, { style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(CardHeader, { children: jsx("div", { className: "flex items-start gap-2", children: jsx(CardDescription, { children: "These are authentication keys that you've generated for external applications to authenticate with your service. Keys are displayed only once when generated." }) }) }), jsx(CardContent, { children: jsxs(Table$1, { className: "w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "p-2 text-left text-sm text-[#646464]", children: "NAME" }), jsx(TableHead, { className: "p-2 text-left text-sm text-[#646464]", children: "CREATED" }), jsx(TableHead, { className: "p-2 text-left text-sm text-[#646464]", children: "EXPIRES" }), jsx(TableHead, { className: "p-2 text-left text-sm text-[#646464]" })] }) }), jsx(TableBody, { children: isApiKeysLoading ? (jsx(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, children: jsx(TableCell$1, { colSpan: 4, className: "p-4 sm:text-center text-sm text-gray-500", children: "Loading..." }) })) : (apiKeys === null || apiKeys === void 0 ? void 0 : apiKeys.length) === 0 ? (jsx(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, children: jsx(TableCell$1, { colSpan: 4, className: "p-4 sm:text-center text-sm text-gray-500", children: "No API keys found" }) })) : (apiKeys === null || apiKeys === void 0 ? void 0 : apiKeys.map((apiKey) => (jsxs(TableRow$1, { className: "text-sm", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell$1, { className: "p-2 whitespace-nowrap text-[#646464]", children: apiKey.name }), jsx(TableCell$1, { className: "p-2 whitespace-nowrap text-[#646464]", children: apiKey.created ? format(apiKey.created, 'PPP') : 'N/A' }), jsx(TableCell$1, { className: "p-2 whitespace-nowrap text-[#646464]", children: apiKey.expires ? format(apiKey.expires, 'PPP') : 'N/A' }), jsx(TableCell$1, { className: "p-2", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer", onClick: () => openDeleteApiModal({ name: apiKey.name }), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, apiKey.name)))) })] }) })] }), apiKeyToDelete && (jsx(DeleteApiModal$1, { isOpen: !!apiKeyToDelete, onClose: closeDeleteApiModal, apiKey: apiKeyToDelete, tenantKey: tenantKey }))] }));
198423
+ return (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-4", children: [jsx(InfoBanner, { icon: jsx(KeyRound, { className: "w-5 h-5" }), children: "These are authentication keys that you've generated for external applications to authenticate with your service. Keys are displayed only once when generated." }), jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Name" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Created" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Expires" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[50px]" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isApiKeysLoading ? (jsx("tr", { children: jsx("td", { colSpan: 4, className: "px-6 py-8 text-center text-sm text-gray-500", children: "Loading..." }) })) : (apiKeys === null || apiKeys === void 0 ? void 0 : apiKeys.length) === 0 ? (jsx("tr", { children: jsx("td", { colSpan: 4, className: "px-6 py-8 text-center text-sm text-gray-500", children: "No API keys found" }) })) : (apiKeys === null || apiKeys === void 0 ? void 0 : apiKeys.map((apiKey) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap text-gray-900 dark:text-gray-100", children: apiKey.name }), jsx("td", { className: "px-6 py-4 whitespace-nowrap text-gray-600 dark:text-gray-300", children: apiKey.created ? format(apiKey.created, 'PPP') : 'N/A' }), jsx("td", { className: "px-6 py-4 whitespace-nowrap text-gray-600 dark:text-gray-300", children: apiKey.expires ? format(apiKey.expires, 'PPP') : 'N/A' }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer", onClick: () => openDeleteApiModal({ name: apiKey.name }), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, apiKey.name)))) })] }) })] }), apiKeyToDelete && (jsx(DeleteApiModal$1, { isOpen: !!apiKeyToDelete, onClose: closeDeleteApiModal, apiKey: apiKeyToDelete, tenantKey: tenantKey }))] }));
198418
198424
  }
198419
198425
 
198420
198426
  function ApiKeyModal$1({ isOpen, onClose, apiKey }) {
@@ -198799,23 +198805,23 @@ function IntegrationLLMsTab({ tenantKey }) {
198799
198805
  toast.error('Failed to delete credential');
198800
198806
  }
198801
198807
  };
198802
- return (jsxs(Card, { style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(CardHeader, { children: jsx("div", { className: "flex items-start gap-2", children: jsx(CardDescription, { children: "These are LLM keys from third-party services that you've configured for use with your application." }) }) }), jsx(CardContent, { children: jsx("div", { className: "w-full overflow-x-auto", children: jsxs(Table$1, { className: "min-w-[600px] w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { children: "NAME" }), jsx(TableHead, { children: "KEY" })] }) }), jsx(TableBody, { children: isMaskedCredentialsLoading ? (jsx(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, children: jsx(TableCell$1, { colSpan: 4, className: "p-4 sm:text-center text-sm text-gray-500", children: "Loading..." }) })) : maskedCredentials.length === 0 ? (jsx(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, children: jsx(TableCell$1, { colSpan: 4, className: "p-4 sm:text-center text-sm text-gray-500", children: "No LLM keys found" }) })) : (maskedCredentials.map((cred, idx) => {
198803
- var _a, _b, _c;
198804
- const provider = ((_a = cred.service_info) === null || _a === void 0 ? void 0 : _a.display_name) || cred.name;
198805
- // Use logo from service_info only
198806
- let logoUrl;
198807
- let logoAlt;
198808
- if ((_b = cred.service_info) === null || _b === void 0 ? void 0 : _b.logo) {
198809
- logoUrl = cred.service_info.logo;
198810
- logoAlt = cred.service_info.display_name || cred.service_info.name;
198811
- }
198812
- const isAzure = isAzureOpenAI(cred);
198813
- const azureModels = isAzure ? getAzureModels(cred) : [];
198814
- const isExpanded = expandedRows.has(cred.name);
198815
- return (jsxs(React__default.Fragment, { children: [jsxs(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell$1, { children: jsxs("div", { className: "flex items-center gap-2", children: [logoUrl ? (jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" })) : (jsx("span", { className: "text-lg", children: '🔑' })), jsx("span", { className: "font-normal text-gray-900", children: provider || cred.name }), isAzure && azureModels.length > 0 && (jsx("button", { type: "button", onClick: () => toggleRowExpansion(cred.name), className: "p-0.5 hover:bg-gray-100 rounded", children: isExpanded ? (jsx(ChevronUp, { className: "h-4 w-4 text-gray-500" })) : (jsx(ChevronDown, { className: "h-4 w-4 text-gray-500" })) }))] }) }), jsx(TableCell$1, { className: "font-mono text-sm text-gray-900", children: isAzure ? (jsxs("span", { className: "text-xs text-gray-500", children: ["(", azureModels.length, " model", azureModels.length > 1 ? 's' : '', ")"] })) : (String((_c = cred === null || cred === void 0 ? void 0 : cred.value) === null || _c === void 0 ? void 0 : _c.key).slice(0, 15) || '') }), jsx(TableCell$1, { children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer mr-2", disabled: isDeletingIntegration || isDeletingCredential, onClick: () => handleDeleteCredential(cred.name, cred.platform, false), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }), isAzure &&
198816
- isExpanded &&
198817
- azureModels.map((model, modelIdx) => (jsxs(TableRow$1, { style: { borderColor: 'oklch(.922 0 0)' }, className: "", children: [jsx(TableCell$1, { className: "pl-12", children: jsx("span", { className: "text-sm text-gray-700", children: model.modelName.toLowerCase() }) }), jsx(TableCell$1, { className: "font-mono text-sm text-gray-600", children: model.maskedKey.slice(0, 15) || '' }), jsx(TableCell$1, { children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer", disabled: isDeletingIntegration || isDeletingCredential, onClick: () => handleDeleteCredential(cred.name, cred.platform, false, model.modelName), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, `${cred.name}-${model.modelName}-${modelIdx}`)))] }, cred.name + idx));
198818
- })) })] }) }) })] }));
198808
+ return (jsxs("div", { className: "space-y-4", children: [jsx(InfoBanner, { icon: jsx(Bot, { className: "w-5 h-5" }), children: "These are LLM keys from third-party services that you've configured for use with your application." }), jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm min-w-[600px]", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Name" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Key" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[50px]" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isMaskedCredentialsLoading ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "Loading..." }) })) : maskedCredentials.length === 0 ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "No LLM keys found" }) })) : (maskedCredentials.map((cred, idx) => {
198809
+ var _a, _b, _c;
198810
+ const provider = ((_a = cred.service_info) === null || _a === void 0 ? void 0 : _a.display_name) || cred.name;
198811
+ // Use logo from service_info only
198812
+ let logoUrl;
198813
+ let logoAlt;
198814
+ if ((_b = cred.service_info) === null || _b === void 0 ? void 0 : _b.logo) {
198815
+ logoUrl = cred.service_info.logo;
198816
+ logoAlt = cred.service_info.display_name || cred.service_info.name;
198817
+ }
198818
+ const isAzure = isAzureOpenAI(cred);
198819
+ const azureModels = isAzure ? getAzureModels(cred) : [];
198820
+ const isExpanded = expandedRows.has(cred.name);
198821
+ return (jsxs(React__default.Fragment, { children: [jsxs("tr", { children: [jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex items-center gap-2", children: [logoUrl ? (jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" })) : (jsx("span", { className: "text-lg", children: '🔑' })), jsx("span", { className: "font-normal text-gray-900 dark:text-gray-100", children: provider || cred.name }), isAzure && azureModels.length > 0 && (jsx("button", { type: "button", onClick: () => toggleRowExpansion(cred.name), className: "p-0.5 hover:bg-gray-100 rounded", children: isExpanded ? (jsx(ChevronUp, { className: "h-4 w-4 text-gray-500" })) : (jsx(ChevronDown, { className: "h-4 w-4 text-gray-500" })) }))] }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-900 dark:text-gray-100", children: isAzure ? (jsxs("span", { className: "text-xs text-gray-500", children: ["(", azureModels.length, " model", azureModels.length > 1 ? 's' : '', ")"] })) : (String((_c = cred === null || cred === void 0 ? void 0 : cred.value) === null || _c === void 0 ? void 0 : _c.key).slice(0, 15) || '') }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer mr-2", disabled: isDeletingIntegration || isDeletingCredential, onClick: () => handleDeleteCredential(cred.name, cred.platform, false), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }), isAzure &&
198822
+ isExpanded &&
198823
+ azureModels.map((model, modelIdx) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 pl-12", children: jsx("span", { className: "text-sm text-gray-700", children: model.modelName.toLowerCase() }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-600", children: model.maskedKey.slice(0, 15) || '' }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer", disabled: isDeletingIntegration || isDeletingCredential, onClick: () => handleDeleteCredential(cred.name, cred.platform, false, model.modelName), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, `${cred.name}-${model.modelName}-${modelIdx}`)))] }, cred.name + idx));
198824
+ })) })] }) })] }));
198819
198825
  }
198820
198826
 
198821
198827
  // Dynamic schema based on selected provider
@@ -198938,7 +198944,7 @@ function CreateDataSourceModal({ isOpen, onClose, tenantKey, onSuccess }) {
198938
198944
  } }, schemaField.name))) })), jsx(DialogFooter, { className: "justify-end", children: jsx(form.Subscribe, { selector: (state) => ({ canSubmit: state.canSubmit }), children: ({ canSubmit }) => (jsx(Button$1, { type: "submit", disabled: !canSubmit || isLoading || isIntegrationSchemaLoading, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isLoading ? 'Submitting...' : 'Submit' })) }) })] })] }) }));
198939
198945
  }
198940
198946
 
198941
- function IntegrationDataSourcesTab({ tenantKey, }) {
198947
+ function IntegrationDataSourcesTab({ tenantKey }) {
198942
198948
  // Fetch masked integration credentials from API
198943
198949
  const { data: maskedCredentials = [], isLoading: isMaskedCredentialsLoading, refetch, } = useGetMaskedIntegrationCredentialsQuery({ org: tenantKey });
198944
198950
  const [deleteIntegrationCredential, { isLoading: isDeletingIntegration }] = useDeleteIntegrationCredentialMutation();
@@ -198949,26 +198955,26 @@ function IntegrationDataSourcesTab({ tenantKey, }) {
198949
198955
  platform_key: platformKey,
198950
198956
  name,
198951
198957
  }).unwrap();
198952
- toast.success("Data source credential deleted successfully");
198958
+ toast.success('Data source credential deleted successfully');
198953
198959
  refetch();
198954
198960
  }
198955
198961
  catch (error) {
198956
- console.error("Failed to delete credential:", error);
198957
- toast.error("Failed to delete credential");
198962
+ console.error('Failed to delete credential:', error);
198963
+ toast.error('Failed to delete credential');
198958
198964
  }
198959
198965
  };
198960
- return (jsxs(Card, { style: { borderColor: "oklch(.922 0 0)" }, children: [jsx(CardHeader, { children: jsx("div", { className: "flex items-start gap-2", children: jsx(CardDescription, { children: "These are data source credentials from third-party services that you've configured for use with your application." }) }) }), jsx(CardContent, { children: jsx("div", { className: "w-full overflow-x-auto", children: jsxs(Table$1, { className: "min-w-[600px] w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { style: { borderColor: "oklch(.922 0 0)" }, children: [jsx(TableHead, { children: "NAME" }), jsx(TableHead, { children: "KEY" })] }) }), jsx(TableBody, { children: isMaskedCredentialsLoading ? (jsx(TableRow$1, { style: { borderColor: "oklch(.922 0 0)" }, children: jsx(TableCell$1, { colSpan: 4, className: "p-4 sm:text-center text-sm text-gray-500", children: "Loading..." }) })) : maskedCredentials.length === 0 ? (jsx(TableRow$1, { style: { borderColor: "oklch(.922 0 0)" }, children: jsx(TableCell$1, { colSpan: 4, className: "p-4 sm:text-center text-sm text-gray-500", children: "No data source credentials found" }) })) : (maskedCredentials.map((cred, idx) => {
198961
- var _a, _b, _c;
198962
- const provider = ((_a = cred.service_info) === null || _a === void 0 ? void 0 : _a.display_name) || cred.name;
198963
- // Use logo from service_info only
198964
- let logoUrl;
198965
- let logoAlt;
198966
- if ((_b = cred.service_info) === null || _b === void 0 ? void 0 : _b.logo) {
198967
- logoUrl = cred.service_info.logo;
198968
- logoAlt = cred.service_info.display_name || cred.service_info.name;
198969
- }
198970
- return (jsxs(TableRow$1, { style: { borderColor: "oklch(.922 0 0)" }, children: [jsx(TableCell$1, { children: jsxs("div", { className: "flex items-center gap-2", children: [logoUrl ? (jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" })) : (jsx("span", { className: "text-lg", children: "🔑" })), jsx("span", { className: "font-normal text-gray-900", children: provider || cred.name })] }) }), jsx(TableCell$1, { className: "font-mono text-sm text-gray-900", children: String((_c = cred === null || cred === void 0 ? void 0 : cred.value) === null || _c === void 0 ? void 0 : _c.key).slice(0, 15) || "" }), jsx(TableCell$1, { children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer mr-2", disabled: isDeletingIntegration, onClick: () => handleDeleteCredential(cred.name, cred.platform), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, cred.name + idx));
198971
- })) })] }) }) })] }));
198966
+ return (jsxs("div", { className: "space-y-4", children: [jsx(InfoBanner, { icon: jsx(Database, { className: "w-5 h-5" }), children: "These are data source credentials from third-party services that you've configured for use with your application." }), jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm min-w-[600px]", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Name" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Key" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[50px]" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isMaskedCredentialsLoading ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "Loading..." }) })) : maskedCredentials.length === 0 ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "No data source credentials found" }) })) : (maskedCredentials.map((cred, idx) => {
198967
+ var _a, _b, _c;
198968
+ const provider = ((_a = cred.service_info) === null || _a === void 0 ? void 0 : _a.display_name) || cred.name;
198969
+ // Use logo from service_info only
198970
+ let logoUrl;
198971
+ let logoAlt;
198972
+ if ((_b = cred.service_info) === null || _b === void 0 ? void 0 : _b.logo) {
198973
+ logoUrl = cred.service_info.logo;
198974
+ logoAlt = cred.service_info.display_name || cred.service_info.name;
198975
+ }
198976
+ return (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex items-center gap-2", children: [logoUrl ? (jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" })) : (jsx("span", { className: "text-lg", children: '🔑' })), jsx("span", { className: "font-normal text-gray-900 dark:text-gray-100", children: provider || cred.name })] }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-900 dark:text-gray-100", children: String((_c = cred === null || cred === void 0 ? void 0 : cred.value) === null || _c === void 0 ? void 0 : _c.key).slice(0, 15) || '' }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer mr-2", disabled: isDeletingIntegration, onClick: () => handleDeleteCredential(cred.name, cred.platform), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, cred.name + idx));
198977
+ })) })] }) })] }));
198972
198978
  }
198973
198979
 
198974
198980
  function IntegrationsTab({ tenantKey, username, }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/iblai-js",
3
- "version": "1.17.3",
3
+ "version": "1.17.5",
4
4
  "description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
5
5
  "type": "module",
6
6
  "engines": {
@@ -68,8 +68,8 @@
68
68
  "winston": "3.19.0",
69
69
  "@iblai/data-layer": "1.7.0",
70
70
  "@iblai/mcp": "1.5.3",
71
- "@iblai/web-utils": "1.10.3",
72
- "@iblai/web-containers": "1.8.5"
71
+ "@iblai/web-containers": "1.8.6",
72
+ "@iblai/web-utils": "1.10.5"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "@radix-ui/react-dialog": "^1.1.7",