@iblai/iblai-js 2.21.0 → 2.22.0

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.
@@ -1,9 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { useRef, useEffect, useMemo, useCallback, useState, createContext, useContext, forwardRef, createElement as createElement$1, useLayoutEffect, useReducer, useImperativeHandle, isValidElement, Children, PureComponent, cloneElement, Component, Fragment as Fragment$2, useId as useId$2, useDebugValue, lazy, Suspense } from 'react';
3
3
  import * as dataLayer from '@iblai/data-layer';
4
- import { useGetLlmsQuery, useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useGetUserProfileSummaryQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useGetAiSearchMentorsQuery, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, useUserLlmUsageSummary, useUserLlmSpendOverTime, useUserLlmCostByModel, useUserLlmCostByService, useUserLlmRecentActivity, USER_LLM_RECENT_ACTIVITY_PAGE_SIZE, useUserLlmTraceObservations, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useGetVectorDocumentsQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetLlmUsageMetricsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, VERCEL_SPA, useGetCustomDomainsQuery, useGetHostingProjectsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useCreateHostingProjectDomainMutation, useUpdateHostingDomainMutation, useDeleteHostingDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, USER_PROGRESS_DATA_POINTS, useResetTemplateMutation, useSendTestTemplateEmailMutation, useUpdateTemplateMutation, useGetTemplateDetailsQuery, USER_PROGRESS_SUMMARY_TYPE, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetLlmUsageTracesQuery, useGetLlmUsageObservationsQuery, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetAverageRatingQuery, useGetModelCostsQuery, useGetPerUserCostsQuery, useGetTenantCostQuery, useGetAgentCostQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useGetPlatformAuditLogsQuery, PLATFORM_AUDIT_EVENT_TYPES, PLATFORM_AUDIT_ACTION_CODES, useGetMentorMemoriesQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
4
+ import { useGetLlmsQuery, useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useGetUserProfileSummaryQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerCourseOutlineQuery, getSections, findResumeBlock, flattenOutline, normalizeLearnerCompletionError, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useGetAiSearchMentorsQuery, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, useUserLlmUsageSummary, useUserLlmSpendOverTime, useUserLlmCostByModel, useUserLlmCostByService, useUserLlmRecentActivity, USER_LLM_RECENT_ACTIVITY_PAGE_SIZE, useUserLlmTraceObservations, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useGetVectorDocumentsQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetLlmUsageMetricsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, VERCEL_SPA, useGetCustomDomainsQuery, useGetHostingProjectsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useCreateHostingProjectDomainMutation, useUpdateHostingDomainMutation, useDeleteHostingDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, USER_PROGRESS_DATA_POINTS, useResetTemplateMutation, useSendTestTemplateEmailMutation, useUpdateTemplateMutation, useGetTemplateDetailsQuery, USER_PROGRESS_SUMMARY_TYPE, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetLlmUsageTracesQuery, useGetLlmUsageObservationsQuery, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetAverageRatingQuery, useGetModelCostsQuery, useGetPerUserCostsQuery, useGetTenantCostQuery, useGetAgentCostQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useGetPlatformAuditLogsQuery, PLATFORM_AUDIT_EVENT_TYPES, PLATFORM_AUDIT_ACTION_CODES, useGetMentorMemoriesQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
5
5
  import { useDispatch, useSelector } from 'react-redux';
6
- import { selectSessionId, selectActiveChatMessages, useCachedSessionId, chatActions, LOCAL_STORAGE_KEYS, TimeTracker, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, isPureWatcher, getInitials, useTenantMetadata, useUsername, selectStreaming, isLoggedIn, TOOL_NAME_MAP, WRITE_TODOS_TOOL, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, getTimeAgo, REQUIRED_ACTIONS_FOR_GROUPS, getVisibleAnalyticsTabs, getUserName as getUserName$2, formatRelativeTime as formatRelativeTime$2, ANONYMOUS_USERNAME, combineCSVData, WATCHER_HIDDEN_REPORTS, canViewPlatformAuditLogs, redirectToAuthSpaJoinTenant, redirectToAuthSpa, getAuthSpaJoinUrl, useOS, selectNumberOfActiveChatMessages, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, chatInputSliceActions, removeFile, WithFormPermissions, MENTOR_VISIBILITY } from '@iblai/web-utils';
6
+ import { selectSessionId, selectActiveChatMessages, useCachedSessionId, chatActions, LOCAL_STORAGE_KEYS, TimeTracker, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, isPureWatcher, getInitials, useTenantMetadata, useUsername, selectStreaming, isLoggedIn, TOOL_NAME_MAP, WRITE_TODOS_TOOL, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, getTimeAgo, REQUIRED_ACTIONS_FOR_GROUPS, getVisibleAnalyticsTabs, canViewMonetizationAnalytics, getUserName as getUserName$2, formatRelativeTime as formatRelativeTime$2, ANONYMOUS_USERNAME, combineCSVData, WATCHER_HIDDEN_REPORTS, canViewPlatformAuditLogs, redirectToAuthSpaJoinTenant, redirectToAuthSpa, getAuthSpaJoinUrl, useOS, selectNumberOfActiveChatMessages, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, chatInputSliceActions, removeFile, WithFormPermissions, MENTOR_VISIBILITY } from '@iblai/web-utils';
7
7
  import { toast } from 'sonner';
8
8
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
9
9
  import * as ReactDOM from 'react-dom';
@@ -2325,6 +2325,8 @@ var analyticsAnalyticsMonetizationStats$3 = {
2325
2325
  tableHeadPlan: "Plan",
2326
2326
  tableHeadAmount: "Amount",
2327
2327
  tableHeadStatus: "Status",
2328
+ tableHeadUser: "User",
2329
+ tableHeadSubscribed: "Subscribed",
2328
2330
  subscriberCountTotal: "{count} subscriber{plural} total",
2329
2331
  previous: "Previous",
2330
2332
  pageLabel: "Page {page}",
@@ -9646,6 +9648,8 @@ var analyticsAnalyticsMonetizationStats$2 = {
9646
9648
  tableHeadPlan: "Plan",
9647
9649
  tableHeadAmount: "Montant",
9648
9650
  tableHeadStatus: "Statut",
9651
+ tableHeadUser: "Utilisateur",
9652
+ tableHeadSubscribed: "Abonné le",
9649
9653
  subscriberCountTotal: "{count} abonné{plural} au total",
9650
9654
  previous: "Précédent",
9651
9655
  pageLabel: "Page {page}",
@@ -16967,6 +16971,8 @@ var analyticsAnalyticsMonetizationStats$1 = {
16967
16971
  tableHeadPlan: "Plan",
16968
16972
  tableHeadAmount: "Monto",
16969
16973
  tableHeadStatus: "Estado",
16974
+ tableHeadUser: "Usuario",
16975
+ tableHeadSubscribed: "Suscrito el",
16970
16976
  subscriberCountTotal: "{count} suscriptor{plural} en total",
16971
16977
  previous: "Anterior",
16972
16978
  pageLabel: "Página {page}",
@@ -24288,6 +24294,8 @@ var analyticsAnalyticsMonetizationStats = {
24288
24294
  tableHeadPlan: "方案",
24289
24295
  tableHeadAmount: "金额",
24290
24296
  tableHeadStatus: "状态",
24297
+ tableHeadUser: "用户",
24298
+ tableHeadSubscribed: "订阅日期",
24291
24299
  subscriberCountTotal: "共 {count} 位订阅者",
24292
24300
  previous: "上一页",
24293
24301
  pageLabel: "第 {page} 页",
@@ -145975,7 +145983,205 @@ const EmptyStats = ({ title = 'No data available' }) => {
145975
145983
  return (jsx("div", { className: "flex justify-center items-center h-full", children: jsx("p", { className: "text-gray-500 text-sm", children: title }) }));
145976
145984
  };
145977
145985
 
145978
- const COMPLETED_COLOR = '#ED8936';
145986
+ var COLLAPSIBLE_NAME = "Collapsible";
145987
+ var [createCollapsibleContext] = createContextScope$1(COLLAPSIBLE_NAME);
145988
+ var [CollapsibleProvider, useCollapsibleContext] = createCollapsibleContext(COLLAPSIBLE_NAME);
145989
+ var Collapsible$1 = React.forwardRef(
145990
+ (props, forwardedRef) => {
145991
+ const {
145992
+ __scopeCollapsible,
145993
+ open: openProp,
145994
+ defaultOpen,
145995
+ disabled,
145996
+ onOpenChange,
145997
+ ...collapsibleProps
145998
+ } = props;
145999
+ const [open, setOpen] = useControllableState$2({
146000
+ prop: openProp,
146001
+ defaultProp: defaultOpen ?? false,
146002
+ onChange: onOpenChange,
146003
+ caller: COLLAPSIBLE_NAME
146004
+ });
146005
+ return /* @__PURE__ */ jsx(
146006
+ CollapsibleProvider,
146007
+ {
146008
+ scope: __scopeCollapsible,
146009
+ disabled,
146010
+ contentId: useId$1(),
146011
+ open,
146012
+ onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
146013
+ children: /* @__PURE__ */ jsx(
146014
+ Primitive$4.div,
146015
+ {
146016
+ "data-state": getState$3(open),
146017
+ "data-disabled": disabled ? "" : void 0,
146018
+ ...collapsibleProps,
146019
+ ref: forwardedRef
146020
+ }
146021
+ )
146022
+ }
146023
+ );
146024
+ }
146025
+ );
146026
+ Collapsible$1.displayName = COLLAPSIBLE_NAME;
146027
+ var TRIGGER_NAME$3 = "CollapsibleTrigger";
146028
+ var CollapsibleTrigger$1 = React.forwardRef(
146029
+ (props, forwardedRef) => {
146030
+ const { __scopeCollapsible, ...triggerProps } = props;
146031
+ const context = useCollapsibleContext(TRIGGER_NAME$3, __scopeCollapsible);
146032
+ return /* @__PURE__ */ jsx(
146033
+ Primitive$4.button,
146034
+ {
146035
+ type: "button",
146036
+ "aria-controls": context.contentId,
146037
+ "aria-expanded": context.open || false,
146038
+ "data-state": getState$3(context.open),
146039
+ "data-disabled": context.disabled ? "" : void 0,
146040
+ disabled: context.disabled,
146041
+ ...triggerProps,
146042
+ ref: forwardedRef,
146043
+ onClick: composeEventHandlers$2(props.onClick, context.onOpenToggle)
146044
+ }
146045
+ );
146046
+ }
146047
+ );
146048
+ CollapsibleTrigger$1.displayName = TRIGGER_NAME$3;
146049
+ var CONTENT_NAME$4 = "CollapsibleContent";
146050
+ var CollapsibleContent$1 = React.forwardRef(
146051
+ (props, forwardedRef) => {
146052
+ const { forceMount, ...contentProps } = props;
146053
+ const context = useCollapsibleContext(CONTENT_NAME$4, props.__scopeCollapsible);
146054
+ return /* @__PURE__ */ jsx(Presence$2, { present: forceMount || context.open, children: ({ present }) => /* @__PURE__ */ jsx(CollapsibleContentImpl, { ...contentProps, ref: forwardedRef, present }) });
146055
+ }
146056
+ );
146057
+ CollapsibleContent$1.displayName = CONTENT_NAME$4;
146058
+ var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
146059
+ const { __scopeCollapsible, present, children, ...contentProps } = props;
146060
+ const context = useCollapsibleContext(CONTENT_NAME$4, __scopeCollapsible);
146061
+ const [isPresent, setIsPresent] = React.useState(present);
146062
+ const ref = React.useRef(null);
146063
+ const composedRefs = useComposedRefs$1(forwardedRef, ref);
146064
+ const heightRef = React.useRef(0);
146065
+ const height = heightRef.current;
146066
+ const widthRef = React.useRef(0);
146067
+ const width = widthRef.current;
146068
+ const isOpen = context.open || isPresent;
146069
+ const isMountAnimationPreventedRef = React.useRef(isOpen);
146070
+ const originalStylesRef = React.useRef(void 0);
146071
+ React.useEffect(() => {
146072
+ const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);
146073
+ return () => cancelAnimationFrame(rAF);
146074
+ }, []);
146075
+ useLayoutEffect2$1(() => {
146076
+ const node = ref.current;
146077
+ if (node) {
146078
+ originalStylesRef.current = originalStylesRef.current || {
146079
+ transitionDuration: node.style.transitionDuration,
146080
+ animationName: node.style.animationName
146081
+ };
146082
+ node.style.transitionDuration = "0s";
146083
+ node.style.animationName = "none";
146084
+ const rect = node.getBoundingClientRect();
146085
+ heightRef.current = rect.height;
146086
+ widthRef.current = rect.width;
146087
+ if (!isMountAnimationPreventedRef.current) {
146088
+ node.style.transitionDuration = originalStylesRef.current.transitionDuration;
146089
+ node.style.animationName = originalStylesRef.current.animationName;
146090
+ }
146091
+ setIsPresent(present);
146092
+ }
146093
+ }, [context.open, present]);
146094
+ return /* @__PURE__ */ jsx(
146095
+ Primitive$4.div,
146096
+ {
146097
+ "data-state": getState$3(context.open),
146098
+ "data-disabled": context.disabled ? "" : void 0,
146099
+ id: context.contentId,
146100
+ hidden: !isOpen,
146101
+ ...contentProps,
146102
+ ref: composedRefs,
146103
+ style: {
146104
+ [`--radix-collapsible-content-height`]: height ? `${height}px` : void 0,
146105
+ [`--radix-collapsible-content-width`]: width ? `${width}px` : void 0,
146106
+ ...props.style
146107
+ },
146108
+ children: isOpen && children
146109
+ }
146110
+ );
146111
+ });
146112
+ function getState$3(open) {
146113
+ return open ? "open" : "closed";
146114
+ }
146115
+ var Root$5 = Collapsible$1;
146116
+
146117
+ const Collapsible = Root$5;
146118
+ const CollapsibleTrigger = CollapsibleTrigger$1;
146119
+ const CollapsibleContent = CollapsibleContent$1;
146120
+
146121
+ const BAR_COLOR$1 = 'var(--color-amber-500, #f59e0b)';
146122
+ const ERROR_MESSAGES = {
146123
+ forbidden: 'Completion breakdown is not available for this learner.',
146124
+ not_enrolled: 'This learner is not enrolled in this course.',
146125
+ unavailable: 'Could not load the completion breakdown. Please try again later.',
146126
+ unauthorized: 'Completion breakdown is not available for this learner.',
146127
+ invalid_request: 'Completion breakdown is not available for this course.',
146128
+ unknown: 'Could not load the completion breakdown.',
146129
+ };
146130
+ // Backend values are already rounded to 2 decimals; show whole numbers
146131
+ // unless the value is fractional (e.g. 33.33).
146132
+ const formatPct = (value) => {
146133
+ const pct = value !== null && value !== void 0 ? value : 0;
146134
+ return `${Number.isInteger(pct) ? pct : pct.toFixed(2).replace(/\.?0+$/, '')}%`;
146135
+ };
146136
+ function CompletionBar({ value, label }) {
146137
+ const clamped = Math.min(Math.max(value, 0), 100);
146138
+ return (jsx("span", { className: "block h-1.5 w-full rounded-full bg-gray-200", role: "progressbar", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": clamped, children: jsx("span", { className: "block h-1.5 rounded-full", style: { width: `${clamped}%`, backgroundColor: BAR_COLOR$1 } }) }));
146139
+ }
146140
+ function SubsectionRow({ block }) {
146141
+ return (jsxs("li", { className: "space-y-1 py-2", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-sm text-gray-700", children: [jsx("span", { className: "truncate", children: block.display_name }), block.special_exam_info ? (jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 rounded-full bg-gray-100 px-2 py-0.5 text-[11px] text-gray-600", children: [jsx(Clock, { className: "h-3 w-3", "aria-hidden": "true" }), block.special_exam_info.short_description] })) : null] }), jsx("span", { className: "shrink-0 text-xs font-medium text-gray-600", children: formatPct(block.completion_percentage) })] }), jsx(CompletionBar, { value: block.completion_percentage, label: `${block.display_name} completion` })] }));
146142
+ }
146143
+ function SectionRow({ block }) {
146144
+ var _a;
146145
+ const [open, setOpen] = useState(false);
146146
+ const subsections = (_a = block.children) !== null && _a !== void 0 ? _a : [];
146147
+ return (jsx(Collapsible, { open: open, onOpenChange: setOpen, asChild: true, children: jsxs("li", { className: "py-2.5", children: [jsxs(CollapsibleTrigger, { className: "flex w-full items-center gap-2 rounded text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-amber-500 disabled:cursor-default", disabled: subsections.length === 0, children: [jsx(ChevronRight, { className: `h-4 w-4 shrink-0 text-gray-400 transition-transform ${open ? 'rotate-90' : ''} ${subsections.length === 0 ? 'invisible' : ''}`, "aria-hidden": "true" }), jsxs("span", { className: "block min-w-0 flex-1 space-y-1.5", children: [jsxs("span", { className: "flex items-center justify-between gap-3", children: [jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-sm font-medium text-gray-900", children: [jsx("span", { className: "truncate", children: block.display_name }), block.complete ? (jsx(CircleCheck, { className: "h-4 w-4 shrink-0 text-green-600", "aria-label": "Complete" })) : null] }), jsx("span", { className: "shrink-0 text-sm font-semibold text-gray-700", children: formatPct(block.completion_percentage) })] }), jsx(CompletionBar, { value: block.completion_percentage, label: `${block.display_name} completion` })] })] }), subsections.length > 0 ? (jsx(CollapsibleContent, { children: jsx("ul", { className: "ml-6 mt-1 divide-y divide-gray-100", children: subsections.map((subsection) => (jsx(SubsectionRow, { block: subsection }, subsection.id))) }) })) : null] }) }));
146148
+ }
146149
+ /**
146150
+ * Per-section completion for one learner in one course, from the DM
146151
+ * completion outline. Percentages come from the backend as-is.
146152
+ */
146153
+ function CourseCompletionBreakdown({ username, courseId, tenantKey, skip = false, }) {
146154
+ const { data, error, isLoading, isFetching, refetch } = useGetLearnerCourseOutlineQuery({ username, course_id: courseId, platform_key: tenantKey }, { skip: skip || !username || !courseId || !tenantKey });
146155
+ const sections = useMemo(() => (data ? getSections(data) : []), [data]);
146156
+ const resumePath = useMemo(() => {
146157
+ if (!data)
146158
+ return null;
146159
+ const resume = findResumeBlock(data);
146160
+ if (!resume || resume.id === data.id)
146161
+ return null;
146162
+ const entry = flattenOutline(data).find(({ block }) => block.id === resume.id);
146163
+ // Drop the course name; the modal header already shows it.
146164
+ return entry ? entry.path.slice(1).join(' › ') : null;
146165
+ }, [data]);
146166
+ const normalizedError = normalizeLearnerCompletionError(error);
146167
+ let body;
146168
+ if (isLoading || (isFetching && !data)) {
146169
+ body = jsx("p", { className: "py-4 text-sm text-gray-500", children: "Loading completion breakdown..." });
146170
+ }
146171
+ else if (normalizedError) {
146172
+ body = (jsxs("div", { className: "flex items-center justify-between gap-3 py-2", children: [jsx("p", { className: "text-sm text-gray-500", children: ERROR_MESSAGES[normalizedError.kind] }), normalizedError.retryable ? (jsx(Button$1, { variant: "outline", size: "sm", onClick: () => refetch(), disabled: isFetching, children: "Retry" })) : null] }));
146173
+ }
146174
+ else if (sections.length === 0) {
146175
+ body = jsx("p", { className: "py-2 text-sm text-gray-500", children: "No sections in this course yet." });
146176
+ }
146177
+ else {
146178
+ body = (jsxs(Fragment$1, { children: [resumePath ? (jsxs("p", { className: "text-xs text-gray-500", children: ["Last visited: ", jsx("span", { className: "font-medium text-gray-700", children: resumePath })] })) : null, jsx("ul", { className: "divide-y divide-[oklch(0.922_0_0)]", children: sections.map((section) => (jsx(SectionRow, { block: section.block }, section.id))) })] }));
146179
+ }
146180
+ return (jsxs("section", { className: "space-y-2 rounded-lg border p-4", style: { borderColor: 'oklch(.922 0 0)' }, "aria-labelledby": "completion-breakdown-heading", children: [jsxs("div", { children: [jsx("h4", { id: "completion-breakdown-heading", className: "text-sm font-semibold text-gray-900", children: "Completion breakdown" }), jsx("p", { className: "text-xs text-gray-500", children: "Progress through each section of this course." })] }), body] }));
146181
+ }
146182
+
146183
+ // Theme token (the same one bg-amber-500 resolves to), with Tailwind's default as fallback.
146184
+ const COMPLETED_COLOR = 'var(--color-amber-500, #f59e0b)';
145979
146185
  const REMAINING_COLOR = '#E5E7EB';
145980
146186
  const formatDate$2 = (value) => {
145981
146187
  if (!value)
@@ -146081,7 +146287,7 @@ function EnrolledUserProgressModal({ open, onOpenChange, username, userName, ema
146081
146287
  const passingPct = getPassingPct((_h = (_g = item === null || item === void 0 ? void 0 : item.edx_progress) === null || _g === void 0 ? void 0 : _g.grading_policy) === null || _h === void 0 ? void 0 : _h.grade_range);
146082
146288
  return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "max-w-2xl max-h-[85vh] overflow-y-auto", "aria-label": "Enrolled user progress", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: userName || username || 'Learner progress' }), jsxs(DialogDescription, { children: [email ? `${email} · ` : '', resolvedName || (isProgram ? 'Program progress' : 'Course progress')] })] }), loading ? (jsx("div", { className: "flex items-center justify-center py-12", children: jsx("div", { className: "text-sm text-gray-500", children: "Loading..." }) })) : !item ? (jsx(EmptyStats, { title: "No progress data available" })) : (jsxs("div", { className: "space-y-6", children: [jsxs("div", { className: "relative mx-auto", style: { width: 220, height: 220 }, children: [jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsx(PieChart, { children: jsxs(Pie, { data: pieData, dataKey: "value", cx: "50%", cy: "50%", innerRadius: 75, outerRadius: 100, startAngle: 90, endAngle: -270, stroke: "none", isAnimationActive: false, children: [jsx(Cell, { fill: COMPLETED_COLOR }), jsx(Cell, { fill: REMAINING_COLOR })] }) }) }), jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center pointer-events-none", children: [jsxs("span", { className: "text-3xl font-bold text-gray-700", children: [percentage, "%"] }), jsx("span", { className: "text-sm text-gray-500", children: "completed" })] })] }), jsxs("div", { className: "divide-y divide-[oklch(0.922_0_0)]", children: [jsx(DetailRow$1, { label: "Status", children: jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${((_j = item.completion) === null || _j === void 0 ? void 0 : _j.passed)
146083
146289
  ? 'bg-green-50 text-green-700'
146084
- : 'bg-gray-100 text-gray-600'}`, children: ((_k = item.completion) === null || _k === void 0 ? void 0 : _k.passed) ? 'Passed' : 'Not passed' }) }), jsx(DetailRow$1, { label: "Passed on", children: formatDate$2((_l = item.completion) === null || _l === void 0 ? void 0 : _l.passed_date) }), jsx(DetailRow$1, { label: "Time spent", children: item.time_spent || '—' }), jsx(DetailRow$1, { label: "Enrollment date", children: formatDate$2((_o = (_m = item.enrollment) === null || _m === void 0 ? void 0 : _m.started) !== null && _o !== void 0 ? _o : (_p = item.enrollment) === null || _p === void 0 ? void 0 : _p.created) })] }), ((_s = (_r = (_q = item.edx_progress) === null || _q === void 0 ? void 0 : _q.grading_policy) === null || _r === void 0 ? void 0 : _r.assignment_policies) === null || _s === void 0 ? void 0 : _s.length) ? (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "rounded-lg border p-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grades" }), jsx("p", { className: "text-xs text-gray-500", children: "This represents the weighted grade against the grade needed to pass this course." }), jsx(GradeBar, { currentPct: currentGradePct, passingPct: passingPct })] }), jsxs("div", { className: "flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 px-4 py-3", children: [jsx(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-600" }), jsxs("span", { className: "text-sm font-medium text-gray-800", children: ["A weighted grade of ", passingPct, "% is required to pass in this course"] })] }), jsxs("div", { className: "rounded-lg border p-4 space-y-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grade summary" }), jsx("div", { className: "overflow-x-auto", children: jsxs("table", { className: "w-full border-collapse text-sm", children: [jsx("thead", { children: jsxs("tr", { className: "bg-amber-50 text-[11px] uppercase tracking-wide text-gray-600", children: [jsx("th", { className: "px-3 py-2 text-left font-medium", children: "Assignment type" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weight" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Grade" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weighted grade" })] }) }), jsxs("tbody", { children: [gradeSummary === null || gradeSummary === void 0 ? void 0 : gradeSummary.rows.map((row, index) => (jsxs("tr", { className: index % 2 === 0 ? '' : 'bg-gray-50', children: [jsxs("td", { className: "px-3 py-2 text-gray-800", children: [row.type, row.footnote ? (jsx("sup", { className: "ml-0.5 text-amber-500", children: row.footnote })) : null] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.weightPct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.gradePct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right font-semibold text-amber-600", children: [row.weightedGradePct, "%"] })] }, row.type))), jsxs("tr", { className: "border-l-2 border-amber-400 bg-amber-50", children: [jsx("td", { className: "px-3 py-2 font-medium text-gray-800", colSpan: 3, children: "Current weighted grade summary" }), jsxs("td", { className: "px-3 py-2 text-right font-bold text-amber-600", children: [currentGradePct, "%"] })] })] })] }) }), gradeSummary && gradeSummary.footnotes.length > 0 ? (jsx("div", { className: "space-y-1", children: gradeSummary.footnotes.map((note, index) => (jsxs("p", { className: "text-xs text-gray-500", children: [jsx("sup", { className: "text-amber-500", children: index + 1 }), " ", note] }, note))) })) : null] })] })) : null] }))] }) }));
146290
+ : 'bg-gray-100 text-gray-600'}`, children: ((_k = item.completion) === null || _k === void 0 ? void 0 : _k.passed) ? 'Passed' : 'Not passed' }) }), jsx(DetailRow$1, { label: "Passed on", children: formatDate$2((_l = item.completion) === null || _l === void 0 ? void 0 : _l.passed_date) }), jsx(DetailRow$1, { label: "Time spent", children: item.time_spent || '—' }), jsx(DetailRow$1, { label: "Enrollment date", children: formatDate$2((_o = (_m = item.enrollment) === null || _m === void 0 ? void 0 : _m.started) !== null && _o !== void 0 ? _o : (_p = item.enrollment) === null || _p === void 0 ? void 0 : _p.created) })] }), !isProgram ? (jsx(CourseCompletionBreakdown, { username: username, courseId: normalizedId, tenantKey: tenantKey, skip: !open })) : null, ((_s = (_r = (_q = item.edx_progress) === null || _q === void 0 ? void 0 : _q.grading_policy) === null || _r === void 0 ? void 0 : _r.assignment_policies) === null || _s === void 0 ? void 0 : _s.length) ? (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "rounded-lg border p-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grades" }), jsx("p", { className: "text-xs text-gray-500", children: "This represents the weighted grade against the grade needed to pass this course." }), jsx(GradeBar, { currentPct: currentGradePct, passingPct: passingPct })] }), jsxs("div", { className: "flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 px-4 py-3", children: [jsx(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-600" }), jsxs("span", { className: "text-sm font-medium text-gray-800", children: ["A weighted grade of ", passingPct, "% is required to pass in this course"] })] }), jsxs("div", { className: "rounded-lg border p-4 space-y-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grade summary" }), jsx("div", { className: "overflow-x-auto", children: jsxs("table", { className: "w-full border-collapse text-sm", children: [jsx("thead", { children: jsxs("tr", { className: "bg-amber-50 text-[11px] uppercase tracking-wide text-gray-600", children: [jsx("th", { className: "px-3 py-2 text-left font-medium", children: "Assignment type" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weight" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Grade" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weighted grade" })] }) }), jsxs("tbody", { children: [gradeSummary === null || gradeSummary === void 0 ? void 0 : gradeSummary.rows.map((row, index) => (jsxs("tr", { className: index % 2 === 0 ? '' : 'bg-gray-50', children: [jsxs("td", { className: "px-3 py-2 text-gray-800", children: [row.type, row.footnote ? (jsx("sup", { className: "ml-0.5 text-amber-500", children: row.footnote })) : null] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.weightPct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.gradePct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right font-semibold text-amber-600", children: [row.weightedGradePct, "%"] })] }, row.type))), jsxs("tr", { className: "border-l-2 border-amber-400 bg-amber-50", children: [jsx("td", { className: "px-3 py-2 font-medium text-gray-800", colSpan: 3, children: "Current weighted grade summary" }), jsxs("td", { className: "px-3 py-2 text-right font-bold text-amber-600", children: [currentGradePct, "%"] })] })] })] }) }), gradeSummary && gradeSummary.footnotes.length > 0 ? (jsx("div", { className: "space-y-1", children: gradeSummary.footnotes.map((note, index) => (jsxs("p", { className: "text-xs text-gray-500", children: [jsx("sup", { className: "text-amber-500", children: index + 1 }), " ", note] }, note))) })) : null] })] })) : null] }))] }) }));
146085
146291
  }
146086
146292
  function DetailRow$1({ label, children }) {
146087
146293
  return (jsxs("div", { className: "flex items-center justify-between gap-4 py-2", children: [jsx("span", { className: "text-sm text-gray-500", children: label }), jsx("span", { className: "text-sm font-medium text-gray-900 text-right", children: children })] }));
@@ -146497,20 +146703,20 @@ var MenuPortal = (props) => {
146497
146703
  return /* @__PURE__ */ jsx(PortalProvider$1, { scope: __scopeMenu, forceMount, children: /* @__PURE__ */ jsx(Presence$1, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(Portal$6, { asChild: true, container, children }) }) });
146498
146704
  };
146499
146705
  MenuPortal.displayName = PORTAL_NAME$3;
146500
- var CONTENT_NAME$4 = "MenuContent";
146501
- var [MenuContentProvider, useMenuContentContext] = createMenuContext(CONTENT_NAME$4);
146706
+ var CONTENT_NAME$3 = "MenuContent";
146707
+ var [MenuContentProvider, useMenuContentContext] = createMenuContext(CONTENT_NAME$3);
146502
146708
  var MenuContent = React.forwardRef(
146503
146709
  (props, forwardedRef) => {
146504
- const portalContext = usePortalContext$1(CONTENT_NAME$4, props.__scopeMenu);
146710
+ const portalContext = usePortalContext$1(CONTENT_NAME$3, props.__scopeMenu);
146505
146711
  const { forceMount = portalContext.forceMount, ...contentProps } = props;
146506
- const context = useMenuContext(CONTENT_NAME$4, props.__scopeMenu);
146507
- const rootContext = useMenuRootContext(CONTENT_NAME$4, props.__scopeMenu);
146712
+ const context = useMenuContext(CONTENT_NAME$3, props.__scopeMenu);
146713
+ const rootContext = useMenuRootContext(CONTENT_NAME$3, props.__scopeMenu);
146508
146714
  return /* @__PURE__ */ jsx(Collection$1.Provider, { scope: props.__scopeMenu, children: /* @__PURE__ */ jsx(Presence$1, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(Collection$1.Slot, { scope: props.__scopeMenu, children: rootContext.modal ? /* @__PURE__ */ jsx(MenuRootContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(MenuRootContentNonModal, { ...contentProps, ref: forwardedRef }) }) }) });
146509
146715
  }
146510
146716
  );
146511
146717
  var MenuRootContentModal = React.forwardRef(
146512
146718
  (props, forwardedRef) => {
146513
- const context = useMenuContext(CONTENT_NAME$4, props.__scopeMenu);
146719
+ const context = useMenuContext(CONTENT_NAME$3, props.__scopeMenu);
146514
146720
  const ref = React.useRef(null);
146515
146721
  const composedRefs = useComposedRefs$1(forwardedRef, ref);
146516
146722
  React.useEffect(() => {
@@ -146536,7 +146742,7 @@ var MenuRootContentModal = React.forwardRef(
146536
146742
  }
146537
146743
  );
146538
146744
  var MenuRootContentNonModal = React.forwardRef((props, forwardedRef) => {
146539
- const context = useMenuContext(CONTENT_NAME$4, props.__scopeMenu);
146745
+ const context = useMenuContext(CONTENT_NAME$3, props.__scopeMenu);
146540
146746
  return /* @__PURE__ */ jsx(
146541
146747
  MenuContentImpl,
146542
146748
  {
@@ -146568,8 +146774,8 @@ var MenuContentImpl = React.forwardRef(
146568
146774
  disableOutsideScroll,
146569
146775
  ...contentProps
146570
146776
  } = props;
146571
- const context = useMenuContext(CONTENT_NAME$4, __scopeMenu);
146572
- const rootContext = useMenuRootContext(CONTENT_NAME$4, __scopeMenu);
146777
+ const context = useMenuContext(CONTENT_NAME$3, __scopeMenu);
146778
+ const rootContext = useMenuRootContext(CONTENT_NAME$3, __scopeMenu);
146573
146779
  const popperScope = usePopperScope$1(__scopeMenu);
146574
146780
  const rovingFocusGroupScope = useRovingFocusGroupScope$1(__scopeMenu);
146575
146781
  const getItems = useCollection$1(__scopeMenu);
@@ -146732,7 +146938,7 @@ var MenuContentImpl = React.forwardRef(
146732
146938
  );
146733
146939
  }
146734
146940
  );
146735
- MenuContent.displayName = CONTENT_NAME$4;
146941
+ MenuContent.displayName = CONTENT_NAME$3;
146736
146942
  var GROUP_NAME$2 = "MenuGroup";
146737
146943
  var MenuGroup = React.forwardRef(
146738
146944
  (props, forwardedRef) => {
@@ -147106,10 +147312,10 @@ MenuSubTrigger.displayName = SUB_TRIGGER_NAME$1;
147106
147312
  var SUB_CONTENT_NAME$1 = "MenuSubContent";
147107
147313
  var MenuSubContent = React.forwardRef(
147108
147314
  (props, forwardedRef) => {
147109
- const portalContext = usePortalContext$1(CONTENT_NAME$4, props.__scopeMenu);
147315
+ const portalContext = usePortalContext$1(CONTENT_NAME$3, props.__scopeMenu);
147110
147316
  const { forceMount = portalContext.forceMount, ...subContentProps } = props;
147111
- const context = useMenuContext(CONTENT_NAME$4, props.__scopeMenu);
147112
- const rootContext = useMenuRootContext(CONTENT_NAME$4, props.__scopeMenu);
147317
+ const context = useMenuContext(CONTENT_NAME$3, props.__scopeMenu);
147318
+ const rootContext = useMenuRootContext(CONTENT_NAME$3, props.__scopeMenu);
147113
147319
  const subContext = useMenuSubContext(SUB_CONTENT_NAME$1, props.__scopeMenu);
147114
147320
  const ref = React.useRef(null);
147115
147321
  const composedRefs = useComposedRefs$1(forwardedRef, ref);
@@ -147261,11 +147467,11 @@ var DropdownMenu$1 = (props) => {
147261
147467
  );
147262
147468
  };
147263
147469
  DropdownMenu$1.displayName = DROPDOWN_MENU_NAME;
147264
- var TRIGGER_NAME$3 = "DropdownMenuTrigger";
147470
+ var TRIGGER_NAME$2 = "DropdownMenuTrigger";
147265
147471
  var DropdownMenuTrigger$1 = React.forwardRef(
147266
147472
  (props, forwardedRef) => {
147267
147473
  const { __scopeDropdownMenu, disabled = false, ...triggerProps } = props;
147268
- const context = useDropdownMenuContext(TRIGGER_NAME$3, __scopeDropdownMenu);
147474
+ const context = useDropdownMenuContext(TRIGGER_NAME$2, __scopeDropdownMenu);
147269
147475
  const menuScope = useMenuScope(__scopeDropdownMenu);
147270
147476
  return /* @__PURE__ */ jsx(Anchor2$1, { asChild: true, ...menuScope, children: /* @__PURE__ */ jsx(
147271
147477
  Primitive$3.button,
@@ -147296,7 +147502,7 @@ var DropdownMenuTrigger$1 = React.forwardRef(
147296
147502
  ) });
147297
147503
  }
147298
147504
  );
147299
- DropdownMenuTrigger$1.displayName = TRIGGER_NAME$3;
147505
+ DropdownMenuTrigger$1.displayName = TRIGGER_NAME$2;
147300
147506
  var PORTAL_NAME$2 = "DropdownMenuPortal";
147301
147507
  var DropdownMenuPortal$1 = (props) => {
147302
147508
  const { __scopeDropdownMenu, ...portalProps } = props;
@@ -147304,11 +147510,11 @@ var DropdownMenuPortal$1 = (props) => {
147304
147510
  return /* @__PURE__ */ jsx(Portal$1, { ...menuScope, ...portalProps });
147305
147511
  };
147306
147512
  DropdownMenuPortal$1.displayName = PORTAL_NAME$2;
147307
- var CONTENT_NAME$3 = "DropdownMenuContent";
147513
+ var CONTENT_NAME$2 = "DropdownMenuContent";
147308
147514
  var DropdownMenuContent$1 = React.forwardRef(
147309
147515
  (props, forwardedRef) => {
147310
147516
  const { __scopeDropdownMenu, ...contentProps } = props;
147311
- const context = useDropdownMenuContext(CONTENT_NAME$3, __scopeDropdownMenu);
147517
+ const context = useDropdownMenuContext(CONTENT_NAME$2, __scopeDropdownMenu);
147312
147518
  const menuScope = useMenuScope(__scopeDropdownMenu);
147313
147519
  const hasInteractedOutsideRef = React.useRef(false);
147314
147520
  return /* @__PURE__ */ jsx(
@@ -147345,7 +147551,7 @@ var DropdownMenuContent$1 = React.forwardRef(
147345
147551
  );
147346
147552
  }
147347
147553
  );
147348
- DropdownMenuContent$1.displayName = CONTENT_NAME$3;
147554
+ DropdownMenuContent$1.displayName = CONTENT_NAME$2;
147349
147555
  var GROUP_NAME$1 = "DropdownMenuGroup";
147350
147556
  var DropdownMenuGroup$1 = React.forwardRef(
147351
147557
  (props, forwardedRef) => {
@@ -149455,7 +149661,7 @@ function PreviousMonthButton(props) {
149455
149661
  * @group Components
149456
149662
  * @see https://daypicker.dev/guides/custom-components
149457
149663
  */
149458
- function Root$5(props) {
149664
+ function Root$4(props) {
149459
149665
  const { rootRef, ...rest } = props;
149460
149666
  return React__default.createElement("div", { ...rest, ref: rootRef });
149461
149667
  }
@@ -149563,7 +149769,7 @@ var components$1 = /*#__PURE__*/Object.freeze({
149563
149769
  NextMonthButton: NextMonthButton,
149564
149770
  Option: Option,
149565
149771
  PreviousMonthButton: PreviousMonthButton,
149566
- Root: Root$5,
149772
+ Root: Root$4,
149567
149773
  Select: Select,
149568
149774
  Week: Week,
149569
149775
  WeekNumber: WeekNumber,
@@ -151633,11 +151839,11 @@ var PopoverAnchor$1 = React.forwardRef(
151633
151839
  }
151634
151840
  );
151635
151841
  PopoverAnchor$1.displayName = ANCHOR_NAME;
151636
- var TRIGGER_NAME$2 = "PopoverTrigger";
151842
+ var TRIGGER_NAME$1 = "PopoverTrigger";
151637
151843
  var PopoverTrigger$1 = React.forwardRef(
151638
151844
  (props, forwardedRef) => {
151639
151845
  const { __scopePopover, ...triggerProps } = props;
151640
- const context = usePopoverContext(TRIGGER_NAME$2, __scopePopover);
151846
+ const context = usePopoverContext(TRIGGER_NAME$1, __scopePopover);
151641
151847
  const popperScope = usePopperScope(__scopePopover);
151642
151848
  const composedTriggerRef = useComposedRefs$1(forwardedRef, context.triggerRef);
151643
151849
  const trigger = /* @__PURE__ */ jsx(
@@ -151647,7 +151853,7 @@ var PopoverTrigger$1 = React.forwardRef(
151647
151853
  "aria-haspopup": "dialog",
151648
151854
  "aria-expanded": context.open,
151649
151855
  "aria-controls": context.contentId,
151650
- "data-state": getState$3(context.open),
151856
+ "data-state": getState$2(context.open),
151651
151857
  ...triggerProps,
151652
151858
  ref: composedTriggerRef,
151653
151859
  onClick: composeEventHandlers$1(props.onClick, context.onOpenToggle)
@@ -151656,7 +151862,7 @@ var PopoverTrigger$1 = React.forwardRef(
151656
151862
  return context.hasCustomAnchor ? trigger : /* @__PURE__ */ jsx(Anchor$1, { asChild: true, ...popperScope, children: trigger });
151657
151863
  }
151658
151864
  );
151659
- PopoverTrigger$1.displayName = TRIGGER_NAME$2;
151865
+ PopoverTrigger$1.displayName = TRIGGER_NAME$1;
151660
151866
  var PORTAL_NAME$1 = "PopoverPortal";
151661
151867
  var [PortalProvider, usePortalContext] = createPopoverContext(PORTAL_NAME$1, {
151662
151868
  forceMount: void 0
@@ -151667,20 +151873,20 @@ var PopoverPortal = (props) => {
151667
151873
  return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopePopover, forceMount, children: /* @__PURE__ */ jsx(Presence$1, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(Portal$6, { asChild: true, container, children }) }) });
151668
151874
  };
151669
151875
  PopoverPortal.displayName = PORTAL_NAME$1;
151670
- var CONTENT_NAME$2 = "PopoverContent";
151876
+ var CONTENT_NAME$1 = "PopoverContent";
151671
151877
  var PopoverContent$1 = React.forwardRef(
151672
151878
  (props, forwardedRef) => {
151673
- const portalContext = usePortalContext(CONTENT_NAME$2, props.__scopePopover);
151879
+ const portalContext = usePortalContext(CONTENT_NAME$1, props.__scopePopover);
151674
151880
  const { forceMount = portalContext.forceMount, ...contentProps } = props;
151675
- const context = usePopoverContext(CONTENT_NAME$2, props.__scopePopover);
151881
+ const context = usePopoverContext(CONTENT_NAME$1, props.__scopePopover);
151676
151882
  return /* @__PURE__ */ jsx(Presence$1, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(PopoverContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(PopoverContentNonModal, { ...contentProps, ref: forwardedRef }) });
151677
151883
  }
151678
151884
  );
151679
- PopoverContent$1.displayName = CONTENT_NAME$2;
151885
+ PopoverContent$1.displayName = CONTENT_NAME$1;
151680
151886
  var Slot = createSlot("PopoverContent.RemoveScroll");
151681
151887
  var PopoverContentModal = React.forwardRef(
151682
151888
  (props, forwardedRef) => {
151683
- const context = usePopoverContext(CONTENT_NAME$2, props.__scopePopover);
151889
+ const context = usePopoverContext(CONTENT_NAME$1, props.__scopePopover);
151684
151890
  const contentRef = React.useRef(null);
151685
151891
  const composedRefs = useComposedRefs$1(forwardedRef, contentRef);
151686
151892
  const isRightClickOutsideRef = React.useRef(false);
@@ -151720,7 +151926,7 @@ var PopoverContentModal = React.forwardRef(
151720
151926
  );
151721
151927
  var PopoverContentNonModal = React.forwardRef(
151722
151928
  (props, forwardedRef) => {
151723
- const context = usePopoverContext(CONTENT_NAME$2, props.__scopePopover);
151929
+ const context = usePopoverContext(CONTENT_NAME$1, props.__scopePopover);
151724
151930
  const hasInteractedOutsideRef = React.useRef(false);
151725
151931
  const hasPointerDownOutsideRef = React.useRef(false);
151726
151932
  return /* @__PURE__ */ jsx(
@@ -151772,7 +151978,7 @@ var PopoverContentImpl = React.forwardRef(
151772
151978
  onInteractOutside,
151773
151979
  ...contentProps
151774
151980
  } = props;
151775
- const context = usePopoverContext(CONTENT_NAME$2, __scopePopover);
151981
+ const context = usePopoverContext(CONTENT_NAME$1, __scopePopover);
151776
151982
  const popperScope = usePopperScope(__scopePopover);
151777
151983
  useFocusGuards();
151778
151984
  return /* @__PURE__ */ jsx(
@@ -151796,7 +152002,7 @@ var PopoverContentImpl = React.forwardRef(
151796
152002
  children: /* @__PURE__ */ jsx(
151797
152003
  Content$2,
151798
152004
  {
151799
- "data-state": getState$3(context.open),
152005
+ "data-state": getState$2(context.open),
151800
152006
  role: "dialog",
151801
152007
  id: context.contentId,
151802
152008
  ...popperScope,
@@ -151847,7 +152053,7 @@ var PopoverArrow = React.forwardRef(
151847
152053
  }
151848
152054
  );
151849
152055
  PopoverArrow.displayName = ARROW_NAME;
151850
- function getState$3(open) {
152056
+ function getState$2(open) {
151851
152057
  return open ? "open" : "closed";
151852
152058
  }
151853
152059
  var Root2$2 = Popover$1;
@@ -188555,7 +188761,7 @@ var Checkbox$1 = React.forwardRef(
188555
188761
  role: "checkbox",
188556
188762
  "aria-checked": isIndeterminate(checked) ? "mixed" : checked,
188557
188763
  "aria-required": required,
188558
- "data-state": getState$2(checked),
188764
+ "data-state": getState$1(checked),
188559
188765
  "data-disabled": disabled ? "" : void 0,
188560
188766
  disabled,
188561
188767
  value,
@@ -188600,7 +188806,7 @@ var CheckboxIndicator = React.forwardRef(
188600
188806
  return /* @__PURE__ */ jsx(Presence$3, { present: forceMount || isIndeterminate(context.state) || context.state === true, children: /* @__PURE__ */ jsx(
188601
188807
  Primitive$2.span,
188602
188808
  {
188603
- "data-state": getState$2(context.state),
188809
+ "data-state": getState$1(context.state),
188604
188810
  "data-disabled": context.disabled ? "" : void 0,
188605
188811
  ...indicatorProps,
188606
188812
  ref: forwardedRef,
@@ -188666,14 +188872,14 @@ CheckboxBubbleInput.displayName = BUBBLE_INPUT_NAME;
188666
188872
  function isIndeterminate(checked) {
188667
188873
  return checked === "indeterminate";
188668
188874
  }
188669
- function getState$2(checked) {
188875
+ function getState$1(checked) {
188670
188876
  return isIndeterminate(checked) ? "indeterminate" : checked ? "checked" : "unchecked";
188671
188877
  }
188672
- var Root$4 = Checkbox$1;
188878
+ var Root$3 = Checkbox$1;
188673
188879
  var Indicator$1 = CheckboxIndicator;
188674
188880
 
188675
- const Checkbox = React.forwardRef(({ className, ...props }, ref) => (jsx(Root$4, { ref: ref, className: cn("peer border-primary focus-visible:ring-ring h-4 w-4 shrink-0 rounded-sm border shadow-sm focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-blue-500 data-[state=checked]:text-white", className), ...props, children: jsx(Indicator$1, { className: cn("flex items-center justify-center text-current"), children: jsx(Check, { className: "h-4 w-4" }) }) })));
188676
- Checkbox.displayName = Root$4.displayName;
188881
+ const Checkbox = React.forwardRef(({ className, ...props }, ref) => (jsx(Root$3, { ref: ref, className: cn("peer border-primary focus-visible:ring-ring h-4 w-4 shrink-0 rounded-sm border shadow-sm focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-blue-500 data-[state=checked]:text-white", className), ...props, children: jsx(Indicator$1, { className: cn("flex items-center justify-center text-current"), children: jsx(Check, { className: "h-4 w-4" }) }) })));
188882
+ Checkbox.displayName = Root$3.displayName;
188677
188883
 
188678
188884
  function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermission = false, }) {
188679
188885
  var _a;
@@ -189647,141 +189853,6 @@ function RetrievedDocumentsButton({ sessionId = '', documents, className, label,
189647
189853
  }, "data-testid": "retrieved-documents-button", children: [jsx(FileText, { className: "h-4 w-4 text-blue-600" }), jsx("span", { children: label !== null && label !== void 0 ? label : t('retrievedDocumentsButton.title') })] }), jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: jsxs(DialogContent, { className: "flex max-h-[80vh] flex-col gap-0 p-0 sm:max-w-[425px] md:max-w-[600px]", children: [jsx(DialogHeader, { className: "border-b border-gray-200 px-4 py-2", children: jsxs(DialogTitle, { className: "flex items-center gap-2 text-base font-medium text-[#646464]", children: [jsx(FileText, { className: "h-5 w-5 text-blue-600" }), t('retrievedDocumentsButton.title')] }) }), jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", "data-testid": "retrieved-documents-scroll", children: jsx(DocumentSidebar, { isModal: true, sessionId: sessionId, documents: documents }) })] }) })] }));
189648
189854
  }
189649
189855
 
189650
- var COLLAPSIBLE_NAME = "Collapsible";
189651
- var [createCollapsibleContext] = createContextScope$1(COLLAPSIBLE_NAME);
189652
- var [CollapsibleProvider, useCollapsibleContext] = createCollapsibleContext(COLLAPSIBLE_NAME);
189653
- var Collapsible$1 = React.forwardRef(
189654
- (props, forwardedRef) => {
189655
- const {
189656
- __scopeCollapsible,
189657
- open: openProp,
189658
- defaultOpen,
189659
- disabled,
189660
- onOpenChange,
189661
- ...collapsibleProps
189662
- } = props;
189663
- const [open, setOpen] = useControllableState$2({
189664
- prop: openProp,
189665
- defaultProp: defaultOpen ?? false,
189666
- onChange: onOpenChange,
189667
- caller: COLLAPSIBLE_NAME
189668
- });
189669
- return /* @__PURE__ */ jsx(
189670
- CollapsibleProvider,
189671
- {
189672
- scope: __scopeCollapsible,
189673
- disabled,
189674
- contentId: useId$1(),
189675
- open,
189676
- onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
189677
- children: /* @__PURE__ */ jsx(
189678
- Primitive$4.div,
189679
- {
189680
- "data-state": getState$1(open),
189681
- "data-disabled": disabled ? "" : void 0,
189682
- ...collapsibleProps,
189683
- ref: forwardedRef
189684
- }
189685
- )
189686
- }
189687
- );
189688
- }
189689
- );
189690
- Collapsible$1.displayName = COLLAPSIBLE_NAME;
189691
- var TRIGGER_NAME$1 = "CollapsibleTrigger";
189692
- var CollapsibleTrigger$1 = React.forwardRef(
189693
- (props, forwardedRef) => {
189694
- const { __scopeCollapsible, ...triggerProps } = props;
189695
- const context = useCollapsibleContext(TRIGGER_NAME$1, __scopeCollapsible);
189696
- return /* @__PURE__ */ jsx(
189697
- Primitive$4.button,
189698
- {
189699
- type: "button",
189700
- "aria-controls": context.contentId,
189701
- "aria-expanded": context.open || false,
189702
- "data-state": getState$1(context.open),
189703
- "data-disabled": context.disabled ? "" : void 0,
189704
- disabled: context.disabled,
189705
- ...triggerProps,
189706
- ref: forwardedRef,
189707
- onClick: composeEventHandlers$2(props.onClick, context.onOpenToggle)
189708
- }
189709
- );
189710
- }
189711
- );
189712
- CollapsibleTrigger$1.displayName = TRIGGER_NAME$1;
189713
- var CONTENT_NAME$1 = "CollapsibleContent";
189714
- var CollapsibleContent$1 = React.forwardRef(
189715
- (props, forwardedRef) => {
189716
- const { forceMount, ...contentProps } = props;
189717
- const context = useCollapsibleContext(CONTENT_NAME$1, props.__scopeCollapsible);
189718
- return /* @__PURE__ */ jsx(Presence$2, { present: forceMount || context.open, children: ({ present }) => /* @__PURE__ */ jsx(CollapsibleContentImpl, { ...contentProps, ref: forwardedRef, present }) });
189719
- }
189720
- );
189721
- CollapsibleContent$1.displayName = CONTENT_NAME$1;
189722
- var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
189723
- const { __scopeCollapsible, present, children, ...contentProps } = props;
189724
- const context = useCollapsibleContext(CONTENT_NAME$1, __scopeCollapsible);
189725
- const [isPresent, setIsPresent] = React.useState(present);
189726
- const ref = React.useRef(null);
189727
- const composedRefs = useComposedRefs$1(forwardedRef, ref);
189728
- const heightRef = React.useRef(0);
189729
- const height = heightRef.current;
189730
- const widthRef = React.useRef(0);
189731
- const width = widthRef.current;
189732
- const isOpen = context.open || isPresent;
189733
- const isMountAnimationPreventedRef = React.useRef(isOpen);
189734
- const originalStylesRef = React.useRef(void 0);
189735
- React.useEffect(() => {
189736
- const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);
189737
- return () => cancelAnimationFrame(rAF);
189738
- }, []);
189739
- useLayoutEffect2$1(() => {
189740
- const node = ref.current;
189741
- if (node) {
189742
- originalStylesRef.current = originalStylesRef.current || {
189743
- transitionDuration: node.style.transitionDuration,
189744
- animationName: node.style.animationName
189745
- };
189746
- node.style.transitionDuration = "0s";
189747
- node.style.animationName = "none";
189748
- const rect = node.getBoundingClientRect();
189749
- heightRef.current = rect.height;
189750
- widthRef.current = rect.width;
189751
- if (!isMountAnimationPreventedRef.current) {
189752
- node.style.transitionDuration = originalStylesRef.current.transitionDuration;
189753
- node.style.animationName = originalStylesRef.current.animationName;
189754
- }
189755
- setIsPresent(present);
189756
- }
189757
- }, [context.open, present]);
189758
- return /* @__PURE__ */ jsx(
189759
- Primitive$4.div,
189760
- {
189761
- "data-state": getState$1(context.open),
189762
- "data-disabled": context.disabled ? "" : void 0,
189763
- id: context.contentId,
189764
- hidden: !isOpen,
189765
- ...contentProps,
189766
- ref: composedRefs,
189767
- style: {
189768
- [`--radix-collapsible-content-height`]: height ? `${height}px` : void 0,
189769
- [`--radix-collapsible-content-width`]: width ? `${width}px` : void 0,
189770
- ...props.style
189771
- },
189772
- children: isOpen && children
189773
- }
189774
- );
189775
- });
189776
- function getState$1(open) {
189777
- return open ? "open" : "closed";
189778
- }
189779
- var Root$3 = Collapsible$1;
189780
-
189781
- const Collapsible = Root$3;
189782
- const CollapsibleTrigger = CollapsibleTrigger$1;
189783
- const CollapsibleContent = CollapsibleContent$1;
189784
-
189785
189856
  function getFriendlyToolName(toolName) {
189786
189857
  if (TOOL_NAME_MAP === null || TOOL_NAME_MAP === void 0 ? void 0 : TOOL_NAME_MAP[toolName])
189787
189858
  return TOOL_NAME_MAP[toolName];
@@ -228252,7 +228323,9 @@ function NotificationDropdown({ org, userId, className, onViewNotifications, })
228252
228323
  return (jsx(Fragment$1, { children: jsxs(DropdownMenu, { open: notificationsOpen, onOpenChange: setNotificationsOpen, children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button$1, { variant: "ghost", size: "icon", className: `relative ${className}`, "aria-label": t('notificationsNotificationDropdown.bellAriaLabel', {
228253
228324
  count: unreadCount,
228254
228325
  plural: unreadCount === 1 ? '' : 's',
228255
- }), children: [jsx(Bell, { className: "h-6 w-6 text-[#646464]" }), !isNotificationCountLoading && unreadCount > 0 && (jsx("span", { className: "absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 text-xs text-white", children: unreadCount }))] }) }), jsxs(DropdownMenuContent, { align: "end", className: "w-[300px] p-2 z-[9999] border border-gray-100 max-h-[300px] overflow-y-auto", children: [jsxs("div", { className: "px-4 py-3 text-sm font-semibold border-b border-gray-100 flex items-center justify-between", children: [jsx("span", { children: t('notificationsNotificationDropdown.notificationsHeader') }), jsx(Button$1, { variant: "link", size: "sm", className: "text-sm text-blue-600 h-auto p-0", onClick: () => onViewNotifications === null || onViewNotifications === void 0 ? void 0 : onViewNotifications(), children: t('notificationsNotificationDropdown.viewAll') })] }), isLoading && (jsx("div", { className: "px-3 py-2 text-sm text-gray-500", children: t('notificationsNotificationDropdown.loading') })), (!isLoading && isError) ||
228326
+ }), children: [jsx(Bell, { className: "h-6 w-6 text-[#646464]" }), !isNotificationCountLoading && unreadCount > 0 && (
228327
+ // Anchored from the left so wider counts (e.g. "99+") grow away from the bell
228328
+ jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute top-0.5 left-[55%] flex h-5 min-w-5 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-semibold leading-none tabular-nums text-white ring-2 ring-white", children: unreadCount > 99 ? '99+' : unreadCount }))] }) }), jsxs(DropdownMenuContent, { align: "end", className: "w-[300px] p-2 z-[9999] border border-gray-100 max-h-[300px] overflow-y-auto", children: [jsxs("div", { className: "px-3 py-3 text-sm font-semibold border-b border-gray-100 flex items-center justify-between", children: [jsx("span", { children: t('notificationsNotificationDropdown.notificationsHeader') }), jsx(Button$1, { variant: "link", size: "sm", className: "text-sm text-blue-600 h-auto p-0", onClick: () => onViewNotifications === null || onViewNotifications === void 0 ? void 0 : onViewNotifications(), children: t('notificationsNotificationDropdown.viewAll') })] }), isLoading && (jsx("div", { className: "px-3 py-2 text-sm text-gray-500", children: t('notificationsNotificationDropdown.loading') })), (!isLoading && isError) ||
228256
228329
  (!isLoading && !isError && filteredNotifications.length === 0) ? (jsx("div", { className: "px-3 py-2 text-sm text-gray-500", children: t('notificationsNotificationDropdown.noNewNotifications') })) : (jsxs(Fragment$1, { children: [!isLoading &&
228257
228330
  !isError &&
228258
228331
  filteredNotifications.length > 0 &&
@@ -232032,11 +232105,18 @@ const defaultTabs = [
232032
232105
  label: 'Audit',
232033
232106
  value: 'audit',
232034
232107
  },
232035
- /*{
232036
- label: 'Monetization',
232037
- value: 'monetization',
232038
- },*/
232108
+ {
232109
+ // Opt-in via `enableMonetization`, and then only for a user holding
232110
+ // `can_sell_items` on the tenant — see `canViewMonetizationAnalytics`.
232111
+ label: 'Monetization',
232112
+ value: 'monetization',
232113
+ },
232039
232114
  ];
232115
+ /**
232116
+ * Tab value gated on `enableMonetization` and the selling permission,
232117
+ * whichever `tabs` it comes from.
232118
+ */
232119
+ const MONETIZATION_TAB = 'monetization';
232040
232120
  /**
232041
232121
  * How many results the `dbId` lookup asks for. The query is the agent's own
232042
232122
  * `unique_id`, so the match is normally first; a handful of rows covers a
@@ -232044,7 +232124,7 @@ const defaultTabs = [
232044
232124
  */
232045
232125
  const SCOPE_LOOKUP_LIMIT = 5;
232046
232126
  const className = 'inline-flex h-7 shrink-0 items-center justify-center whitespace-nowrap rounded-[5px] px-2 sm:px-2.5 py-0 text-sm text-gray-500 ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-blue-600 data-[state=active]:font-semibold font-medium data-[state=active]:bg-[#f5f7fb] data-[state=active]:shadow-none cursor-pointer';
232047
- function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs = defaultTabs, activeTabClassName = '', beforeDataReports, excludeTabs = [], showPicker = false, tenantKey, scopedMentor, onScopedMentorChange, }) {
232127
+ function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs = defaultTabs, activeTabClassName = '', beforeDataReports, excludeTabs = [], showPicker = false, tenantKey, scopedMentor, onScopedMentorChange, enableMonetization = false, }) {
232048
232128
  var _a, _b;
232049
232129
  const { currentTenant } = useCurrentTenant();
232050
232130
  const rbacPermissions = useSelector(selectRbacPermissions);
@@ -232113,10 +232193,18 @@ function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs =
232113
232193
  // the caller passed, custom tabs included.
232114
232194
  const isRestricted = isPureWatcher(rbacPermissions, currentTenant);
232115
232195
  const allowedTabs = useMemo(() => getVisibleAnalyticsTabs(rbacPermissions, currentTenant), [rbacPermissions, currentTenant]);
232116
- const canAccessTab = useCallback(
232117
- // Callers may pass custom tab values, so compare as plain strings: anything
232118
- // outside the watcher allow-list stays hidden from a restricted user.
232119
- (tabValue) => !isRestricted || allowedTabs.includes(tabValue), [isRestricted, allowedTabs]);
232196
+ // Monetization is a host opt-in (the tenant's `enable_monetization` flag)
232197
+ // and, on top of that, has its own RBAC action rather than a place in the
232198
+ // watcher allow-list: only a user who may sell on this tenant sees the tab,
232199
+ // admins included — the rule the sidebar and profile Account panel apply.
232200
+ const canViewMonetization = useMemo(() => enableMonetization && canViewMonetizationAnalytics(rbacPermissions, currentTenant), [enableMonetization, rbacPermissions, currentTenant]);
232201
+ const canAccessTab = useCallback((tabValue) => {
232202
+ if (tabValue === MONETIZATION_TAB && !canViewMonetization)
232203
+ return false;
232204
+ // Callers may pass custom tab values, so compare as plain strings: anything
232205
+ // outside the watcher allow-list stays hidden from a restricted user.
232206
+ return !isRestricted || allowedTabs.includes(tabValue);
232207
+ }, [isRestricted, allowedTabs, canViewMonetization]);
232120
232208
  useEffect(() => {
232121
232209
  const mainContentContainer = document.getElementById('main-content-container');
232122
232210
  if (mainContentContainer) {
@@ -232161,18 +232249,20 @@ function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs =
232161
232249
  latestPropsRef.current = { onTabChange, excludeTabs };
232162
232250
  });
232163
232251
  // A watcher who deep-links into a restricted tab (e.g. /analytics/users, or
232164
- // the Overview landing page) gets sent to the first tab they may open. It has
232165
- // to skip `excludeTabs`: a host that drops a tab has no route behind it, so
232252
+ // the Overview landing page) gets sent to the first tab they may open, as
232253
+ // does anyone landing on Monetization while the host has it off or without
232254
+ // the selling permission. It has to skip `excludeTabs`: a host that drops a
232255
+ // tab has no route behind it, so
232166
232256
  // redirecting there would 404 (mentorai excludes courses/programs).
232167
232257
  useEffect(() => {
232168
232258
  if (isActiveTabAllowed)
232169
232259
  return;
232170
232260
  const { onTabChange: notify, excludeTabs: excluded } = latestPropsRef.current;
232171
- const fallbackTab = allowedTabs.find((tab) => !excluded.includes(tab));
232261
+ const fallbackTab = allowedTabs.find((tab) => !excluded.includes(tab) && canAccessTab(tab));
232172
232262
  if (fallbackTab === undefined)
232173
232263
  return;
232174
232264
  notify(fallbackTab);
232175
- }, [isActiveTabAllowed, allowedTabs]);
232265
+ }, [isActiveTabAllowed, allowedTabs, canAccessTab]);
232176
232266
  const handleTabClick = (tabValue) => {
232177
232267
  if (!canAccessTab(tabValue))
232178
232268
  return;
@@ -236092,31 +236182,12 @@ const useMonetization = ({ tenantKey }) => {
236092
236182
  itemType: pw.item_type,
236093
236183
  }));
236094
236184
  })();
236095
- const generateResemblingColors = (totalColors) => {
236096
- const baseColorVariations = [
236097
- '#2b7fff',
236098
- '#4d8fff',
236099
- '#6fa0ff',
236100
- '#91b1ff',
236101
- '#b3c2ff',
236102
- '#1a6fee',
236103
- '#0961dd',
236104
- '#0056cc',
236105
- '#004bbb',
236106
- '#0040aa',
236107
- ];
236108
- const colors = [];
236109
- for (let i = 0; i < totalColors && i < baseColorVariations.length; i++) {
236110
- colors.push(baseColorVariations[i]);
236111
- }
236112
- while (colors.length < totalColors) {
236113
- const hue = Math.floor(Math.random() * 360);
236114
- colors.push(`hsl(${hue}, 70%, 50%)`);
236115
- }
236116
- return colors;
236117
- };
236118
- const statusColors = generateResemblingColors(statusDistribution.length);
236119
- const itemTypeColors = generateResemblingColors(itemTypeDistribution.length);
236185
+ // Slices take the shared categorical palette in order, so neighbouring
236186
+ // statuses and item types are told apart by hue rather than by shades of
236187
+ // one blue. Past six slices the palette cycles, as it does on every other
236188
+ // multi-series chart (see chart-palette.ts).
236189
+ const statusColors = statusDistribution.map((_, index) => colorForRank(index));
236190
+ const itemTypeColors = itemTypeDistribution.map((_, index) => colorForRank(index));
236120
236191
  return {
236121
236192
  revenueData,
236122
236193
  isLoadingRevenue,
@@ -236140,6 +236211,15 @@ const useMonetization = ({ tenantKey }) => {
236140
236211
  };
236141
236212
  };
236142
236213
 
236214
+ /** What a cell shows when the row carries nothing for it, as the other tables do. */
236215
+ const EMPTY_CELL = '\u2014';
236216
+ /** The day a subscription started, or a dash when the row has no usable date. */
236217
+ function formatSubscribedOn(iso) {
236218
+ if (!iso)
236219
+ return EMPTY_CELL;
236220
+ const date = new Date(iso);
236221
+ return Number.isNaN(date.getTime()) ? EMPTY_CELL : format$1(date, 'MMM dd, yyyy');
236222
+ }
236143
236223
  function statusBadgeStyle(status) {
236144
236224
  switch (status) {
236145
236225
  case 'active':
@@ -236154,11 +236234,15 @@ function statusBadgeStyle(status) {
236154
236234
  return 'bg-gray-100 text-gray-500 border-gray-200 hover:bg-gray-100';
236155
236235
  }
236156
236236
  }
236157
- function AnalyticsMonetizationStats({ tenantKey }) {
236237
+ function AnalyticsMonetizationStats({ tenantKey, currentSPA, }) {
236158
236238
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
236159
236239
  const t = useT();
236160
236240
  const { revenueData, isLoadingRevenue, paywallsData, isLoadingPaywalls, subscribersData, isLoadingSubscribers, paywallTypeFilter, setPaywallTypeFilter, subscriberStatusFilter, setSubscriberStatusFilter, paywallPage, setPaywallPage, subscriberPage, setSubscriberPage, statusDistribution, itemTypeDistribution, statusColors, itemTypeColors, } = useMonetization({ tenantKey });
236161
- return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoadingRevenue, title: t('analyticsAnalyticsMonetizationStats.totalRevenue'), value: Number((revenueData === null || revenueData === void 0 ? void 0 : revenueData.sales_volume) || 0).toLocaleString(), showDollarSign: true, description: t('analyticsAnalyticsMonetizationStats.totalRevenueDescription') }), jsx(StatCard, { loading: isLoadingRevenue, title: t('analyticsAnalyticsMonetizationStats.totalSales'), value: (_a = revenueData === null || revenueData === void 0 ? void 0 : revenueData.sales_count) !== null && _a !== void 0 ? _a : 0, description: t('analyticsAnalyticsMonetizationStats.totalSalesDescription') }), jsx(StatCard, { loading: isLoadingPaywalls, title: t('analyticsAnalyticsMonetizationStats.activePaywalls'), value: (_b = paywallsData === null || paywallsData === void 0 ? void 0 : paywallsData.count) !== null && _b !== void 0 ? _b : 0, description: t('analyticsAnalyticsMonetizationStats.activePaywallsDescription') }), jsx(StatCard, { loading: isLoadingSubscribers, title: t('analyticsAnalyticsMonetizationStats.totalSubscribers'), value: (_c = subscribersData === null || subscribersData === void 0 ? void 0 : subscribersData.count) !== null && _c !== void 0 ? _c : 0, description: t('analyticsAnalyticsMonetizationStats.totalSubscribersDescription') })] }), jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-5", children: [jsx(Card$1, { className: "w-full bg-white rounded-lg border border-gray-100 overflow-hidden shadow-sm", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsMonetizationStats.subscriptionStatusChartCardAriaLabel'), children: [jsx("div", { className: "mb-6", children: jsxs("div", { className: "flex items-center gap-1", children: [jsx("h3", { className: "text-base font-medium text-gray-700", children: t('analyticsAnalyticsMonetizationStats.subscribersByStatus') }), jsx(CardInfoIcon, { title: t('analyticsAnalyticsMonetizationStats.subscribersByStatus'), description: t('analyticsAnalyticsMonetizationStats.subscribersByStatusDescription') })] }) }), jsx("div", { className: "w-full", style: { height: '350px' }, children: jsx(ChartContainer, { title: t('analyticsAnalyticsMonetizationStats.subscribersByStatus'), config: {
236241
+ return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoadingRevenue, title: t('analyticsAnalyticsMonetizationStats.totalRevenue'),
236242
+ // Fixed two decimals with no locale grouping, the way every cost
236243
+ // card on the Cost tab reads — `toLocaleString` gave "4 180,5" in a
236244
+ // French browser.
236245
+ value: Number((revenueData === null || revenueData === void 0 ? void 0 : revenueData.sales_volume) || 0).toFixed(2), showDollarSign: true, description: t('analyticsAnalyticsMonetizationStats.totalRevenueDescription') }), jsx(StatCard, { loading: isLoadingRevenue, title: t('analyticsAnalyticsMonetizationStats.totalSales'), value: (_a = revenueData === null || revenueData === void 0 ? void 0 : revenueData.sales_count) !== null && _a !== void 0 ? _a : 0, description: t('analyticsAnalyticsMonetizationStats.totalSalesDescription') }), jsx(StatCard, { loading: isLoadingPaywalls, title: t('analyticsAnalyticsMonetizationStats.activePaywalls'), value: (_b = paywallsData === null || paywallsData === void 0 ? void 0 : paywallsData.count) !== null && _b !== void 0 ? _b : 0, description: t('analyticsAnalyticsMonetizationStats.activePaywallsDescription') }), jsx(StatCard, { loading: isLoadingSubscribers, title: t('analyticsAnalyticsMonetizationStats.totalSubscribers'), value: (_c = subscribersData === null || subscribersData === void 0 ? void 0 : subscribersData.count) !== null && _c !== void 0 ? _c : 0, description: t('analyticsAnalyticsMonetizationStats.totalSubscribersDescription') })] }), jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-5", children: [jsx(Card$1, { className: "w-full bg-white rounded-lg border border-gray-100 overflow-hidden shadow-sm", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsMonetizationStats.subscriptionStatusChartCardAriaLabel'), children: [jsx("div", { className: "mb-6", children: jsxs("div", { className: "flex items-center gap-1", children: [jsx("h3", { className: "text-base font-medium text-gray-700", children: t('analyticsAnalyticsMonetizationStats.subscribersByStatus') }), jsx(CardInfoIcon, { title: t('analyticsAnalyticsMonetizationStats.subscribersByStatus'), description: t('analyticsAnalyticsMonetizationStats.subscribersByStatusDescription') })] }) }), jsx("div", { className: "w-full", style: { height: '350px' }, children: jsx(ChartContainer, { title: t('analyticsAnalyticsMonetizationStats.subscribersByStatus'), config: {
236162
236246
  value: {
236163
236247
  label: t('analyticsAnalyticsMonetizationStats.subscribersLabel'),
236164
236248
  color: '#38A1E5',
@@ -236193,11 +236277,11 @@ function AnalyticsMonetizationStats({ tenantKey }) {
236193
236277
  }), description: t('analyticsAnalyticsMonetizationStats.subscribersTableDescription') })] }), jsxs(Select$1, { value: subscriberStatusFilter, onValueChange: (v) => {
236194
236278
  setSubscriberStatusFilter(v);
236195
236279
  setSubscriberPage(1);
236196
- }, children: [jsx(SelectTrigger, { className: "w-[130px]", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('analyticsAnalyticsMonetizationStats.filterAll') }), jsx(SelectItem, { value: "active", children: t('analyticsAnalyticsMonetizationStats.filterActive') }), jsx(SelectItem, { value: "trialing", children: t('analyticsAnalyticsMonetizationStats.filterTrialing') }), jsx(SelectItem, { value: "canceled", children: t('analyticsAnalyticsMonetizationStats.filterCanceled') }), jsx(SelectItem, { value: "past_due", children: t('analyticsAnalyticsMonetizationStats.filterPastDue') })] })] })] }) }), jsx("div", { className: "rounded-md overflow-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "w-[250px]", children: t('analyticsAnalyticsMonetizationStats.tableHeadItem') }), jsx(TableHead, { className: "w-[100px]", children: t('analyticsAnalyticsMonetizationStats.tableHeadType') }), jsx(TableHead, { className: "w-[120px]", children: t('analyticsAnalyticsMonetizationStats.tableHeadPlan') }), jsx(TableHead, { className: "w-[100px]", children: t('analyticsAnalyticsMonetizationStats.tableHeadAmount') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsMonetizationStats.tableHeadStatus') })] }) }), jsx(TableBody, { children: (_f = subscribersData === null || subscribersData === void 0 ? void 0 : subscribersData.results) === null || _f === void 0 ? void 0 : _f.map((sub, index) => {
236280
+ }, children: [jsx(SelectTrigger, { className: "w-[130px]", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('analyticsAnalyticsMonetizationStats.filterAll') }), jsx(SelectItem, { value: "active", children: t('analyticsAnalyticsMonetizationStats.filterActive') }), jsx(SelectItem, { value: "trialing", children: t('analyticsAnalyticsMonetizationStats.filterTrialing') }), jsx(SelectItem, { value: "canceled", children: t('analyticsAnalyticsMonetizationStats.filterCanceled') }), jsx(SelectItem, { value: "past_due", children: t('analyticsAnalyticsMonetizationStats.filterPastDue') })] })] })] }) }), jsx("div", { className: "rounded-md overflow-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { className: "table-fixed min-w-[900px]", children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "w-[24%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadUser') }), jsx(TableHead, { className: "w-[24%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadItem') }), jsx(TableHead, { className: "w-[10.4%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadType') }), jsx(TableHead, { className: "w-[10.4%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadPlan') }), jsx(TableHead, { className: "w-[10.4%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadAmount') }), jsx(TableHead, { className: "w-[10.4%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadSubscribed') }), jsx(TableHead, { className: "w-[10.4%] text-right", children: t('analyticsAnalyticsMonetizationStats.tableHeadStatus') })] }) }), jsx(TableBody, { children: (_f = subscribersData === null || subscribersData === void 0 ? void 0 : subscribersData.results) === null || _f === void 0 ? void 0 : _f.map((sub, index) => {
236197
236281
  var _a, _b, _c;
236198
- return (jsxs(TableRow, { className: cn(index % 2 === 0 ? 'bg-gray-50' : '', 'h-[48px]'), style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell, { className: "font-medium", children: sub.item_name || sub.item_id }), jsx(TableCell, { children: jsx(Badge, { variant: "secondary", className: "text-xs capitalize", children: sub.item_type }) }), jsx(TableCell, { children: (_a = sub.price) === null || _a === void 0 ? void 0 : _a.name }), jsx(TableCell, { children: sub.status === 'grandfathered' ? null : (jsxs(Fragment$1, { children: ["$", (_b = sub.price) === null || _b === void 0 ? void 0 : _b.amount, ((_c = sub.price) === null || _c === void 0 ? void 0 : _c.interval) && sub.price.interval !== 'one_time'
236282
+ return (jsxs(TableRow, { className: cn(index % 2 === 0 ? 'bg-gray-50' : '', 'h-[48px]'), style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell, { className: "font-medium", children: jsx(UserProfileLink, { tenantKey: tenantKey, currentSPA: currentSPA, username: sub.username, display: sub.email || sub.username || EMPTY_CELL }) }), jsx(TableCell, { className: "font-medium truncate", title: sub.item_name || sub.item_id, children: sub.item_name || sub.item_id }), jsx(TableCell, { children: jsx(Badge, { variant: "secondary", className: "text-xs capitalize", children: sub.item_type }) }), jsx(TableCell, { children: (_a = sub.price) === null || _a === void 0 ? void 0 : _a.name }), jsx(TableCell, { className: "whitespace-nowrap", children: sub.status === 'grandfathered' ? null : (jsxs(Fragment$1, { children: ["$", (_b = sub.price) === null || _b === void 0 ? void 0 : _b.amount, ((_c = sub.price) === null || _c === void 0 ? void 0 : _c.interval) && sub.price.interval !== 'one_time'
236199
236283
  ? `/${sub.price.interval}`
236200
- : ''] })) }), jsx(TableCell, { className: "text-right", children: jsx(Badge, { className: statusBadgeStyle(sub.status), children: sub.status }) })] }, sub.unique_id));
236284
+ : ''] })) }), jsx(TableCell, { className: "whitespace-nowrap", children: formatSubscribedOn(sub.created_at) }), jsx(TableCell, { className: "text-right", children: jsx(Badge, { className: statusBadgeStyle(sub.status), children: sub.status }) })] }, sub.unique_id));
236201
236285
  }) })] }) }), (!((_g = subscribersData === null || subscribersData === void 0 ? void 0 : subscribersData.results) === null || _g === void 0 ? void 0 : _g.length) || ((_h = subscribersData === null || subscribersData === void 0 ? void 0 : subscribersData.results) === null || _h === void 0 ? void 0 : _h.length) === 0) && (jsx("div", { className: "h-[60px]", children: jsx(EmptyStats, {}) })), subscribersData &&
236202
236286
  (subscribersData.previous_page !== null || subscribersData.next_page !== null) && (jsxs("div", { className: "flex items-center justify-between py-3", children: [jsx("div", { className: "text-sm text-gray-700", children: t('analyticsAnalyticsMonetizationStats.subscriberCountTotal', {
236203
236287
  count: subscribersData.count,
@@ -236211,9 +236295,9 @@ function AnalyticsMonetizationStats({ tenantKey }) {
236211
236295
  }), description: t('analyticsAnalyticsMonetizationStats.paywallsTableDescription') })] }), jsxs(Select$1, { value: paywallTypeFilter, onValueChange: (v) => {
236212
236296
  setPaywallTypeFilter(v);
236213
236297
  setPaywallPage(1);
236214
- }, children: [jsx(SelectTrigger, { className: "w-[130px]", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('analyticsAnalyticsMonetizationStats.filterAllTypes') }), jsx(SelectItem, { value: "mentor", children: t('analyticsAnalyticsMonetizationStats.filterAgent') }), jsx(SelectItem, { value: "course", children: t('analyticsAnalyticsMonetizationStats.filterCourse') })] })] })] }) }), jsx("div", { className: "rounded-md overflow-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "w-[250px]", children: t('analyticsAnalyticsMonetizationStats.tableHeadItem') }), jsx(TableHead, { className: "w-[100px]", children: t('analyticsAnalyticsMonetizationStats.tableHeadType') }), jsx(TableHead, { className: "w-[100px]", children: t('analyticsAnalyticsMonetizationStats.tableHeadPrices') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsMonetizationStats.tableHeadStatus') })] }) }), jsx(TableBody, { children: (_l = paywallsData === null || paywallsData === void 0 ? void 0 : paywallsData.results) === null || _l === void 0 ? void 0 : _l.map((pw, index) => {
236298
+ }, children: [jsx(SelectTrigger, { className: "w-[130px]", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('analyticsAnalyticsMonetizationStats.filterAllTypes') }), jsx(SelectItem, { value: "mentor", children: t('analyticsAnalyticsMonetizationStats.filterAgent') }), jsx(SelectItem, { value: "course", children: t('analyticsAnalyticsMonetizationStats.filterCourse') })] })] })] }) }), jsx("div", { className: "rounded-md overflow-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { className: "table-fixed min-w-[640px]", children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "w-[40%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadItem') }), jsx(TableHead, { className: "w-[20%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadType') }), jsx(TableHead, { className: "w-[20%]", children: t('analyticsAnalyticsMonetizationStats.tableHeadPrices') }), jsx(TableHead, { className: "w-[20%] text-right", children: t('analyticsAnalyticsMonetizationStats.tableHeadStatus') })] }) }), jsx(TableBody, { children: (_l = paywallsData === null || paywallsData === void 0 ? void 0 : paywallsData.results) === null || _l === void 0 ? void 0 : _l.map((pw, index) => {
236215
236299
  var _a, _b;
236216
- return (jsxs(TableRow, { className: cn(index % 2 === 0 ? 'bg-gray-50' : '', 'h-[48px]'), style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell, { className: "font-medium", children: pw.item_name || pw.item_id }), jsx(TableCell, { children: jsx(Badge, { variant: "secondary", className: "text-xs capitalize", children: pw.item_type }) }), jsx(TableCell, { children: t('analyticsAnalyticsMonetizationStats.activePricesCount', {
236300
+ return (jsxs(TableRow, { className: cn(index % 2 === 0 ? 'bg-gray-50' : '', 'h-[48px]'), style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell, { className: "font-medium truncate", title: pw.item_name || pw.item_id, children: pw.item_name || pw.item_id }), jsx(TableCell, { children: jsx(Badge, { variant: "secondary", className: "text-xs capitalize", children: pw.item_type }) }), jsx(TableCell, { children: t('analyticsAnalyticsMonetizationStats.activePricesCount', {
236217
236301
  count: (_b = (_a = pw.prices) === null || _a === void 0 ? void 0 : _a.filter((p) => p.is_active).length) !== null && _b !== void 0 ? _b : 0,
236218
236302
  }) }), jsx(TableCell, { className: "text-right", children: jsx(Badge, { className: pw.is_enabled
236219
236303
  ? 'bg-blue-100 text-blue-700 border-blue-200 hover:bg-blue-100'