@atlashub/smartstack 3.28.0 → 3.30.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.
- package/dist/chunks/{AgentSkillsPage-ChykpPZx.js → AgentSkillsPage-CVq3qZoe.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ChykpPZx.js.map → AgentSkillsPage-CVq3qZoe.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-ABpqnnyK.js → AgentSkillsPage-DJb49NMA.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ABpqnnyK.js.map → AgentSkillsPage-DJb49NMA.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BltzNlXI.js → AgentWorkloadPage-D_nk3gKj.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BltzNlXI.js.map → AgentWorkloadPage-D_nk3gKj.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BI5QWJyQ.js → AgentWorkloadPage-oHEi-sFh.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BI5QWJyQ.js.map → AgentWorkloadPage-oHEi-sFh.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BaheZKBq.js → ApiCatalogDetailPage-Cr0q2HnB.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-BaheZKBq.js.map → ApiCatalogDetailPage-Cr0q2HnB.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-CsRxlHwO.js → ApiCatalogDetailPage-DX8buBkV.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-CsRxlHwO.js.map → ApiCatalogDetailPage-DX8buBkV.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-CqmmHpQ4.js → ApiCatalogPage-DN7sazvI.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-CqmmHpQ4.js.map → ApiCatalogPage-DN7sazvI.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-B0yIz8-U.js → ApiCatalogPage-DqboIzZE.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-B0yIz8-U.js.map → ApiCatalogPage-DqboIzZE.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CngD5JSN.js → ApplicationDetailPage--9YwwS5A.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage-CngD5JSN.js.map → ApplicationDetailPage--9YwwS5A.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CdT6KNd7.js → ApplicationDetailPage-CCNjr64K.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-CdT6KNd7.js.map → ApplicationDetailPage-CCNjr64K.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-DHmnjk2O.js → ApplicationsDashboardPage-BSsHN3Yj.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-DHmnjk2O.js.map → ApplicationsDashboardPage-BSsHN3Yj.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-1V4iQ6eY.js → ApplicationsDashboardPage-Bs-Xgca4.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-1V4iQ6eY.js.map → ApplicationsDashboardPage-Bs-Xgca4.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-Bo3NDnBF.js → ApplicationsGridPage-DDysNWJ5.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-Bo3NDnBF.js.map → ApplicationsGridPage-DDysNWJ5.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-CiMJFlB_.js → ApplicationsGridPage-s1WEzOXS.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-CiMJFlB_.js.map → ApplicationsGridPage-s1WEzOXS.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-L2_S23aN.js → ApplicationsListPage-B3CSMiV0.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-L2_S23aN.js.map → ApplicationsListPage-B3CSMiV0.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-De8jQ1Cm.js → ApplicationsListPage-B6ZCecIl.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-De8jQ1Cm.js.map → ApplicationsListPage-B6ZCecIl.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-DBq7_Sm8.js → ApplicationsPage-BBaiBM--.js} +2 -2
- package/dist/chunks/{ApplicationsPage-DBq7_Sm8.js.map → ApplicationsPage-BBaiBM--.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-CiNI-b0R.js → ApplicationsPage-ztPwoAGt.js} +4 -4
- package/dist/chunks/{ApplicationsPage-CiNI-b0R.js.map → ApplicationsPage-ztPwoAGt.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-DFsO4ZES.js → AssignmentRulesPage-CK4L4rBO.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-DFsO4ZES.js.map → AssignmentRulesPage-CK4L4rBO.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-C8rfUsMB.js → AssignmentRulesPage-DFSVFFXr.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-C8rfUsMB.js.map → AssignmentRulesPage-DFSVFFXr.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-78C_EBsw.js → AssignmentsPage-Bp7oQD7Q.js} +2 -2
- package/dist/chunks/{AssignmentsPage-78C_EBsw.js.map → AssignmentsPage-Bp7oQD7Q.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-COCikISI.js → AssignmentsPage-JCLpyg94.js} +2 -2
- package/dist/chunks/{AssignmentsPage-COCikISI.js.map → AssignmentsPage-JCLpyg94.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-DqT6ueVi.js → AuthCallbackPage-Bl9xlJ3h.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-DqT6ueVi.js.map → AuthCallbackPage-Bl9xlJ3h.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BF4bkTnR.js → AuthCallbackPage-CzMHz4jy.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BF4bkTnR.js.map → AuthCallbackPage-CzMHz4jy.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-Bh_K5qJn.js → ConfirmEmailPage-D_8T1vqV.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-Bh_K5qJn.js.map → ConfirmEmailPage-D_8T1vqV.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-DJy4idrf.js → ConfirmEmailPage-M7mJgXvn.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-DJy4idrf.js.map → ConfirmEmailPage-M7mJgXvn.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-pL7jbG9o.js → CreateSupportTicketPage-BNEGavlu.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-pL7jbG9o.js.map → CreateSupportTicketPage-BNEGavlu.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-AVTwXbJd.js → CreateSupportTicketPage-C2X2mfds.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-AVTwXbJd.js.map → CreateSupportTicketPage-C2X2mfds.js.map} +1 -1
- package/dist/chunks/{DashboardPage-DdQlTLw0.js → DashboardPage-4oy2YqvT.js} +2 -2
- package/dist/chunks/{DashboardPage-DdQlTLw0.js.map → DashboardPage-4oy2YqvT.js.map} +1 -1
- package/dist/chunks/{DashboardPage-C55mIiB6.js → DashboardPage-CO-8B8EI.js} +3 -3
- package/dist/chunks/{DashboardPage-C55mIiB6.js.map → DashboardPage-CO-8B8EI.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CcCnUl7s.js → DashboardPage-CPArUG-S.js} +2 -2
- package/dist/chunks/{DashboardPage-CcCnUl7s.js.map → DashboardPage-CPArUG-S.js.map} +1 -1
- package/dist/chunks/{DashboardPage-DOitDfGV.js → DashboardPage-D5MRMxEV.js} +3 -3
- package/dist/chunks/{DashboardPage-DOitDfGV.js.map → DashboardPage-D5MRMxEV.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-DNnZftCH.js → EscalationConfigPage-CwdnfJbJ.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-DNnZftCH.js.map → EscalationConfigPage-CwdnfJbJ.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-DRr55328.js → EscalationConfigPage-DnjLFXnL.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-DRr55328.js.map → EscalationConfigPage-DnjLFXnL.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-1SCOPIqK.js → ForceChangePasswordPage-ZEIfyqwE.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-1SCOPIqK.js.map → ForceChangePasswordPage-ZEIfyqwE.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-DBeG_HRO.js → ForceChangePasswordPage-sh-3h_H9.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-DBeG_HRO.js.map → ForceChangePasswordPage-sh-3h_H9.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-Dlb6wKfC.js → ForgotPasswordPage-B4M6-xeM.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-Dlb6wKfC.js.map → ForgotPasswordPage-B4M6-xeM.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-DffYfXva.js → ForgotPasswordPage-MIu-U7p0.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-DffYfXva.js.map → ForgotPasswordPage-MIu-U7p0.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-C9nRbeHI.js → GroupDetailPage-4XK3Bs_r.js} +5 -5
- package/dist/chunks/{GroupDetailPage-C9nRbeHI.js.map → GroupDetailPage-4XK3Bs_r.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-CPPUWzXf.js → GroupDetailPage-C-kvtd2T.js} +2 -2
- package/dist/chunks/{GroupDetailPage-CPPUWzXf.js.map → GroupDetailPage-C-kvtd2T.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-BAX0xwJX.js → MyAccessRequestsPage-CP41FzHi.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-BAX0xwJX.js.map → MyAccessRequestsPage-CP41FzHi.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-BMY1V631.js → MyAccessRequestsPage-DzrXTrVi.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-BMY1V631.js.map → MyAccessRequestsPage-DzrXTrVi.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-Bbn4HxN2.js → MyTenantsPage-CZRkMbh8.js} +2 -2
- package/dist/chunks/{MyTenantsPage-Bbn4HxN2.js.map → MyTenantsPage-CZRkMbh8.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BHtp67SD.js → MyTenantsPage-V_SwYio2.js} +3 -3
- package/dist/chunks/{MyTenantsPage-BHtp67SD.js.map → MyTenantsPage-V_SwYio2.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-BvZeiTXu.js → MyTicketsPage-DOUhaLal.js} +2 -2
- package/dist/chunks/{MyTicketsPage-BvZeiTXu.js.map → MyTicketsPage-DOUhaLal.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-D9IGVofj.js → MyTicketsPage-DnvAIeyr.js} +2 -2
- package/dist/chunks/{MyTicketsPage-D9IGVofj.js.map → MyTicketsPage-DnvAIeyr.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-DiPBCsAF.js → NavigationAppsPage-DXvpLsbt.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-DiPBCsAF.js.map → NavigationAppsPage-DXvpLsbt.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-ChtMK1yt.js → NavigationAppsPage-DfTa4jCG.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-ChtMK1yt.js.map → NavigationAppsPage-DfTa4jCG.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BxCiGzHk.js → NotificationsPage-D76MdAs-.js} +2 -2
- package/dist/chunks/{NotificationsPage-BxCiGzHk.js.map → NotificationsPage-D76MdAs-.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BCnL9oPb.js → NotificationsPage-I1yCk7tk.js} +2 -2
- package/dist/chunks/{NotificationsPage-BCnL9oPb.js.map → NotificationsPage-I1yCk7tk.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-CV_cxq7k.js → OnboardingWizardPage-BRUzcl1A.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-CV_cxq7k.js.map → OnboardingWizardPage-BRUzcl1A.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-Du-tQ2ag.js → OnboardingWizardPage-DtWUPCh3.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-Du-tQ2ag.js.map → OnboardingWizardPage-DtWUPCh3.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-C1iuWv0G.js → PermissionDetailPage-CUNKbl7t.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-C1iuWv0G.js.map → PermissionDetailPage-CUNKbl7t.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Ds4Jt1os.js → PermissionDetailPage-DJJGbXoX.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Ds4Jt1os.js.map → PermissionDetailPage-DJJGbXoX.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-BGI2nxCn.js → PermissionsPage-B8wmawPV.js} +2 -2
- package/dist/chunks/{PermissionsPage-BGI2nxCn.js.map → PermissionsPage-B8wmawPV.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-sauv7ct1.js → PermissionsPage-Dbjcctuh.js} +2 -2
- package/dist/chunks/{PermissionsPage-sauv7ct1.js.map → PermissionsPage-Dbjcctuh.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-CQWEcghD.js → PortalDashboardPage-BeNfBZmb.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-CQWEcghD.js.map → PortalDashboardPage-BeNfBZmb.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-2kCbJw9w.js → PortalDashboardPage-zii0ll57.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-2kCbJw9w.js.map → PortalDashboardPage-zii0ll57.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Bu4gaDRb.js → PreferencesPage-BCpuIGzv.js} +2 -2
- package/dist/chunks/{PreferencesPage-Bu4gaDRb.js.map → PreferencesPage-BCpuIGzv.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Dbg0bEYD.js → PreferencesPage-BmvrBaAD.js} +2 -2
- package/dist/chunks/{PreferencesPage-Dbg0bEYD.js.map → PreferencesPage-BmvrBaAD.js.map} +1 -1
- package/dist/chunks/{ProfilePage-C5QS7tsh.js → ProfilePage-eowQd59_.js} +2 -2
- package/dist/chunks/{ProfilePage-C5QS7tsh.js.map → ProfilePage-eowQd59_.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DfiBhOUt.js → ProfilePage-mf5wI0-n.js} +2 -2
- package/dist/chunks/{ProfilePage-DfiBhOUt.js.map → ProfilePage-mf5wI0-n.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-Bs0mapj8.js → ReferencesManagementPage-8UPgkVE8.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-Bs0mapj8.js.map → ReferencesManagementPage-8UPgkVE8.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-C0RgHbJb.js → ReferencesManagementPage-CLsaUNqA.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-C0RgHbJb.js.map → ReferencesManagementPage-CLsaUNqA.js.map} +1 -1
- package/dist/chunks/{RegisterPage-DS1chV_A.js → RegisterPage-57X-ILDb.js} +2 -2
- package/dist/chunks/{RegisterPage-DS1chV_A.js.map → RegisterPage-57X-ILDb.js.map} +1 -1
- package/dist/chunks/{RegisterPage-DoeIiJt0.js → RegisterPage-CNyHSbqs.js} +2 -2
- package/dist/chunks/{RegisterPage-DoeIiJt0.js.map → RegisterPage-CNyHSbqs.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-3KEk3zj5.js → ResetPasswordPage-CyV8l-Zo.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-3KEk3zj5.js.map → ResetPasswordPage-CyV8l-Zo.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-C_VQSFB5.js → ResetPasswordPage-JW8-mh_k.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-C_VQSFB5.js.map → ResetPasswordPage-JW8-mh_k.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-S6URD--N.js → ResolutionModal-CjwE73NX.js} +2 -2
- package/dist/chunks/{ResolutionModal-S6URD--N.js.map → ResolutionModal-CjwE73NX.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-BzI1x79r.js → ResolutionModal-wddG59kg.js} +2 -2
- package/dist/chunks/{ResolutionModal-BzI1x79r.js.map → ResolutionModal-wddG59kg.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-SXK9cq_3.js → RoleDetailPage-CrioVHFI.js} +3 -3
- package/dist/chunks/{RoleDetailPage-SXK9cq_3.js.map → RoleDetailPage-CrioVHFI.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-DvEEWPKr.js → RoleDetailPage-TUOGR1ow.js} +2 -2
- package/dist/chunks/{RoleDetailPage-DvEEWPKr.js.map → RoleDetailPage-TUOGR1ow.js.map} +1 -1
- package/dist/chunks/{RolesPage-B75lCugt.js → RolesPage-CAcols3D.js} +2 -2
- package/dist/chunks/{RolesPage-B75lCugt.js.map → RolesPage-CAcols3D.js.map} +1 -1
- package/dist/chunks/{RolesPage-C5gYJxAl.js → RolesPage-sJBWaNff.js} +2 -2
- package/dist/chunks/{RolesPage-C5gYJxAl.js.map → RolesPage-sJBWaNff.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BqXHATb6.js → SlaConfigPage-BPGRloOS.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BqXHATb6.js.map → SlaConfigPage-BPGRloOS.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-DZ4P1FFW.js → SlaConfigPage-D5TRn7Ir.js} +2 -2
- package/dist/chunks/{SlaConfigPage-DZ4P1FFW.js.map → SlaConfigPage-D5TRn7Ir.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-B4xy_pCQ.js → SupportPermissionsPage-Dc2bWTzG.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-B4xy_pCQ.js.map → SupportPermissionsPage-Dc2bWTzG.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-DW7KJjYK.js → SupportPermissionsPage-UXmYLrIq.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-DW7KJjYK.js.map → SupportPermissionsPage-UXmYLrIq.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DZa0PQTE.js → TemplatesPage-dmPlqqiD.js} +2 -2
- package/dist/chunks/{TemplatesPage-DZa0PQTE.js.map → TemplatesPage-dmPlqqiD.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-m5-sLJ7F.js → TemplatesPage-nTY85sNA.js} +2 -2
- package/dist/chunks/{TemplatesPage-m5-sLJ7F.js.map → TemplatesPage-nTY85sNA.js.map} +1 -1
- package/dist/chunks/{TenantCard-BJQi7Oew.js → TenantCard-BUXfstRZ.js} +2 -2
- package/dist/chunks/{TenantCard-BJQi7Oew.js.map → TenantCard-BUXfstRZ.js.map} +1 -1
- package/dist/chunks/{TenantCard-CqfifMrM.js → TenantCard-BhT-31ls.js} +2 -2
- package/dist/chunks/{TenantCard-CqfifMrM.js.map → TenantCard-BhT-31ls.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-CdiYJvuH.js → TenantScopeSelector-3_mzBLNI.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-CdiYJvuH.js.map → TenantScopeSelector-3_mzBLNI.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Cl5DD318.js → TenantScopeSelector-B-SRDR2R.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Cl5DD318.js.map → TenantScopeSelector-B-SRDR2R.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-BOC9rHu3.js → TicketDetailPage-B4cR3rOC.js} +2 -2
- package/dist/chunks/{TicketDetailPage-BOC9rHu3.js.map → TicketDetailPage-B4cR3rOC.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-C1UuMxD8.js → TicketDetailPage-xN3wPnFL.js} +2 -2
- package/dist/chunks/{TicketDetailPage-C1UuMxD8.js.map → TicketDetailPage-xN3wPnFL.js.map} +1 -1
- package/dist/chunks/{TicketsPage-BCgHZA-m.js → TicketsPage-CkHgXSxU.js} +2 -2
- package/dist/chunks/{TicketsPage-BCgHZA-m.js.map → TicketsPage-CkHgXSxU.js.map} +1 -1
- package/dist/chunks/{TicketsPage-BjaN4Baq.js → TicketsPage-Dwi2xpMI.js} +2 -2
- package/dist/chunks/{TicketsPage-BjaN4Baq.js.map → TicketsPage-Dwi2xpMI.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-ChQL1mVY.js → UserCreateTicketPage-D2a3EOey.js} +3 -3
- package/dist/chunks/UserCreateTicketPage-D2a3EOey.js.map +1 -0
- package/dist/chunks/{UserCreateTicketPage-DkjsHeV7.js → UserCreateTicketPage-bcbSLglE.js} +48 -48
- package/dist/chunks/UserCreateTicketPage-bcbSLglE.js.map +1 -0
- package/dist/chunks/{UserDashboardPage-BMYrtF3o.js → UserDashboardPage-DwnDRNoW.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BMYrtF3o.js.map → UserDashboardPage-DwnDRNoW.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-81-3GJAQ.js → UserDashboardPage-ZMsx8LWw.js} +2 -2
- package/dist/chunks/{UserDashboardPage-81-3GJAQ.js.map → UserDashboardPage-ZMsx8LWw.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BMW8jAWG.js → UserDetailPage-BRFowOFL.js} +2 -2
- package/dist/chunks/{UserDetailPage-BMW8jAWG.js.map → UserDetailPage-BRFowOFL.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-D6oCH2eS.js → UserDetailPage-CZyV-zsg.js} +5 -5
- package/dist/chunks/{UserDetailPage-D6oCH2eS.js.map → UserDetailPage-CZyV-zsg.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-ZH2BDWBt.js → UserTicketDetailPage-BstGk_BP.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-ZH2BDWBt.js.map → UserTicketDetailPage-BstGk_BP.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-Z_myXXJ0.js → UserTicketDetailPage-DzB_pELt.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-Z_myXXJ0.js.map → UserTicketDetailPage-DzB_pELt.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-B8Ka6uRa.js → UsersGroupsPage-BygTv_kK.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-B8Ka6uRa.js.map → UsersGroupsPage-BygTv_kK.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-xJmGib8b.js → UsersGroupsPage-DTmhzttW.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-xJmGib8b.js.map → UsersGroupsPage-DTmhzttW.js.map} +1 -1
- package/dist/chunks/{UsersPage-CQ38akZ_.js → UsersPage-DcwLyMAX.js} +2 -2
- package/dist/chunks/{UsersPage-CQ38akZ_.js.map → UsersPage-DcwLyMAX.js.map} +1 -1
- package/dist/chunks/{UsersPage-Bd2-vl39.js → UsersPage-TIqSHgHj.js} +2 -2
- package/dist/chunks/{UsersPage-Bd2-vl39.js.map → UsersPage-TIqSHgHj.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-DguOx0q0.js → accessRequestsApi-3FjMFbpa.js} +2 -2
- package/dist/chunks/{accessRequestsApi-DguOx0q0.js.map → accessRequestsApi-3FjMFbpa.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-COtWo9kC.js → accessRequestsApi-B6dsJzvH.js} +2 -2
- package/dist/chunks/{accessRequestsApi-COtWo9kC.js.map → accessRequestsApi-B6dsJzvH.js.map} +1 -1
- package/dist/chunks/{aiApi-CITiWGYX.js → aiApi-9G4wG_mT.js} +2 -2
- package/dist/chunks/{aiApi-CITiWGYX.js.map → aiApi-9G4wG_mT.js.map} +1 -1
- package/dist/chunks/{aiApi-BmZsud6O.js → aiApi-DXOdsoxr.js} +2 -2
- package/dist/chunks/{aiApi-BmZsud6O.js.map → aiApi-DXOdsoxr.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-BYoEJzSN.js → applicationAnalyticsApi-D0DEp9Y-.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-BYoEJzSN.js.map → applicationAnalyticsApi-D0DEp9Y-.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-D62lc6z4.js → applicationAnalyticsApi-DhOd6idI.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-D62lc6z4.js.map → applicationAnalyticsApi-DhOd6idI.js.map} +1 -1
- package/dist/chunks/auth-Ca2Rn6on.js +2 -0
- package/dist/chunks/auth-Ca2Rn6on.js.map +1 -0
- package/dist/chunks/auth-ClNTDOqm.js +18 -0
- package/dist/chunks/auth-ClNTDOqm.js.map +1 -0
- package/dist/chunks/auth-DECnMZjF.js +18 -0
- package/dist/chunks/auth-DECnMZjF.js.map +1 -0
- package/dist/chunks/auth-DPvxdqy4.js +18 -0
- package/dist/chunks/auth-DPvxdqy4.js.map +1 -0
- package/dist/chunks/auth-HzvnTaOm.js +2 -0
- package/dist/chunks/auth-HzvnTaOm.js.map +1 -0
- package/dist/chunks/auth-M6aNTKCH.js +2 -0
- package/dist/chunks/auth-M6aNTKCH.js.map +1 -0
- package/dist/chunks/auth-UHnAu6_e.js +2 -0
- package/dist/chunks/auth-UHnAu6_e.js.map +1 -0
- package/dist/chunks/auth-YrujJY7m.js +18 -0
- package/dist/chunks/auth-YrujJY7m.js.map +1 -0
- package/dist/chunks/{groupsApi-3CR-_g5b.js → groupsApi-Db8G2lLs.js} +2 -2
- package/dist/chunks/{groupsApi-3CR-_g5b.js.map → groupsApi-Db8G2lLs.js.map} +1 -1
- package/dist/chunks/{groupsApi-BUyBgf_N.js → groupsApi-lbxNsHFv.js} +2 -2
- package/dist/chunks/{groupsApi-BUyBgf_N.js.map → groupsApi-lbxNsHFv.js.map} +1 -1
- package/dist/chunks/{index-IJR_91Yt.js → index-BI2dc1FS.js} +2 -2
- package/dist/chunks/{index-IJR_91Yt.js.map → index-BI2dc1FS.js.map} +1 -1
- package/dist/chunks/{index-DIQ6Jmmq.js → index-Bn8HzILk.js} +4 -4
- package/dist/chunks/{index-DIQ6Jmmq.js.map → index-Bn8HzILk.js.map} +1 -1
- package/dist/chunks/{index-DA5VyW0k.js → index-CN2WRyg1.js} +2249 -2264
- package/dist/chunks/index-CN2WRyg1.js.map +1 -0
- package/dist/chunks/{index-Br2wsGE8.js → index-CTGSmYvs.js} +2 -2
- package/dist/chunks/{index-Br2wsGE8.js.map → index-CTGSmYvs.js.map} +1 -1
- package/dist/chunks/index-CUICSveU.js +2 -0
- package/dist/chunks/index-CUICSveU.js.map +1 -0
- package/dist/chunks/{index-S-X8qFYW.js → index-CgtbaFf5.js} +2 -2
- package/dist/chunks/{index-S-X8qFYW.js.map → index-CgtbaFf5.js.map} +1 -1
- package/dist/chunks/{index-_g82N2nb.js → index-D0HS542b.js} +2 -2
- package/dist/chunks/{index-_g82N2nb.js.map → index-D0HS542b.js.map} +1 -1
- package/dist/chunks/{index-BIqcvvbh.js → index-DEtq-xUL.js} +9 -8
- package/dist/chunks/index-DEtq-xUL.js.map +1 -0
- package/dist/chunks/{index-BOKR3bw6.js → index-DF93KQFR.js} +2 -2
- package/dist/chunks/{index-BOKR3bw6.js.map → index-DF93KQFR.js.map} +1 -1
- package/dist/chunks/{index-CxgEV-rT.js → index-DLekpNSE.js} +2 -2
- package/dist/chunks/{index-CxgEV-rT.js.map → index-DLekpNSE.js.map} +1 -1
- package/dist/chunks/{index-DEOBhXS_.js → index-DUS-tunb.js} +2 -2
- package/dist/chunks/{index-DEOBhXS_.js.map → index-DUS-tunb.js.map} +1 -1
- package/dist/chunks/{index-BMsjMCv9.js → index-DjC1u2hI.js} +3 -3
- package/dist/chunks/{index-BMsjMCv9.js.map → index-DjC1u2hI.js.map} +1 -1
- package/dist/chunks/{index-BxHVPJ-j.js → index-DqbVFB1H.js} +2 -2
- package/dist/chunks/{index-BxHVPJ-j.js.map → index-DqbVFB1H.js.map} +1 -1
- package/dist/chunks/{index-Djy4eIbB.js → index-DwqLhQ8S.js} +2 -2
- package/dist/chunks/{index-Djy4eIbB.js.map → index-DwqLhQ8S.js.map} +1 -1
- package/dist/chunks/{index-C1w97Ejz.js → index-HsAOBno4.js} +2 -2
- package/dist/chunks/{index-C1w97Ejz.js.map → index-HsAOBno4.js.map} +1 -1
- package/dist/chunks/{index-Czk12A3G.js → index-TiWOcC0g.js} +2 -2
- package/dist/chunks/{index-Czk12A3G.js.map → index-TiWOcC0g.js.map} +1 -1
- package/dist/chunks/{index-vXiLh35n.js → index-cAikSVW0.js} +13 -13
- package/dist/chunks/index-cAikSVW0.js.map +1 -0
- package/dist/chunks/{index-CNxx56kE.js → index-xhRXN1Jq.js} +2 -2
- package/dist/chunks/{index-CNxx56kE.js.map → index-xhRXN1Jq.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-COKA97Ug.js → tenantIconMap-CHeS7oLt.js} +2 -2
- package/dist/chunks/{tenantIconMap-COKA97Ug.js.map → tenantIconMap-CHeS7oLt.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-BuSQUUyZ.js → tenantIconMap-__FKj6CN.js} +2 -2
- package/dist/chunks/{tenantIconMap-BuSQUUyZ.js.map → tenantIconMap-__FKj6CN.js.map} +1 -1
- package/dist/chunks/{ticketingApi-DbREwHez.js → ticketingApi-Cj239hYB.js} +2 -2
- package/dist/chunks/{ticketingApi-DbREwHez.js.map → ticketingApi-Cj239hYB.js.map} +1 -1
- package/dist/chunks/{ticketingApi-C6EbupqP.js → ticketingApi-DF4RwD_6.js} +2 -2
- package/dist/chunks/{ticketingApi-C6EbupqP.js.map → ticketingApi-DF4RwD_6.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-vucIb3_w.js → useAccessRequests-CFam8zFR.js} +3 -3
- package/dist/chunks/{useAccessRequests-vucIb3_w.js.map → useAccessRequests-CFam8zFR.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-C0dY6y-4.js → useAccessRequests-CViOUwyF.js} +2 -2
- package/dist/chunks/{useAccessRequests-C0dY6y-4.js.map → useAccessRequests-CViOUwyF.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BBcw1Rk9.js → useUserAccessRequests-B-Cs6NX1.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BBcw1Rk9.js.map → useUserAccessRequests-B-Cs6NX1.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-Cj0nkesW.js → useUserAccessRequests-CslSQeBJ.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-Cj0nkesW.js.map → useUserAccessRequests-CslSQeBJ.js.map} +1 -1
- package/dist/contexts/AuthContext.d.ts.map +1 -1
- package/dist/pages/LoginPage.d.ts.map +1 -1
- package/dist/pages/platform/administration/tenants/TenantDetailPage.d.ts.map +1 -1
- package/dist/pages/platform/support/UserCreateTicketPage.d.ts.map +1 -1
- package/dist/services/api/apiClient.d.ts.map +1 -1
- package/dist/services/support/ticketDraftService.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +6 -6
- package/dist/utils/permissions.generated.d.ts +288 -0
- package/dist/utils/permissions.generated.d.ts.map +1 -0
- package/dist/utils/uuid.d.ts +6 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/chunks/UserCreateTicketPage-ChQL1mVY.js.map +0 -1
- package/dist/chunks/UserCreateTicketPage-DkjsHeV7.js.map +0 -1
- package/dist/chunks/auth-B-hELPDB.js +0 -2
- package/dist/chunks/auth-B-hELPDB.js.map +0 -1
- package/dist/chunks/auth-BYaMuq7D.js +0 -16
- package/dist/chunks/auth-BYaMuq7D.js.map +0 -1
- package/dist/chunks/auth-C5zpZ9k7.js +0 -2
- package/dist/chunks/auth-C5zpZ9k7.js.map +0 -1
- package/dist/chunks/auth-CDpRMVv1.js +0 -16
- package/dist/chunks/auth-CDpRMVv1.js.map +0 -1
- package/dist/chunks/auth-CyPkCta2.js +0 -2
- package/dist/chunks/auth-CyPkCta2.js.map +0 -1
- package/dist/chunks/auth-DL47kvnl.js +0 -2
- package/dist/chunks/auth-DL47kvnl.js.map +0 -1
- package/dist/chunks/auth-Diiv90i1.js +0 -16
- package/dist/chunks/auth-Diiv90i1.js.map +0 -1
- package/dist/chunks/auth-rog9MvUr.js +0 -16
- package/dist/chunks/auth-rog9MvUr.js.map +0 -1
- package/dist/chunks/index-BIqcvvbh.js.map +0 -1
- package/dist/chunks/index-DA5VyW0k.js.map +0 -1
- package/dist/chunks/index-Dht6EQW1.js +0 -2
- package/dist/chunks/index-Dht6EQW1.js.map +0 -1
- package/dist/chunks/index-vXiLh35n.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage-DOitDfGV.js","sources":["../../src/components/dashboard/DeviceBreakdownChart.tsx","../../src/components/dashboard/EngagementMetricsCard.tsx","../../src/pages/platform/administration/DashboardPage.tsx"],"sourcesContent":["import React from 'react';\r\nimport { Monitor, Smartphone, Tablet } from 'lucide-react';\r\nimport type { DeviceAnalyticsDto } from '@/services/api/applicationAnalyticsApi';\r\n\r\ninterface DeviceBreakdownChartProps {\r\n readonly data: DeviceAnalyticsDto | null;\r\n}\r\n\r\nconst deviceIcons: Record<string, React.ReactNode> = {\r\n Desktop: <Monitor className=\"w-4 h-4\" />,\r\n Mobile: <Smartphone className=\"w-4 h-4\" />,\r\n Tablet: <Tablet className=\"w-4 h-4\" />,\r\n Unknown: <Monitor className=\"w-4 h-4 opacity-50\" />\r\n};\r\n\r\nconst deviceColors = [\r\n '#3b82f6',\r\n '#22c55e',\r\n '#f59e0b',\r\n '#6b7280'\r\n];\r\n\r\nconst browserColors = [\r\n '#3b82f6',\r\n '#8b5cf6',\r\n '#22c55e',\r\n '#f59e0b',\r\n '#ef4444'\r\n];\r\n\r\nexport const DeviceBreakdownChart: React.FC<DeviceBreakdownChartProps> = ({ data }) => {\r\n if (!data || (!data.byDeviceType?.length && !data.byBrowser?.length)) {\r\n return (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n No device data available\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\r\n {/* Device Type Breakdown */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n By Device Type\r\n </h4>\r\n <div className=\"space-y-3\">\r\n {data.byDeviceType.map((device, index) => (\r\n <div key={device.deviceType} className=\"flex items-center gap-3\">\r\n <div className=\"flex items-center gap-2 w-28\">\r\n {deviceIcons[device.deviceType] || deviceIcons.Unknown}\r\n <span className=\"text-sm\">{device.deviceType}</span>\r\n </div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${device.percentage}%`,\r\n backgroundColor: deviceColors[index % deviceColors.length]\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-20 text-right\">\r\n <span className=\"font-medium\">{device.count}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)] ml-1\">\r\n ({device.percentage.toFixed(1)}%)\r\n </span>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Browser Breakdown */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n By Browser\r\n </h4>\r\n <div className=\"space-y-3\">\r\n {data.byBrowser.map((browser, index) => {\r\n const maxCount = Math.max(...data.byBrowser.map(b => b.count), 1);\r\n const percentage = (browser.count / maxCount) * 100;\r\n\r\n return (\r\n <div key={browser.browser} className=\"flex items-center gap-3\">\r\n <div className=\"w-24 text-sm\">{browser.browser}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: browserColors[index % browserColors.length]\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-12 text-right font-medium\">{browser.count}</div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import React from 'react';\r\nimport type { EngagementMetricsDto } from '@/services/api/applicationAnalyticsApi';\r\n\r\ninterface EngagementMetricsCardProps {\r\n readonly data: EngagementMetricsDto | null;\r\n}\r\n\r\nconst sessionColors = ['#ef4444', '#f59e0b', '#22c55e', '#3b82f6'];\r\n\r\nexport const EngagementMetricsCard: React.FC<EngagementMetricsCardProps> = ({ data }) => {\r\n if (!data) {\r\n return (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n No engagement data available\r\n </div>\r\n );\r\n }\r\n\r\n const maxBucketCount = Math.max(...data.sessionDistribution.map(b => b.count), 1);\r\n const maxHourCount = Math.max(...data.peakUsageHours.map(h => h.accessCount), 1);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Session Duration Distribution */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n Session Duration Distribution\r\n </h4>\r\n <div className=\"space-y-3\">\r\n {data.sessionDistribution.map((bucket, index) => {\r\n const percentage = (bucket.count / maxBucketCount) * 100;\r\n\r\n return (\r\n <div key={bucket.bucket} className=\"flex items-center gap-3\">\r\n <div className=\"w-20 text-sm\">{bucket.label}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: sessionColors[index % sessionColors.length]\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-16 text-right\">\r\n <span className=\"font-medium\">{bucket.count}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)] ml-1\">\r\n sessions\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Peak Usage Hours */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n Peak Usage Hours\r\n </h4>\r\n <div className=\"flex items-end gap-1 h-32 overflow-x-auto pb-2\">\r\n {data.peakUsageHours.map((hourData) => {\r\n const heightPercentage = (hourData.accessCount / maxHourCount) * 100;\r\n\r\n return (\r\n <div\r\n key={hourData.hour}\r\n className=\"flex-1 min-w-[20px] flex flex-col items-center gap-1\"\r\n >\r\n <div\r\n className=\"w-full bg-gradient-to-t from-blue-500 to-cyan-500 rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{\r\n height: `${heightPercentage}%`,\r\n minHeight: hourData.accessCount > 0 ? '4px' : '0'\r\n }}\r\n title={`${hourData.hour}h: ${hourData.accessCount} accesses`}\r\n />\r\n {hourData.hour % 3 === 0 && (\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {hourData.hour}h\r\n </span>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Engagement Summary */}\r\n <div className=\"grid grid-cols-2 gap-4 pt-4 border-t border-[var(--border-color)]\">\r\n <div className=\"text-center p-3 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-2xl font-bold text-blue-600\">\r\n {data.dailyActiveUsers}\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n Daily Active Users\r\n </div>\r\n </div>\r\n <div className=\"text-center p-3 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-2xl font-bold text-green-600\">\r\n {(data.retentionRate * 100).toFixed(1)}%\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n Retention Rate\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import { useState, useEffect, useCallback, useRef } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n Users,\r\n UserCheck,\r\n UserX,\r\n UserPlus,\r\n Activity,\r\n AlertTriangle,\r\n Key,\r\n Shield,\r\n TrendingUp,\r\n RefreshCw,\r\n Loader2,\r\n Clock,\r\n Globe,\r\n Monitor,\r\n} from 'lucide-react';\r\nimport {\r\n adminApi,\r\n type UserDashboardOverviewDto,\r\n type UserStatusCountDto,\r\n type UserRoleDistributionDto,\r\n type UserTrendDto,\r\n type SecurityAlertDto,\r\n type ActiveSessionsStatsDto,\r\n type LatestActiveSessionDto,\r\n} from '@/services/api/adminApi';\r\nimport { applicationAnalyticsApi } from '@/services/api/applicationAnalyticsApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport type { DeviceAnalyticsDto, EngagementMetricsDto } from '@/services/api/applicationAnalyticsApi';\r\nimport { DeviceBreakdownChart } from '@/components/dashboard/DeviceBreakdownChart';\r\nimport { EngagementMetricsCard } from '@/components/dashboard/EngagementMetricsCard';\r\n\r\nconst statusColors: Record<string, string> = {\r\n Active: '#22c55e',\r\n Inactive: '#ef4444',\r\n};\r\n\r\nexport function AdminDashboardPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'navigation']);\r\n const navigate = useNavigate();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const [loading, setLoading] = useState(true);\r\n const [refreshing, setRefreshing] = useState(false);\r\n const [period, setPeriod] = useState(30);\r\n\r\n const [overview, setOverview] = useState<UserDashboardOverviewDto | null>(null);\r\n const [statusData, setStatusData] = useState<UserStatusCountDto[]>([]);\r\n const [roleData, setRoleData] = useState<UserRoleDistributionDto[]>([]);\r\n const [trends, setTrends] = useState<UserTrendDto[]>([]);\r\n const [latestSessions, setLatestSessions] = useState<LatestActiveSessionDto[]>([]);\r\n const [securityAlerts, setSecurityAlerts] = useState<SecurityAlertDto[]>([]);\r\n const [sessionStats, setSessionStats] = useState<ActiveSessionsStatsDto | null>(null);\r\n const [deviceStats, setDeviceStats] = useState<DeviceAnalyticsDto | null>(null);\r\n const [engagementMetrics, setEngagementMetrics] = useState<EngagementMetricsDto | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n // Ref to track if component is still mounted (StrictMode protection)\r\n const abortControllerRef = useRef<AbortController | null>(null);\r\n\r\n const loadData = useCallback(async (signal?: AbortSignal) => {\r\n try {\r\n setError(null);\r\n const [\r\n overviewRes,\r\n statusRes,\r\n roleRes,\r\n trendsRes,\r\n latestSessionsRes,\r\n alertsRes,\r\n sessionsRes,\r\n deviceRes,\r\n engagementRes,\r\n ] = await Promise.all([\r\n adminApi.dashboard.getOverview(period, { signal }),\r\n adminApi.dashboard.getByStatus({ signal }),\r\n adminApi.dashboard.getByRole({ signal }),\r\n adminApi.dashboard.getTrends(period, { signal }),\r\n adminApi.dashboard.getLatestActiveSessions(5, { signal }),\r\n adminApi.dashboard.getSecurityAlerts(3, 24, { signal }),\r\n adminApi.dashboard.getActiveSessions({ signal }),\r\n applicationAnalyticsApi.getDeviceStats(period, { signal }),\r\n applicationAnalyticsApi.getEngagementMetrics(period, { signal }),\r\n ]);\r\n\r\n // Only update state if request wasn't aborted\r\n if (!signal?.aborted) {\r\n setOverview(overviewRes ?? null);\r\n setStatusData(statusRes ?? []);\r\n setRoleData(roleRes ?? []);\r\n setTrends(trendsRes ?? []);\r\n setLatestSessions(latestSessionsRes ?? []);\r\n setSecurityAlerts(alertsRes ?? []);\r\n setSessionStats(sessionsRes ?? null);\r\n setDeviceStats(deviceRes ?? null);\r\n setEngagementMetrics(engagementRes ?? null);\r\n }\r\n } catch (err: unknown) {\r\n // Ignore abort errors (expected in StrictMode)\r\n if (err instanceof Error && err.name === 'CanceledError') {\r\n return;\r\n }\r\n console.error('Failed to load dashboard data:', err);\r\n const axiosError = err as { response?: { status?: number; data?: { message?: string } } };\r\n if (axiosError.response?.status === 401) {\r\n setError('Session expirée. Veuillez vous reconnecter.');\r\n } else if (axiosError.response?.status === 403) {\r\n setError('Vous n\\'avez pas les permissions nécessaires pour accéder au dashboard.');\r\n } else {\r\n setError('Erreur lors du chargement des données. Vérifiez que l\\'API est accessible.');\r\n }\r\n } finally {\r\n if (!signal?.aborted) {\r\n setLoading(false);\r\n setRefreshing(false);\r\n }\r\n }\r\n }, [period, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n // Abort any previous request before starting a new one\r\n abortControllerRef.current?.abort();\r\n const controller = new AbortController();\r\n abortControllerRef.current = controller;\r\n\r\n loadData(controller.signal);\r\n\r\n // Cleanup: abort request when component unmounts or period changes\r\n return () => {\r\n controller.abort();\r\n };\r\n }, [loadData]);\r\n\r\n const handleRefresh = () => {\r\n // Abort any previous request before starting a new one\r\n abortControllerRef.current?.abort();\r\n const controller = new AbortController();\r\n abortControllerRef.current = controller;\r\n\r\n setRefreshing(true);\r\n loadData(controller.signal);\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-primary-600)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title') },\r\n { label: t('dashboard.title') }\r\n ]}\r\n />\r\n\r\n {/* Error Banner */}\r\n {error && (\r\n <div className=\"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-center gap-3\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-red-800 dark:text-red-200 font-medium\">{error}</p>\r\n </div>\r\n <button\r\n onClick={handleRefresh}\r\n className=\"text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200\"\r\n >\r\n <RefreshCw className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)] flex items-center gap-2\">\r\n <Users className=\"w-6 h-6\" />\r\n {t('admin:header.title')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)] mt-1\">\r\n Vue d'ensemble de la gestion des utilisateurs\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <select\r\n value={period}\r\n onChange={(e) => setPeriod(Number(e.target.value))}\r\n className=\"input\"\r\n >\r\n <option value={7}>7 derniers jours</option>\r\n <option value={30}>30 derniers jours</option>\r\n <option value={90}>90 derniers jours</option>\r\n </select>\r\n <button\r\n onClick={handleRefresh}\r\n disabled={refreshing}\r\n className=\"btn btn-secondary flex items-center gap-2\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${refreshing ? 'animate-spin' : ''}`} />\r\n Actualiser\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* KPI Cards */}\r\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4\">\r\n <KpiCard\r\n title=\"Total Utilisateurs\"\r\n value={overview?.totalUsers ?? 0}\r\n icon={<Users className=\"w-5 h-5\" />}\r\n color=\"blue\"\r\n />\r\n <KpiCard\r\n title=\"Actifs\"\r\n value={overview?.activeUsers ?? 0}\r\n icon={<UserCheck className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n />\r\n <KpiCard\r\n title=\"Inactifs\"\r\n value={overview?.inactiveUsers ?? 0}\r\n icon={<UserX className=\"w-5 h-5\" />}\r\n color=\"red\"\r\n />\r\n <KpiCard\r\n title=\"Nouveaux\"\r\n value={overview?.newUsers ?? 0}\r\n icon={<UserPlus className=\"w-5 h-5\" />}\r\n color=\"blue\"\r\n subtitle={`${period} derniers jours`}\r\n />\r\n <KpiCard\r\n title=\"Sessions\"\r\n value={overview?.totalSessions ?? 0}\r\n icon={<Activity className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n subtitle={`${period} derniers jours`}\r\n />\r\n <KpiCard\r\n title=\"Connexions Echouées\"\r\n value={overview?.failedLogins ?? 0}\r\n icon={<AlertTriangle className=\"w-5 h-5\" />}\r\n color={(overview?.failedLogins ?? 0) > 10 ? 'red' : 'yellow'}\r\n subtitle={`${period} derniers jours`}\r\n />\r\n </div>\r\n\r\n {/* Security Alerts */}\r\n {(securityAlerts?.length ?? 0) > 0 && (\r\n <div className=\"card p-4 border-l-4 border-red-500\">\r\n <h3 className=\"font-semibold text-red-600 flex items-center gap-2 mb-3\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n Alertes Sécurité ({securityAlerts?.length ?? 0})\r\n </h3>\r\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\r\n {(securityAlerts ?? []).slice(0, 5).map((alert) => (\r\n <button\r\n type=\"button\"\r\n key={alert.userId}\r\n className=\"w-full flex items-center justify-between p-2 bg-red-50 dark:bg-red-900/20 rounded cursor-pointer hover:bg-red-100 dark:hover:bg-red-900/30 text-left\"\r\n onClick={() => navigate(`/administration/users/${alert.userId}`)}\r\n >\r\n <div>\r\n <span className=\"font-medium\">{alert.fullName}</span>\r\n <span className=\"ml-2 text-sm text-[var(--text-secondary)]\">{alert.email}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-xs text-red-600 font-medium\">\r\n {alert.failedAttempts} échecs\r\n </span>\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {alert.ipAddresses?.length ?? 0} IP(s)\r\n </span>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Charts Row */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* Status Distribution */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <UserCheck className=\"w-5 h-5\" />\r\n Utilisateurs par Statut\r\n </h3>\r\n <div className=\"space-y-3\">\r\n {(statusData ?? []).map((item) => {\r\n const total = (statusData ?? []).reduce((sum, s) => sum + s.count, 0);\r\n const percentage = total > 0 ? (item.count / total) * 100 : 0;\r\n return (\r\n <div key={item.status} className=\"flex items-center gap-3\">\r\n <div className=\"w-24 text-sm\">{item.status === 'Active' ? 'Actifs' : 'Inactifs'}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: statusColors[item.status] || '#6b7280',\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-20 text-right\">\r\n <span className=\"font-medium\">{item.count}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)] ml-1\">\r\n ({percentage.toFixed(0)}%)\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Role Distribution */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Key className=\"w-5 h-5\" />\r\n Utilisateurs par Rôle\r\n </h3>\r\n <div className=\"space-y-3\">\r\n {(roleData?.length ?? 0) > 0 ? (\r\n (roleData ?? []).map((item, index) => {\r\n const maxCount = Math.max(...(roleData ?? []).map(r => r.count), 1);\r\n const percentage = (item.count / maxCount) * 100;\r\n const colors = ['#3b82f6', '#8b5cf6', '#22c55e', '#f59e0b', '#ef4444'];\r\n return (\r\n <div key={item.roleName} className=\"flex items-center gap-3\">\r\n <div className=\"w-32 text-sm truncate\" title={item.roleName}>{item.roleName}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: colors[index % colors.length],\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-12 text-right font-medium\">{item.count}</div>\r\n </div>\r\n );\r\n })\r\n ) : (\r\n <div className=\"text-center py-4 text-[var(--text-secondary)]\">\r\n Aucun rôle configuré\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* System Stats */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* System Overview */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Shield className=\"w-5 h-5\" />\r\n Configuration Système\r\n </h3>\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-purple-600\">{overview?.totalRoles ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Rôles</div>\r\n </div>\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-green-600\">{overview?.totalPermissions ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Permissions</div>\r\n </div>\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-blue-600\">{overview?.usersLoggedInRecently ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Connectés récemment</div>\r\n </div>\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-orange-600\">{sessionStats?.totalActiveSessions ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Sessions actives</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Active Sessions Stats */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Monitor className=\"w-5 h-5\" />\r\n Sessions Actives\r\n </h3>\r\n {sessionStats && ((sessionStats.byBrowser?.length ?? 0) > 0 || (sessionStats.byCountry?.length ?? 0) > 0) ? (\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-2\">Par Navigateur</h4>\r\n <div className=\"space-y-2\">\r\n {(sessionStats.byBrowser ?? []).map((item) => (\r\n <div key={item.browser} className=\"flex items-center justify-between text-sm\">\r\n <span>{item.browser}</span>\r\n <span className=\"font-medium\">{item.count}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-2 flex items-center gap-1\">\r\n <Globe className=\"w-4 h-4\" /> Par Pays\r\n </h4>\r\n <div className=\"space-y-2\">\r\n {(sessionStats.byCountry?.length ?? 0) > 0 ? (\r\n (sessionStats.byCountry ?? []).map((item) => (\r\n <div key={item.country} className=\"flex items-center justify-between text-sm\">\r\n <span>{item.country}</span>\r\n <span className=\"font-medium\">{item.count}</span>\r\n </div>\r\n ))\r\n ) : (\r\n <span className=\"text-[var(--text-secondary)] text-sm\">Non disponible</span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n Aucune session active\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Device & Engagement Metrics */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* Device Analytics */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Monitor className=\"w-5 h-5\" />\r\n Appareils & Navigateurs\r\n </h3>\r\n <DeviceBreakdownChart data={deviceStats} />\r\n </div>\r\n\r\n {/* Engagement Metrics */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Activity className=\"w-5 h-5\" />\r\n Engagement Utilisateurs\r\n </h3>\r\n <EngagementMetricsCard data={engagementMetrics} />\r\n </div>\r\n </div>\r\n\r\n {/* Trends Chart */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <TrendingUp className=\"w-5 h-5\" />\r\n Tendances ({period} derniers jours)\r\n </h3>\r\n <div className=\"h-64\">\r\n <TrendChart data={trends ?? []} />\r\n </div>\r\n </div>\r\n\r\n {/* Latest Active Sessions */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Clock className=\"w-5 h-5\" />\r\n Dernières Sessions Actives\r\n </h3>\r\n {(latestSessions?.length ?? 0) > 0 ? (\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"border-b border-[var(--border-color)]\">\r\n <th className=\"text-left p-3 font-medium\">Utilisateur</th>\r\n <th className=\"text-right p-3 font-medium\">Durée</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {(latestSessions ?? []).map((session) => (\r\n <tr\r\n key={session.userId + session.loginAt}\r\n className=\"border-b border-[var(--border-color)] hover:bg-[var(--bg-secondary)] cursor-pointer\"\r\n onClick={() => navigate(`/administration/users/${session.userId}`)}\r\n >\r\n <td className=\"p-3 font-medium\">{session.fullName}</td>\r\n <td className=\"p-3 text-right\">\r\n <span className=\"px-2 py-1 rounded text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400\">\r\n {session.duration}\r\n </span>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n ) : (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n Aucune session active\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nfunction KpiCard({\r\n title,\r\n value,\r\n icon,\r\n color,\r\n subtitle,\r\n}: {\r\n title: string;\r\n value: string | number;\r\n icon: React.ReactNode;\r\n color: 'blue' | 'green' | 'yellow' | 'red';\r\n subtitle?: string;\r\n}) {\r\n const colorClasses = {\r\n blue: 'bg-blue-50 text-blue-600 border-blue-200 dark:bg-blue-900/20 dark:border-blue-800',\r\n green: 'bg-green-50 text-green-600 border-green-200 dark:bg-green-900/20 dark:border-green-800',\r\n yellow: 'bg-yellow-50 text-yellow-600 border-yellow-200 dark:bg-yellow-900/20 dark:border-yellow-800',\r\n red: 'bg-red-50 text-red-600 border-red-200 dark:bg-red-900/20 dark:border-red-800',\r\n };\r\n\r\n return (\r\n <div className={`card p-4 border ${colorClasses[color]}`}>\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <span className=\"text-sm font-medium opacity-80\">{title}</span>\r\n {icon}\r\n </div>\r\n <div className=\"text-2xl font-bold\">{value}</div>\r\n {subtitle && <div className=\"text-xs opacity-70 mt-1\">{subtitle}</div>}\r\n </div>\r\n );\r\n}\r\n\r\nfunction TrendChart({ data }: { data: UserTrendDto[] }) {\r\n if (data.length === 0) {\r\n return (\r\n <div className=\"flex items-center justify-center h-full text-[var(--text-secondary)]\">\r\n Aucune donnée de tendance disponible\r\n </div>\r\n );\r\n }\r\n\r\n const maxValue = Math.max(...data.flatMap((d) => [d.newUsers, d.logins]), 1);\r\n\r\n return (\r\n <div className=\"flex flex-col h-full\">\r\n <div className=\"flex items-center gap-4 mb-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"w-3 h-3 rounded bg-blue-500\" />\r\n <span className=\"text-sm\">Nouveaux utilisateurs</span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"w-3 h-3 rounded bg-green-500\" />\r\n <span className=\"text-sm\">Connexions</span>\r\n </div>\r\n </div>\r\n <div className=\"flex-1 flex items-end gap-1 overflow-x-auto pb-4\">\r\n {data.map((item) => (\r\n <div key={`${item.date}`} className=\"flex-1 min-w-[20px] flex gap-0.5\">\r\n <div\r\n className=\"flex-1 bg-blue-500 rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{\r\n height: `${(item.newUsers / maxValue) * 100}%`,\r\n minHeight: item.newUsers > 0 ? '4px' : '0',\r\n }}\r\n title={`Nouveaux: ${item.newUsers}`}\r\n />\r\n <div\r\n className=\"flex-1 bg-green-500 rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{\r\n height: `${(item.logins / maxValue) * 100}%`,\r\n minHeight: item.logins > 0 ? '4px' : '0',\r\n }}\r\n title={`Connexions: ${item.logins}`}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n <div className=\"flex justify-between text-xs text-[var(--text-secondary)] mt-2\">\r\n <span>{data[0] && new Date(data[0].date).toLocaleDateString('fr-FR')}</span>\r\n <span>{data.at(-1) && new Date(data.at(-1)!.date).toLocaleDateString('fr-FR')}</span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["deviceIcons","jsx","Monitor","Smartphone","Tablet","deviceColors","browserColors","DeviceBreakdownChart","data","jsxs","device","index","browser","maxCount","b","percentage","sessionColors","EngagementMetricsCard","maxBucketCount","maxHourCount","h","bucket","hourData","heightPercentage","statusColors","AdminDashboardPage","t","useTranslation","navigate","useNavigate","currentTenant","isGlobalView","useTenant","loading","setLoading","useState","refreshing","setRefreshing","period","setPeriod","overview","setOverview","statusData","setStatusData","roleData","setRoleData","trends","setTrends","latestSessions","setLatestSessions","securityAlerts","setSecurityAlerts","sessionStats","setSessionStats","deviceStats","setDeviceStats","engagementMetrics","setEngagementMetrics","error","setError","abortControllerRef","useRef","loadData","useCallback","signal","overviewRes","statusRes","roleRes","trendsRes","latestSessionsRes","alertsRes","sessionsRes","deviceRes","engagementRes","adminApi","applicationAnalyticsApi","err","axiosError","useEffect","controller","handleRefresh","Loader2","Breadcrumb","AlertTriangle","RefreshCw","Users","e","KpiCard","UserCheck","UserX","UserPlus","Activity","alert","item","total","sum","s","Key","r","colors","Shield","Globe","TrendingUp","TrendChart","Clock","session","title","value","icon","color","subtitle","maxValue","d"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardPage-D5MRMxEV.js","sources":["../../src/components/dashboard/DeviceBreakdownChart.tsx","../../src/components/dashboard/EngagementMetricsCard.tsx","../../src/pages/platform/administration/DashboardPage.tsx"],"sourcesContent":["import React from 'react';\r\nimport { Monitor, Smartphone, Tablet } from 'lucide-react';\r\nimport type { DeviceAnalyticsDto } from '@/services/api/applicationAnalyticsApi';\r\n\r\ninterface DeviceBreakdownChartProps {\r\n readonly data: DeviceAnalyticsDto | null;\r\n}\r\n\r\nconst deviceIcons: Record<string, React.ReactNode> = {\r\n Desktop: <Monitor className=\"w-4 h-4\" />,\r\n Mobile: <Smartphone className=\"w-4 h-4\" />,\r\n Tablet: <Tablet className=\"w-4 h-4\" />,\r\n Unknown: <Monitor className=\"w-4 h-4 opacity-50\" />\r\n};\r\n\r\nconst deviceColors = [\r\n '#3b82f6',\r\n '#22c55e',\r\n '#f59e0b',\r\n '#6b7280'\r\n];\r\n\r\nconst browserColors = [\r\n '#3b82f6',\r\n '#8b5cf6',\r\n '#22c55e',\r\n '#f59e0b',\r\n '#ef4444'\r\n];\r\n\r\nexport const DeviceBreakdownChart: React.FC<DeviceBreakdownChartProps> = ({ data }) => {\r\n if (!data || (!data.byDeviceType?.length && !data.byBrowser?.length)) {\r\n return (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n No device data available\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\r\n {/* Device Type Breakdown */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n By Device Type\r\n </h4>\r\n <div className=\"space-y-3\">\r\n {data.byDeviceType.map((device, index) => (\r\n <div key={device.deviceType} className=\"flex items-center gap-3\">\r\n <div className=\"flex items-center gap-2 w-28\">\r\n {deviceIcons[device.deviceType] || deviceIcons.Unknown}\r\n <span className=\"text-sm\">{device.deviceType}</span>\r\n </div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${device.percentage}%`,\r\n backgroundColor: deviceColors[index % deviceColors.length]\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-20 text-right\">\r\n <span className=\"font-medium\">{device.count}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)] ml-1\">\r\n ({device.percentage.toFixed(1)}%)\r\n </span>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Browser Breakdown */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n By Browser\r\n </h4>\r\n <div className=\"space-y-3\">\r\n {data.byBrowser.map((browser, index) => {\r\n const maxCount = Math.max(...data.byBrowser.map(b => b.count), 1);\r\n const percentage = (browser.count / maxCount) * 100;\r\n\r\n return (\r\n <div key={browser.browser} className=\"flex items-center gap-3\">\r\n <div className=\"w-24 text-sm\">{browser.browser}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: browserColors[index % browserColors.length]\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-12 text-right font-medium\">{browser.count}</div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import React from 'react';\r\nimport type { EngagementMetricsDto } from '@/services/api/applicationAnalyticsApi';\r\n\r\ninterface EngagementMetricsCardProps {\r\n readonly data: EngagementMetricsDto | null;\r\n}\r\n\r\nconst sessionColors = ['#ef4444', '#f59e0b', '#22c55e', '#3b82f6'];\r\n\r\nexport const EngagementMetricsCard: React.FC<EngagementMetricsCardProps> = ({ data }) => {\r\n if (!data) {\r\n return (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n No engagement data available\r\n </div>\r\n );\r\n }\r\n\r\n const maxBucketCount = Math.max(...data.sessionDistribution.map(b => b.count), 1);\r\n const maxHourCount = Math.max(...data.peakUsageHours.map(h => h.accessCount), 1);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Session Duration Distribution */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n Session Duration Distribution\r\n </h4>\r\n <div className=\"space-y-3\">\r\n {data.sessionDistribution.map((bucket, index) => {\r\n const percentage = (bucket.count / maxBucketCount) * 100;\r\n\r\n return (\r\n <div key={bucket.bucket} className=\"flex items-center gap-3\">\r\n <div className=\"w-20 text-sm\">{bucket.label}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: sessionColors[index % sessionColors.length]\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-16 text-right\">\r\n <span className=\"font-medium\">{bucket.count}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)] ml-1\">\r\n sessions\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Peak Usage Hours */}\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n Peak Usage Hours\r\n </h4>\r\n <div className=\"flex items-end gap-1 h-32 overflow-x-auto pb-2\">\r\n {data.peakUsageHours.map((hourData) => {\r\n const heightPercentage = (hourData.accessCount / maxHourCount) * 100;\r\n\r\n return (\r\n <div\r\n key={hourData.hour}\r\n className=\"flex-1 min-w-[20px] flex flex-col items-center gap-1\"\r\n >\r\n <div\r\n className=\"w-full bg-gradient-to-t from-blue-500 to-cyan-500 rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{\r\n height: `${heightPercentage}%`,\r\n minHeight: hourData.accessCount > 0 ? '4px' : '0'\r\n }}\r\n title={`${hourData.hour}h: ${hourData.accessCount} accesses`}\r\n />\r\n {hourData.hour % 3 === 0 && (\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {hourData.hour}h\r\n </span>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Engagement Summary */}\r\n <div className=\"grid grid-cols-2 gap-4 pt-4 border-t border-[var(--border-color)]\">\r\n <div className=\"text-center p-3 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-2xl font-bold text-blue-600\">\r\n {data.dailyActiveUsers}\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n Daily Active Users\r\n </div>\r\n </div>\r\n <div className=\"text-center p-3 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-2xl font-bold text-green-600\">\r\n {(data.retentionRate * 100).toFixed(1)}%\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n Retention Rate\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import { useState, useEffect, useCallback, useRef } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n Users,\r\n UserCheck,\r\n UserX,\r\n UserPlus,\r\n Activity,\r\n AlertTriangle,\r\n Key,\r\n Shield,\r\n TrendingUp,\r\n RefreshCw,\r\n Loader2,\r\n Clock,\r\n Globe,\r\n Monitor,\r\n} from 'lucide-react';\r\nimport {\r\n adminApi,\r\n type UserDashboardOverviewDto,\r\n type UserStatusCountDto,\r\n type UserRoleDistributionDto,\r\n type UserTrendDto,\r\n type SecurityAlertDto,\r\n type ActiveSessionsStatsDto,\r\n type LatestActiveSessionDto,\r\n} from '@/services/api/adminApi';\r\nimport { applicationAnalyticsApi } from '@/services/api/applicationAnalyticsApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport type { DeviceAnalyticsDto, EngagementMetricsDto } from '@/services/api/applicationAnalyticsApi';\r\nimport { DeviceBreakdownChart } from '@/components/dashboard/DeviceBreakdownChart';\r\nimport { EngagementMetricsCard } from '@/components/dashboard/EngagementMetricsCard';\r\n\r\nconst statusColors: Record<string, string> = {\r\n Active: '#22c55e',\r\n Inactive: '#ef4444',\r\n};\r\n\r\nexport function AdminDashboardPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'navigation']);\r\n const navigate = useNavigate();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const [loading, setLoading] = useState(true);\r\n const [refreshing, setRefreshing] = useState(false);\r\n const [period, setPeriod] = useState(30);\r\n\r\n const [overview, setOverview] = useState<UserDashboardOverviewDto | null>(null);\r\n const [statusData, setStatusData] = useState<UserStatusCountDto[]>([]);\r\n const [roleData, setRoleData] = useState<UserRoleDistributionDto[]>([]);\r\n const [trends, setTrends] = useState<UserTrendDto[]>([]);\r\n const [latestSessions, setLatestSessions] = useState<LatestActiveSessionDto[]>([]);\r\n const [securityAlerts, setSecurityAlerts] = useState<SecurityAlertDto[]>([]);\r\n const [sessionStats, setSessionStats] = useState<ActiveSessionsStatsDto | null>(null);\r\n const [deviceStats, setDeviceStats] = useState<DeviceAnalyticsDto | null>(null);\r\n const [engagementMetrics, setEngagementMetrics] = useState<EngagementMetricsDto | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n // Ref to track if component is still mounted (StrictMode protection)\r\n const abortControllerRef = useRef<AbortController | null>(null);\r\n\r\n const loadData = useCallback(async (signal?: AbortSignal) => {\r\n try {\r\n setError(null);\r\n const [\r\n overviewRes,\r\n statusRes,\r\n roleRes,\r\n trendsRes,\r\n latestSessionsRes,\r\n alertsRes,\r\n sessionsRes,\r\n deviceRes,\r\n engagementRes,\r\n ] = await Promise.all([\r\n adminApi.dashboard.getOverview(period, { signal }),\r\n adminApi.dashboard.getByStatus({ signal }),\r\n adminApi.dashboard.getByRole({ signal }),\r\n adminApi.dashboard.getTrends(period, { signal }),\r\n adminApi.dashboard.getLatestActiveSessions(5, { signal }),\r\n adminApi.dashboard.getSecurityAlerts(3, 24, { signal }),\r\n adminApi.dashboard.getActiveSessions({ signal }),\r\n applicationAnalyticsApi.getDeviceStats(period, { signal }),\r\n applicationAnalyticsApi.getEngagementMetrics(period, { signal }),\r\n ]);\r\n\r\n // Only update state if request wasn't aborted\r\n if (!signal?.aborted) {\r\n setOverview(overviewRes ?? null);\r\n setStatusData(statusRes ?? []);\r\n setRoleData(roleRes ?? []);\r\n setTrends(trendsRes ?? []);\r\n setLatestSessions(latestSessionsRes ?? []);\r\n setSecurityAlerts(alertsRes ?? []);\r\n setSessionStats(sessionsRes ?? null);\r\n setDeviceStats(deviceRes ?? null);\r\n setEngagementMetrics(engagementRes ?? null);\r\n }\r\n } catch (err: unknown) {\r\n // Ignore abort errors (expected in StrictMode)\r\n if (err instanceof Error && err.name === 'CanceledError') {\r\n return;\r\n }\r\n console.error('Failed to load dashboard data:', err);\r\n const axiosError = err as { response?: { status?: number; data?: { message?: string } } };\r\n if (axiosError.response?.status === 401) {\r\n setError('Session expirée. Veuillez vous reconnecter.');\r\n } else if (axiosError.response?.status === 403) {\r\n setError('Vous n\\'avez pas les permissions nécessaires pour accéder au dashboard.');\r\n } else {\r\n setError('Erreur lors du chargement des données. Vérifiez que l\\'API est accessible.');\r\n }\r\n } finally {\r\n if (!signal?.aborted) {\r\n setLoading(false);\r\n setRefreshing(false);\r\n }\r\n }\r\n }, [period, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n // Abort any previous request before starting a new one\r\n abortControllerRef.current?.abort();\r\n const controller = new AbortController();\r\n abortControllerRef.current = controller;\r\n\r\n loadData(controller.signal);\r\n\r\n // Cleanup: abort request when component unmounts or period changes\r\n return () => {\r\n controller.abort();\r\n };\r\n }, [loadData]);\r\n\r\n const handleRefresh = () => {\r\n // Abort any previous request before starting a new one\r\n abortControllerRef.current?.abort();\r\n const controller = new AbortController();\r\n abortControllerRef.current = controller;\r\n\r\n setRefreshing(true);\r\n loadData(controller.signal);\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-primary-600)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title') },\r\n { label: t('dashboard.title') }\r\n ]}\r\n />\r\n\r\n {/* Error Banner */}\r\n {error && (\r\n <div className=\"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 flex items-center gap-3\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-red-800 dark:text-red-200 font-medium\">{error}</p>\r\n </div>\r\n <button\r\n onClick={handleRefresh}\r\n className=\"text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200\"\r\n >\r\n <RefreshCw className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)] flex items-center gap-2\">\r\n <Users className=\"w-6 h-6\" />\r\n {t('admin:header.title')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)] mt-1\">\r\n Vue d'ensemble de la gestion des utilisateurs\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <select\r\n value={period}\r\n onChange={(e) => setPeriod(Number(e.target.value))}\r\n className=\"input\"\r\n >\r\n <option value={7}>7 derniers jours</option>\r\n <option value={30}>30 derniers jours</option>\r\n <option value={90}>90 derniers jours</option>\r\n </select>\r\n <button\r\n onClick={handleRefresh}\r\n disabled={refreshing}\r\n className=\"btn btn-secondary flex items-center gap-2\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${refreshing ? 'animate-spin' : ''}`} />\r\n Actualiser\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* KPI Cards */}\r\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4\">\r\n <KpiCard\r\n title=\"Total Utilisateurs\"\r\n value={overview?.totalUsers ?? 0}\r\n icon={<Users className=\"w-5 h-5\" />}\r\n color=\"blue\"\r\n />\r\n <KpiCard\r\n title=\"Actifs\"\r\n value={overview?.activeUsers ?? 0}\r\n icon={<UserCheck className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n />\r\n <KpiCard\r\n title=\"Inactifs\"\r\n value={overview?.inactiveUsers ?? 0}\r\n icon={<UserX className=\"w-5 h-5\" />}\r\n color=\"red\"\r\n />\r\n <KpiCard\r\n title=\"Nouveaux\"\r\n value={overview?.newUsers ?? 0}\r\n icon={<UserPlus className=\"w-5 h-5\" />}\r\n color=\"blue\"\r\n subtitle={`${period} derniers jours`}\r\n />\r\n <KpiCard\r\n title=\"Sessions\"\r\n value={overview?.totalSessions ?? 0}\r\n icon={<Activity className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n subtitle={`${period} derniers jours`}\r\n />\r\n <KpiCard\r\n title=\"Connexions Echouées\"\r\n value={overview?.failedLogins ?? 0}\r\n icon={<AlertTriangle className=\"w-5 h-5\" />}\r\n color={(overview?.failedLogins ?? 0) > 10 ? 'red' : 'yellow'}\r\n subtitle={`${period} derniers jours`}\r\n />\r\n </div>\r\n\r\n {/* Security Alerts */}\r\n {(securityAlerts?.length ?? 0) > 0 && (\r\n <div className=\"card p-4 border-l-4 border-red-500\">\r\n <h3 className=\"font-semibold text-red-600 flex items-center gap-2 mb-3\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n Alertes Sécurité ({securityAlerts?.length ?? 0})\r\n </h3>\r\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\r\n {(securityAlerts ?? []).slice(0, 5).map((alert) => (\r\n <button\r\n type=\"button\"\r\n key={alert.userId}\r\n className=\"w-full flex items-center justify-between p-2 bg-red-50 dark:bg-red-900/20 rounded cursor-pointer hover:bg-red-100 dark:hover:bg-red-900/30 text-left\"\r\n onClick={() => navigate(`/administration/users/${alert.userId}`)}\r\n >\r\n <div>\r\n <span className=\"font-medium\">{alert.fullName}</span>\r\n <span className=\"ml-2 text-sm text-[var(--text-secondary)]\">{alert.email}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-xs text-red-600 font-medium\">\r\n {alert.failedAttempts} échecs\r\n </span>\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {alert.ipAddresses?.length ?? 0} IP(s)\r\n </span>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Charts Row */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* Status Distribution */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <UserCheck className=\"w-5 h-5\" />\r\n Utilisateurs par Statut\r\n </h3>\r\n <div className=\"space-y-3\">\r\n {(statusData ?? []).map((item) => {\r\n const total = (statusData ?? []).reduce((sum, s) => sum + s.count, 0);\r\n const percentage = total > 0 ? (item.count / total) * 100 : 0;\r\n return (\r\n <div key={item.status} className=\"flex items-center gap-3\">\r\n <div className=\"w-24 text-sm\">{item.status === 'Active' ? 'Actifs' : 'Inactifs'}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: statusColors[item.status] || '#6b7280',\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-20 text-right\">\r\n <span className=\"font-medium\">{item.count}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)] ml-1\">\r\n ({percentage.toFixed(0)}%)\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Role Distribution */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Key className=\"w-5 h-5\" />\r\n Utilisateurs par Rôle\r\n </h3>\r\n <div className=\"space-y-3\">\r\n {(roleData?.length ?? 0) > 0 ? (\r\n (roleData ?? []).map((item, index) => {\r\n const maxCount = Math.max(...(roleData ?? []).map(r => r.count), 1);\r\n const percentage = (item.count / maxCount) * 100;\r\n const colors = ['#3b82f6', '#8b5cf6', '#22c55e', '#f59e0b', '#ef4444'];\r\n return (\r\n <div key={item.roleName} className=\"flex items-center gap-3\">\r\n <div className=\"w-32 text-sm truncate\" title={item.roleName}>{item.roleName}</div>\r\n <div className=\"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full rounded-full transition-all duration-500\"\r\n style={{\r\n width: `${percentage}%`,\r\n backgroundColor: colors[index % colors.length],\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-12 text-right font-medium\">{item.count}</div>\r\n </div>\r\n );\r\n })\r\n ) : (\r\n <div className=\"text-center py-4 text-[var(--text-secondary)]\">\r\n Aucun rôle configuré\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* System Stats */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* System Overview */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Shield className=\"w-5 h-5\" />\r\n Configuration Système\r\n </h3>\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-purple-600\">{overview?.totalRoles ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Rôles</div>\r\n </div>\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-green-600\">{overview?.totalPermissions ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Permissions</div>\r\n </div>\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-blue-600\">{overview?.usersLoggedInRecently ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Connectés récemment</div>\r\n </div>\r\n <div className=\"text-center p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-3xl font-bold text-orange-600\">{sessionStats?.totalActiveSessions ?? 0}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">Sessions actives</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Active Sessions Stats */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Monitor className=\"w-5 h-5\" />\r\n Sessions Actives\r\n </h3>\r\n {sessionStats && ((sessionStats.byBrowser?.length ?? 0) > 0 || (sessionStats.byCountry?.length ?? 0) > 0) ? (\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-2\">Par Navigateur</h4>\r\n <div className=\"space-y-2\">\r\n {(sessionStats.byBrowser ?? []).map((item) => (\r\n <div key={item.browser} className=\"flex items-center justify-between text-sm\">\r\n <span>{item.browser}</span>\r\n <span className=\"font-medium\">{item.count}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n <div>\r\n <h4 className=\"text-sm font-medium text-[var(--text-secondary)] mb-2 flex items-center gap-1\">\r\n <Globe className=\"w-4 h-4\" /> Par Pays\r\n </h4>\r\n <div className=\"space-y-2\">\r\n {(sessionStats.byCountry?.length ?? 0) > 0 ? (\r\n (sessionStats.byCountry ?? []).map((item) => (\r\n <div key={item.country} className=\"flex items-center justify-between text-sm\">\r\n <span>{item.country}</span>\r\n <span className=\"font-medium\">{item.count}</span>\r\n </div>\r\n ))\r\n ) : (\r\n <span className=\"text-[var(--text-secondary)] text-sm\">Non disponible</span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n Aucune session active\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Device & Engagement Metrics */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* Device Analytics */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Monitor className=\"w-5 h-5\" />\r\n Appareils & Navigateurs\r\n </h3>\r\n <DeviceBreakdownChart data={deviceStats} />\r\n </div>\r\n\r\n {/* Engagement Metrics */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Activity className=\"w-5 h-5\" />\r\n Engagement Utilisateurs\r\n </h3>\r\n <EngagementMetricsCard data={engagementMetrics} />\r\n </div>\r\n </div>\r\n\r\n {/* Trends Chart */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <TrendingUp className=\"w-5 h-5\" />\r\n Tendances ({period} derniers jours)\r\n </h3>\r\n <div className=\"h-64\">\r\n <TrendChart data={trends ?? []} />\r\n </div>\r\n </div>\r\n\r\n {/* Latest Active Sessions */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Clock className=\"w-5 h-5\" />\r\n Dernières Sessions Actives\r\n </h3>\r\n {(latestSessions?.length ?? 0) > 0 ? (\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"border-b border-[var(--border-color)]\">\r\n <th className=\"text-left p-3 font-medium\">Utilisateur</th>\r\n <th className=\"text-right p-3 font-medium\">Durée</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {(latestSessions ?? []).map((session) => (\r\n <tr\r\n key={session.userId + session.loginAt}\r\n className=\"border-b border-[var(--border-color)] hover:bg-[var(--bg-secondary)] cursor-pointer\"\r\n onClick={() => navigate(`/administration/users/${session.userId}`)}\r\n >\r\n <td className=\"p-3 font-medium\">{session.fullName}</td>\r\n <td className=\"p-3 text-right\">\r\n <span className=\"px-2 py-1 rounded text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400\">\r\n {session.duration}\r\n </span>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n ) : (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n Aucune session active\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nfunction KpiCard({\r\n title,\r\n value,\r\n icon,\r\n color,\r\n subtitle,\r\n}: {\r\n title: string;\r\n value: string | number;\r\n icon: React.ReactNode;\r\n color: 'blue' | 'green' | 'yellow' | 'red';\r\n subtitle?: string;\r\n}) {\r\n const colorClasses = {\r\n blue: 'bg-blue-50 text-blue-600 border-blue-200 dark:bg-blue-900/20 dark:border-blue-800',\r\n green: 'bg-green-50 text-green-600 border-green-200 dark:bg-green-900/20 dark:border-green-800',\r\n yellow: 'bg-yellow-50 text-yellow-600 border-yellow-200 dark:bg-yellow-900/20 dark:border-yellow-800',\r\n red: 'bg-red-50 text-red-600 border-red-200 dark:bg-red-900/20 dark:border-red-800',\r\n };\r\n\r\n return (\r\n <div className={`card p-4 border ${colorClasses[color]}`}>\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <span className=\"text-sm font-medium opacity-80\">{title}</span>\r\n {icon}\r\n </div>\r\n <div className=\"text-2xl font-bold\">{value}</div>\r\n {subtitle && <div className=\"text-xs opacity-70 mt-1\">{subtitle}</div>}\r\n </div>\r\n );\r\n}\r\n\r\nfunction TrendChart({ data }: { data: UserTrendDto[] }) {\r\n if (data.length === 0) {\r\n return (\r\n <div className=\"flex items-center justify-center h-full text-[var(--text-secondary)]\">\r\n Aucune donnée de tendance disponible\r\n </div>\r\n );\r\n }\r\n\r\n const maxValue = Math.max(...data.flatMap((d) => [d.newUsers, d.logins]), 1);\r\n\r\n return (\r\n <div className=\"flex flex-col h-full\">\r\n <div className=\"flex items-center gap-4 mb-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"w-3 h-3 rounded bg-blue-500\" />\r\n <span className=\"text-sm\">Nouveaux utilisateurs</span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"w-3 h-3 rounded bg-green-500\" />\r\n <span className=\"text-sm\">Connexions</span>\r\n </div>\r\n </div>\r\n <div className=\"flex-1 flex items-end gap-1 overflow-x-auto pb-4\">\r\n {data.map((item) => (\r\n <div key={`${item.date}`} className=\"flex-1 min-w-[20px] flex gap-0.5\">\r\n <div\r\n className=\"flex-1 bg-blue-500 rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{\r\n height: `${(item.newUsers / maxValue) * 100}%`,\r\n minHeight: item.newUsers > 0 ? '4px' : '0',\r\n }}\r\n title={`Nouveaux: ${item.newUsers}`}\r\n />\r\n <div\r\n className=\"flex-1 bg-green-500 rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{\r\n height: `${(item.logins / maxValue) * 100}%`,\r\n minHeight: item.logins > 0 ? '4px' : '0',\r\n }}\r\n title={`Connexions: ${item.logins}`}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n <div className=\"flex justify-between text-xs text-[var(--text-secondary)] mt-2\">\r\n <span>{data[0] && new Date(data[0].date).toLocaleDateString('fr-FR')}</span>\r\n <span>{data.at(-1) && new Date(data.at(-1)!.date).toLocaleDateString('fr-FR')}</span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["deviceIcons","jsx","Monitor","Smartphone","Tablet","deviceColors","browserColors","DeviceBreakdownChart","data","jsxs","device","index","browser","maxCount","b","percentage","sessionColors","EngagementMetricsCard","maxBucketCount","maxHourCount","h","bucket","hourData","heightPercentage","statusColors","AdminDashboardPage","t","useTranslation","navigate","useNavigate","currentTenant","isGlobalView","useTenant","loading","setLoading","useState","refreshing","setRefreshing","period","setPeriod","overview","setOverview","statusData","setStatusData","roleData","setRoleData","trends","setTrends","latestSessions","setLatestSessions","securityAlerts","setSecurityAlerts","sessionStats","setSessionStats","deviceStats","setDeviceStats","engagementMetrics","setEngagementMetrics","error","setError","abortControllerRef","useRef","loadData","useCallback","signal","overviewRes","statusRes","roleRes","trendsRes","latestSessionsRes","alertsRes","sessionsRes","deviceRes","engagementRes","adminApi","applicationAnalyticsApi","err","axiosError","useEffect","controller","handleRefresh","Loader2","Breadcrumb","AlertTriangle","RefreshCw","Users","e","KpiCard","UserCheck","UserX","UserPlus","Activity","alert","item","total","sum","s","Key","r","colors","Shield","Globe","TrendingUp","TrendChart","Clock","session","title","value","icon","color","subtitle","maxValue","d"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { jsxs as s, jsx as e, Fragment as F } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState as c, useCallback as O, useEffect as L } from "react";
|
|
3
3
|
import { useTranslation as P } from "react-i18next";
|
|
4
4
|
import { TrendingUp as U, Loader2 as b, Users as W, Bell as w, AlertTriangle as R, Clock as A, X as q, Check as V, Edit as X } from "lucide-react";
|
|
5
|
-
import { Z, i as y, B as _ } from "./index-
|
|
5
|
+
import { Z, i as y, B as _ } from "./index-CN2WRyg1.js";
|
|
6
6
|
const d = ["Supervisor", "Manager", "Director"], N = {
|
|
7
7
|
None: "bg-[var(--bg-secondary)] text-[var(--text-secondary)]",
|
|
8
8
|
Supervisor: "bg-[var(--info-bg)] text-[var(--info-text)]",
|
|
@@ -228,4 +228,4 @@ function Y() {
|
|
|
228
228
|
export {
|
|
229
229
|
Y as EscalationConfigPage
|
|
230
230
|
};
|
|
231
|
-
//# sourceMappingURL=EscalationConfigPage-
|
|
231
|
+
//# sourceMappingURL=EscalationConfigPage-CwdnfJbJ.js.map
|
package/dist/chunks/{EscalationConfigPage-DNnZftCH.js.map → EscalationConfigPage-CwdnfJbJ.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EscalationConfigPage-DNnZftCH.js","sources":["../../src/pages/platform/support/EscalationConfigPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n TrendingUp,\r\n Loader2,\r\n AlertTriangle,\r\n Bell,\r\n Clock,\r\n Users,\r\n Edit,\r\n Check,\r\n X,\r\n} from 'lucide-react';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { slaApi, type EscalationRuleDto } from '@/services/api/supportApi';\r\nimport { api } from '@/services/api/apiClient';\r\n\r\ninterface RoleDto {\r\n id: string;\r\n name: string;\r\n description: string | null;\r\n}\r\n\r\nconst LEVEL_ORDER = ['Supervisor', 'Manager', 'Director'] as const;\r\n\r\nconst levelColors: Record<string, string> = {\r\n None: 'bg-[var(--bg-secondary)] text-[var(--text-secondary)]',\r\n Supervisor: 'bg-[var(--info-bg)] text-[var(--info-text)]',\r\n Manager: 'bg-[var(--warning-bg)] text-[var(--warning-text)]',\r\n Director: 'bg-[var(--error-bg)] text-[var(--error-text)]',\r\n};\r\n\r\nconst triggerTypeIcons: Record<string, typeof AlertTriangle> = {\r\n ResponseBreach: Clock,\r\n ResolutionBreach: AlertTriangle,\r\n ManualRequest: Bell,\r\n};\r\n\r\nexport function EscalationConfigPage(): ReactElement {\r\n const { t } = useTranslation('support');\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [rules, setRules] = useState<EscalationRuleDto[]>([]);\r\n const [roles, setRoles] = useState<RoleDto[]>([]);\r\n const [editingRule, setEditingRule] = useState<EscalationRuleDto | null>(null);\r\n const [editForm, setEditForm] = useState<{\r\n delayAfterBreachMinutes: number;\r\n notifyRoleId: string | null;\r\n isActive: boolean;\r\n }>({ delayAfterBreachMinutes: 0, notifyRoleId: null, isActive: true });\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const [rulesRes, rolesRes] = await Promise.all([\r\n slaApi.getEscalationRules(),\r\n api.get<RoleDto[]>('/api/administration/permissions/roles'),\r\n ]);\r\n setRules(rulesRes);\r\n setRoles(rolesRes);\r\n } catch (error) {\r\n console.error('Failed to load escalation data:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleEdit = (rule: EscalationRuleDto) => {\r\n setEditingRule(rule);\r\n setEditForm({\r\n delayAfterBreachMinutes: rule.delayAfterBreachMinutes,\r\n notifyRoleId: rule.notifyRoleId,\r\n isActive: rule.isActive,\r\n });\r\n };\r\n\r\n const handleCancelEdit = () => {\r\n setEditingRule(null);\r\n setEditForm({ delayAfterBreachMinutes: 0, notifyRoleId: null, isActive: true });\r\n };\r\n\r\n const handleSave = async () => {\r\n if (!editingRule) return;\r\n\r\n try {\r\n setSaving(true);\r\n await api.put(`/api/support/sla/escalation-rules/${editingRule.id}`, editForm);\r\n loadData();\r\n setEditingRule(null);\r\n } catch (error) {\r\n console.error('Failed to save escalation rule:', error);\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const formatDelay = (minutes: number) => {\r\n if (minutes === 0) return t('escalation.delay.immediate');\r\n if (minutes < 60) return `${minutes} min`;\r\n const hours = Math.floor(minutes / 60);\r\n const remainingMinutes = minutes % 60;\r\n if (remainingMinutes === 0) return `${hours}h`;\r\n return `${hours}h ${remainingMinutes}min`;\r\n };\r\n\r\n const getRoleName = (roleId: string | null) => {\r\n if (!roleId) return t('escalation.notConfigured');\r\n const role = roles.find((r) => r.id === roleId);\r\n return role?.name || t('escalation.unknownRole');\r\n };\r\n\r\n const groupedRules = rules.reduce((acc, rule) => {\r\n if (!acc[rule.level]) {\r\n acc[rule.level] = [];\r\n }\r\n acc[rule.level].push(rule);\r\n return acc;\r\n }, {} as Record<string, EscalationRuleDto[]>);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('title', 'Support'), href: '/support' },\r\n { label: t('escalation.title') }\r\n ]}\r\n />\r\n\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n <TrendingUp className=\"w-6 h-6\" />\r\n {t('escalation.title')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('escalation.subtitle')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {loading ? (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-primary-600)]\" />\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"card p-6 bg-[var(--bg-secondary)]\">\r\n <h3 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('escalation.hierarchy')}\r\n </h3>\r\n <div className=\"flex items-center gap-4\">\r\n {LEVEL_ORDER.map((level, index) => (\r\n <div key={level} className=\"flex items-center gap-2\">\r\n <div className={`px-4 py-2 rounded-[var(--radius-badge)] font-medium ${levelColors[level]}`}>\r\n {t(`escalation.levels.${level}`)}\r\n </div>\r\n {index < 2 && (\r\n <div className=\"text-[var(--text-secondary)]\">→</div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n <p className=\"mt-4 text-sm text-[var(--text-secondary)]\">\r\n {t('escalation.hierarchyDescription')}\r\n </p>\r\n </div>\r\n\r\n <div className=\"space-y-6\">\r\n {Object.entries(groupedRules)\r\n .filter(([level]) => level !== 'None')\r\n .sort((a, b) => {\r\n return LEVEL_ORDER.indexOf(a[0] as typeof LEVEL_ORDER[number]) - LEVEL_ORDER.indexOf(b[0] as typeof LEVEL_ORDER[number]);\r\n })\r\n .map(([level, levelRules]) => (\r\n <div key={level} className=\"card overflow-hidden\">\r\n <div className={`px-6 py-3 ${levelColors[level]} border-b border-[var(--border-color)]`}>\r\n <h3 className=\"font-semibold\">\r\n {t('escalation.level', {\r\n number: LEVEL_ORDER.indexOf(level as typeof LEVEL_ORDER[number]) + 1,\r\n label: t(`escalation.levels.${level}`),\r\n })}\r\n </h3>\r\n </div>\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {levelRules.map((rule) => {\r\n const TriggerIcon = triggerTypeIcons[rule.triggerType] || AlertTriangle;\r\n const isEditing = editingRule?.id === rule.id;\r\n\r\n return (\r\n <div\r\n key={rule.id}\r\n className={`p-4 ${!rule.isActive ? 'opacity-60' : ''}`}\r\n >\r\n {isEditing ? (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <TriggerIcon className=\"w-5 h-5\" />\r\n <span className=\"font-medium\">\r\n {t(`escalation.triggerTypes.${rule.triggerType}`)}\r\n </span>\r\n </div>\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium mb-1\">\r\n {t('escalation.form.delayAfterBreach')}\r\n </label>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n type=\"number\"\r\n min=\"0\"\r\n value={editForm.delayAfterBreachMinutes}\r\n onChange={(e) =>\r\n setEditForm({\r\n ...editForm,\r\n delayAfterBreachMinutes: parseInt(e.target.value) || 0,\r\n })\r\n }\r\n className=\"input w-24\"\r\n />\r\n <span className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('escalation.form.minutes')}\r\n </span>\r\n </div>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium mb-1\">\r\n {t('escalation.form.notifyRole')}\r\n </label>\r\n <select\r\n value={editForm.notifyRoleId || ''}\r\n onChange={(e) =>\r\n setEditForm({\r\n ...editForm,\r\n notifyRoleId: e.target.value || null,\r\n })\r\n }\r\n className=\"input w-full\"\r\n >\r\n <option value=\"\">{t('escalation.form.none')}</option>\r\n {roles.map((role) => (\r\n <option key={role.id} value={role.id}>\r\n {role.name}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium mb-1\">\r\n {t('escalation.form.status')}\r\n </label>\r\n <label className=\"flex items-center gap-2\">\r\n <input\r\n type=\"checkbox\"\r\n checked={editForm.isActive}\r\n onChange={(e) =>\r\n setEditForm({\r\n ...editForm,\r\n isActive: e.target.checked,\r\n })\r\n }\r\n className=\"rounded border-[var(--border-color)]\"\r\n />\r\n <span className=\"text-sm\">{t('escalation.form.active')}</span>\r\n </label>\r\n </div>\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n onClick={handleCancelEdit}\r\n className=\"btn btn-secondary flex items-center gap-1\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n {t('common:actions.cancel')}\r\n </button>\r\n <button\r\n onClick={handleSave}\r\n disabled={saving}\r\n className=\"btn btn-primary flex items-center gap-1\"\r\n >\r\n {saving ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Check className=\"w-4 h-4\" />\r\n )}\r\n {t('common:actions.save')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <TriggerIcon className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n <span className=\"font-medium\">\r\n {t(`escalation.triggerTypes.${rule.triggerType}`)}\r\n </span>\r\n {rule.isSystemDefault ? (\r\n <span className=\"text-[10px] px-1.5 py-0.5 rounded bg-[var(--bg-secondary)] text-[var(--text-secondary)] border border-[var(--border-color)]\">\r\n {t('escalation.scope.system')}\r\n </span>\r\n ) : (\r\n <span className=\"text-[10px] px-1.5 py-0.5 rounded bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]\">\r\n {t('escalation.scope.tenant')}\r\n </span>\r\n )}\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n <Clock className=\"w-4 h-4 inline mr-1\" />\r\n {formatDelay(rule.delayAfterBreachMinutes)}\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n <Bell className=\"w-4 h-4 inline mr-1\" />\r\n {getRoleName(rule.notifyRoleId)}\r\n </div>\r\n {!rule.isActive && (\r\n <span className=\"text-xs px-2 py-0.5 rounded bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {t('escalation.disabled')}\r\n </span>\r\n )}\r\n </div>\r\n <button\r\n onClick={() => handleEdit(rule)}\r\n className=\"btn btn-secondary btn-sm flex items-center gap-1\"\r\n >\r\n <Edit className=\"w-4 h-4\" />\r\n {t('common:actions.edit')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n <div className=\"card p-6\">\r\n <h3 className=\"text-lg font-semibold mb-4\">{t('escalation.howItWorks.title')}</h3>\r\n <div className=\"space-y-4 text-sm text-[var(--text-secondary)]\">\r\n {[1, 2, 3, 4].map((step) => (\r\n <div key={step} className=\"flex gap-3\">\r\n <div className=\"w-6 h-6 rounded-full bg-[var(--info-bg)] text-[var(--info-text)] flex items-center justify-center text-xs font-bold flex-shrink-0\">\r\n {step}\r\n </div>\r\n <p>{t(`escalation.howItWorks.step${step}`)}</p>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["LEVEL_ORDER","levelColors","triggerTypeIcons","Clock","AlertTriangle","Bell","EscalationConfigPage","useTranslation","loading","setLoading","useState","saving","setSaving","rules","setRules","roles","setRoles","editingRule","setEditingRule","editForm","setEditForm","loadData","useCallback","rulesRes","rolesRes","slaApi","api","error","useEffect","handleEdit","rule","handleCancelEdit","handleSave","formatDelay","minutes","hours","remainingMinutes","getRoleName","roleId","r","groupedRules","acc","jsxs","jsx","Breadcrumb","TrendingUp","Loader2","Fragment","Users","level","index","b","levelRules","TriggerIcon","isEditing","e","role","X","Check","Edit","step"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EscalationConfigPage-CwdnfJbJ.js","sources":["../../src/pages/platform/support/EscalationConfigPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n TrendingUp,\r\n Loader2,\r\n AlertTriangle,\r\n Bell,\r\n Clock,\r\n Users,\r\n Edit,\r\n Check,\r\n X,\r\n} from 'lucide-react';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { slaApi, type EscalationRuleDto } from '@/services/api/supportApi';\r\nimport { api } from '@/services/api/apiClient';\r\n\r\ninterface RoleDto {\r\n id: string;\r\n name: string;\r\n description: string | null;\r\n}\r\n\r\nconst LEVEL_ORDER = ['Supervisor', 'Manager', 'Director'] as const;\r\n\r\nconst levelColors: Record<string, string> = {\r\n None: 'bg-[var(--bg-secondary)] text-[var(--text-secondary)]',\r\n Supervisor: 'bg-[var(--info-bg)] text-[var(--info-text)]',\r\n Manager: 'bg-[var(--warning-bg)] text-[var(--warning-text)]',\r\n Director: 'bg-[var(--error-bg)] text-[var(--error-text)]',\r\n};\r\n\r\nconst triggerTypeIcons: Record<string, typeof AlertTriangle> = {\r\n ResponseBreach: Clock,\r\n ResolutionBreach: AlertTriangle,\r\n ManualRequest: Bell,\r\n};\r\n\r\nexport function EscalationConfigPage(): ReactElement {\r\n const { t } = useTranslation('support');\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [rules, setRules] = useState<EscalationRuleDto[]>([]);\r\n const [roles, setRoles] = useState<RoleDto[]>([]);\r\n const [editingRule, setEditingRule] = useState<EscalationRuleDto | null>(null);\r\n const [editForm, setEditForm] = useState<{\r\n delayAfterBreachMinutes: number;\r\n notifyRoleId: string | null;\r\n isActive: boolean;\r\n }>({ delayAfterBreachMinutes: 0, notifyRoleId: null, isActive: true });\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const [rulesRes, rolesRes] = await Promise.all([\r\n slaApi.getEscalationRules(),\r\n api.get<RoleDto[]>('/api/administration/permissions/roles'),\r\n ]);\r\n setRules(rulesRes);\r\n setRoles(rolesRes);\r\n } catch (error) {\r\n console.error('Failed to load escalation data:', error);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleEdit = (rule: EscalationRuleDto) => {\r\n setEditingRule(rule);\r\n setEditForm({\r\n delayAfterBreachMinutes: rule.delayAfterBreachMinutes,\r\n notifyRoleId: rule.notifyRoleId,\r\n isActive: rule.isActive,\r\n });\r\n };\r\n\r\n const handleCancelEdit = () => {\r\n setEditingRule(null);\r\n setEditForm({ delayAfterBreachMinutes: 0, notifyRoleId: null, isActive: true });\r\n };\r\n\r\n const handleSave = async () => {\r\n if (!editingRule) return;\r\n\r\n try {\r\n setSaving(true);\r\n await api.put(`/api/support/sla/escalation-rules/${editingRule.id}`, editForm);\r\n loadData();\r\n setEditingRule(null);\r\n } catch (error) {\r\n console.error('Failed to save escalation rule:', error);\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const formatDelay = (minutes: number) => {\r\n if (minutes === 0) return t('escalation.delay.immediate');\r\n if (minutes < 60) return `${minutes} min`;\r\n const hours = Math.floor(minutes / 60);\r\n const remainingMinutes = minutes % 60;\r\n if (remainingMinutes === 0) return `${hours}h`;\r\n return `${hours}h ${remainingMinutes}min`;\r\n };\r\n\r\n const getRoleName = (roleId: string | null) => {\r\n if (!roleId) return t('escalation.notConfigured');\r\n const role = roles.find((r) => r.id === roleId);\r\n return role?.name || t('escalation.unknownRole');\r\n };\r\n\r\n const groupedRules = rules.reduce((acc, rule) => {\r\n if (!acc[rule.level]) {\r\n acc[rule.level] = [];\r\n }\r\n acc[rule.level].push(rule);\r\n return acc;\r\n }, {} as Record<string, EscalationRuleDto[]>);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('title', 'Support'), href: '/support' },\r\n { label: t('escalation.title') }\r\n ]}\r\n />\r\n\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n <TrendingUp className=\"w-6 h-6\" />\r\n {t('escalation.title')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('escalation.subtitle')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {loading ? (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-primary-600)]\" />\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"card p-6 bg-[var(--bg-secondary)]\">\r\n <h3 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('escalation.hierarchy')}\r\n </h3>\r\n <div className=\"flex items-center gap-4\">\r\n {LEVEL_ORDER.map((level, index) => (\r\n <div key={level} className=\"flex items-center gap-2\">\r\n <div className={`px-4 py-2 rounded-[var(--radius-badge)] font-medium ${levelColors[level]}`}>\r\n {t(`escalation.levels.${level}`)}\r\n </div>\r\n {index < 2 && (\r\n <div className=\"text-[var(--text-secondary)]\">→</div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n <p className=\"mt-4 text-sm text-[var(--text-secondary)]\">\r\n {t('escalation.hierarchyDescription')}\r\n </p>\r\n </div>\r\n\r\n <div className=\"space-y-6\">\r\n {Object.entries(groupedRules)\r\n .filter(([level]) => level !== 'None')\r\n .sort((a, b) => {\r\n return LEVEL_ORDER.indexOf(a[0] as typeof LEVEL_ORDER[number]) - LEVEL_ORDER.indexOf(b[0] as typeof LEVEL_ORDER[number]);\r\n })\r\n .map(([level, levelRules]) => (\r\n <div key={level} className=\"card overflow-hidden\">\r\n <div className={`px-6 py-3 ${levelColors[level]} border-b border-[var(--border-color)]`}>\r\n <h3 className=\"font-semibold\">\r\n {t('escalation.level', {\r\n number: LEVEL_ORDER.indexOf(level as typeof LEVEL_ORDER[number]) + 1,\r\n label: t(`escalation.levels.${level}`),\r\n })}\r\n </h3>\r\n </div>\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {levelRules.map((rule) => {\r\n const TriggerIcon = triggerTypeIcons[rule.triggerType] || AlertTriangle;\r\n const isEditing = editingRule?.id === rule.id;\r\n\r\n return (\r\n <div\r\n key={rule.id}\r\n className={`p-4 ${!rule.isActive ? 'opacity-60' : ''}`}\r\n >\r\n {isEditing ? (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <TriggerIcon className=\"w-5 h-5\" />\r\n <span className=\"font-medium\">\r\n {t(`escalation.triggerTypes.${rule.triggerType}`)}\r\n </span>\r\n </div>\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium mb-1\">\r\n {t('escalation.form.delayAfterBreach')}\r\n </label>\r\n <div className=\"flex items-center gap-2\">\r\n <input\r\n type=\"number\"\r\n min=\"0\"\r\n value={editForm.delayAfterBreachMinutes}\r\n onChange={(e) =>\r\n setEditForm({\r\n ...editForm,\r\n delayAfterBreachMinutes: parseInt(e.target.value) || 0,\r\n })\r\n }\r\n className=\"input w-24\"\r\n />\r\n <span className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('escalation.form.minutes')}\r\n </span>\r\n </div>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium mb-1\">\r\n {t('escalation.form.notifyRole')}\r\n </label>\r\n <select\r\n value={editForm.notifyRoleId || ''}\r\n onChange={(e) =>\r\n setEditForm({\r\n ...editForm,\r\n notifyRoleId: e.target.value || null,\r\n })\r\n }\r\n className=\"input w-full\"\r\n >\r\n <option value=\"\">{t('escalation.form.none')}</option>\r\n {roles.map((role) => (\r\n <option key={role.id} value={role.id}>\r\n {role.name}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium mb-1\">\r\n {t('escalation.form.status')}\r\n </label>\r\n <label className=\"flex items-center gap-2\">\r\n <input\r\n type=\"checkbox\"\r\n checked={editForm.isActive}\r\n onChange={(e) =>\r\n setEditForm({\r\n ...editForm,\r\n isActive: e.target.checked,\r\n })\r\n }\r\n className=\"rounded border-[var(--border-color)]\"\r\n />\r\n <span className=\"text-sm\">{t('escalation.form.active')}</span>\r\n </label>\r\n </div>\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n onClick={handleCancelEdit}\r\n className=\"btn btn-secondary flex items-center gap-1\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n {t('common:actions.cancel')}\r\n </button>\r\n <button\r\n onClick={handleSave}\r\n disabled={saving}\r\n className=\"btn btn-primary flex items-center gap-1\"\r\n >\r\n {saving ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Check className=\"w-4 h-4\" />\r\n )}\r\n {t('common:actions.save')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <TriggerIcon className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n <span className=\"font-medium\">\r\n {t(`escalation.triggerTypes.${rule.triggerType}`)}\r\n </span>\r\n {rule.isSystemDefault ? (\r\n <span className=\"text-[10px] px-1.5 py-0.5 rounded bg-[var(--bg-secondary)] text-[var(--text-secondary)] border border-[var(--border-color)]\">\r\n {t('escalation.scope.system')}\r\n </span>\r\n ) : (\r\n <span className=\"text-[10px] px-1.5 py-0.5 rounded bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]\">\r\n {t('escalation.scope.tenant')}\r\n </span>\r\n )}\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n <Clock className=\"w-4 h-4 inline mr-1\" />\r\n {formatDelay(rule.delayAfterBreachMinutes)}\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n <Bell className=\"w-4 h-4 inline mr-1\" />\r\n {getRoleName(rule.notifyRoleId)}\r\n </div>\r\n {!rule.isActive && (\r\n <span className=\"text-xs px-2 py-0.5 rounded bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {t('escalation.disabled')}\r\n </span>\r\n )}\r\n </div>\r\n <button\r\n onClick={() => handleEdit(rule)}\r\n className=\"btn btn-secondary btn-sm flex items-center gap-1\"\r\n >\r\n <Edit className=\"w-4 h-4\" />\r\n {t('common:actions.edit')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n <div className=\"card p-6\">\r\n <h3 className=\"text-lg font-semibold mb-4\">{t('escalation.howItWorks.title')}</h3>\r\n <div className=\"space-y-4 text-sm text-[var(--text-secondary)]\">\r\n {[1, 2, 3, 4].map((step) => (\r\n <div key={step} className=\"flex gap-3\">\r\n <div className=\"w-6 h-6 rounded-full bg-[var(--info-bg)] text-[var(--info-text)] flex items-center justify-center text-xs font-bold flex-shrink-0\">\r\n {step}\r\n </div>\r\n <p>{t(`escalation.howItWorks.step${step}`)}</p>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["LEVEL_ORDER","levelColors","triggerTypeIcons","Clock","AlertTriangle","Bell","EscalationConfigPage","useTranslation","loading","setLoading","useState","saving","setSaving","rules","setRules","roles","setRoles","editingRule","setEditingRule","editForm","setEditForm","loadData","useCallback","rulesRes","rolesRes","slaApi","api","error","useEffect","handleEdit","rule","handleCancelEdit","handleSave","formatDelay","minutes","hours","remainingMinutes","getRoleName","roleId","r","groupedRules","acc","jsxs","jsx","Breadcrumb","TrendingUp","Loader2","Fragment","Users","level","index","b","levelRules","TriggerIcon","isEditing","e","role","X","Check","Edit","step"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),l=require("react"),M=require("react-i18next"),i=require("lucide-react"),d=require("./index-
|
|
2
|
-
//# sourceMappingURL=EscalationConfigPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),l=require("react"),M=require("react-i18next"),i=require("lucide-react"),d=require("./index-cAikSVW0.js"),x=["Supervisor","Manager","Director"],b={None:"bg-[var(--bg-secondary)] text-[var(--text-secondary)]",Supervisor:"bg-[var(--info-bg)] text-[var(--info-text)]",Manager:"bg-[var(--warning-bg)] text-[var(--warning-text)]",Director:"bg-[var(--error-bg)] text-[var(--error-text)]"},$={ResponseBreach:i.Clock,ResolutionBreach:i.AlertTriangle,ManualRequest:i.Bell};function T(){const{t:a}=M.useTranslation("support"),[y,f]=l.useState(!0),[p,v]=l.useState(!1),[N,R]=l.useState([]),[g,w]=l.useState([]),[m,h]=l.useState(null),[c,o]=l.useState({delayAfterBreachMinutes:0,notifyRoleId:null,isActive:!0}),u=l.useCallback(async()=>{try{f(!0);const[s,t]=await Promise.all([d.slaApi.getEscalationRules(),d.api.get("/api/administration/permissions/roles")]);R(s),w(t)}catch(s){console.error("Failed to load escalation data:",s)}finally{f(!1)}},[]);l.useEffect(()=>{u()},[u]);const A=s=>{h(s),o({delayAfterBreachMinutes:s.delayAfterBreachMinutes,notifyRoleId:s.notifyRoleId,isActive:s.isActive})},k=()=>{h(null),o({delayAfterBreachMinutes:0,notifyRoleId:null,isActive:!0})},C=async()=>{if(m)try{v(!0),await d.api.put(`/api/support/sla/escalation-rules/${m.id}`,c),u(),h(null)}catch(s){console.error("Failed to save escalation rule:",s)}finally{v(!1)}},S=s=>{if(s===0)return a("escalation.delay.immediate");if(s<60)return`${s} min`;const t=Math.floor(s/60),n=s%60;return n===0?`${t}h`:`${t}h ${n}min`},B=s=>s?g.find(n=>n.id===s)?.name||a("escalation.unknownRole"):a("escalation.notConfigured"),E=N.reduce((s,t)=>(s[t.level]||(s[t.level]=[]),s[t.level].push(t),s),{});return e.jsxs("div",{className:"space-y-6",children:[e.jsx(d.Breadcrumb,{items:[{label:a("title","Support"),href:"/support"},{label:a("escalation.title")}]}),e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold flex items-center gap-2",children:[e.jsx(i.TrendingUp,{className:"w-6 h-6"}),a("escalation.title")]}),e.jsx("p",{className:"text-[var(--text-secondary)]",children:a("escalation.subtitle")})]})}),y?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx(i.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-primary-600)]"})}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"card p-6 bg-[var(--bg-secondary)]",children:[e.jsxs("h3",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(i.Users,{className:"w-5 h-5"}),a("escalation.hierarchy")]}),e.jsx("div",{className:"flex items-center gap-4",children:x.map((s,t)=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:`px-4 py-2 rounded-[var(--radius-badge)] font-medium ${b[s]}`,children:a(`escalation.levels.${s}`)}),t<2&&e.jsx("div",{className:"text-[var(--text-secondary)]",children:"→"})]},s))}),e.jsx("p",{className:"mt-4 text-sm text-[var(--text-secondary)]",children:a("escalation.hierarchyDescription")})]}),e.jsx("div",{className:"space-y-6",children:Object.entries(E).filter(([s])=>s!=="None").sort((s,t)=>x.indexOf(s[0])-x.indexOf(t[0])).map(([s,t])=>e.jsxs("div",{className:"card overflow-hidden",children:[e.jsx("div",{className:`px-6 py-3 ${b[s]} border-b border-[var(--border-color)]`,children:e.jsx("h3",{className:"font-semibold",children:a("escalation.level",{number:x.indexOf(s)+1,label:a(`escalation.levels.${s}`)})})}),e.jsx("div",{className:"divide-y divide-[var(--border-color)]",children:t.map(n=>{const j=$[n.triggerType]||i.AlertTriangle,I=m?.id===n.id;return e.jsx("div",{className:`p-4 ${n.isActive?"":"opacity-60"}`,children:I?e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(j,{className:"w-5 h-5"}),e.jsx("span",{className:"font-medium",children:a(`escalation.triggerTypes.${n.triggerType}`)})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:a("escalation.form.delayAfterBreach")}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"number",min:"0",value:c.delayAfterBreachMinutes,onChange:r=>o({...c,delayAfterBreachMinutes:parseInt(r.target.value)||0}),className:"input w-24"}),e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:a("escalation.form.minutes")})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:a("escalation.form.notifyRole")}),e.jsxs("select",{value:c.notifyRoleId||"",onChange:r=>o({...c,notifyRoleId:r.target.value||null}),className:"input w-full",children:[e.jsx("option",{value:"",children:a("escalation.form.none")}),g.map(r=>e.jsx("option",{value:r.id,children:r.name},r.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:a("escalation.form.status")}),e.jsxs("label",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",checked:c.isActive,onChange:r=>o({...c,isActive:r.target.checked}),className:"rounded border-[var(--border-color)]"}),e.jsx("span",{className:"text-sm",children:a("escalation.form.active")})]})]})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsxs("button",{onClick:k,className:"btn btn-secondary flex items-center gap-1",children:[e.jsx(i.X,{className:"w-4 h-4"}),a("common:actions.cancel")]}),e.jsxs("button",{onClick:C,disabled:p,className:"btn btn-primary flex items-center gap-1",children:[p?e.jsx(i.Loader2,{className:"w-4 h-4 animate-spin"}):e.jsx(i.Check,{className:"w-4 h-4"}),a("common:actions.save")]})]})]}):e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(j,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("span",{className:"font-medium",children:a(`escalation.triggerTypes.${n.triggerType}`)}),n.isSystemDefault?e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-[var(--bg-secondary)] text-[var(--text-secondary)] border border-[var(--border-color)]",children:a("escalation.scope.system")}):e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]",children:a("escalation.scope.tenant")})]}),e.jsxs("div",{className:"text-sm text-[var(--text-secondary)]",children:[e.jsx(i.Clock,{className:"w-4 h-4 inline mr-1"}),S(n.delayAfterBreachMinutes)]}),e.jsxs("div",{className:"text-sm text-[var(--text-secondary)]",children:[e.jsx(i.Bell,{className:"w-4 h-4 inline mr-1"}),B(n.notifyRoleId)]}),!n.isActive&&e.jsx("span",{className:"text-xs px-2 py-0.5 rounded bg-[var(--bg-secondary)] text-[var(--text-secondary)]",children:a("escalation.disabled")})]}),e.jsxs("button",{onClick:()=>A(n),className:"btn btn-secondary btn-sm flex items-center gap-1",children:[e.jsx(i.Edit,{className:"w-4 h-4"}),a("common:actions.edit")]})]})},n.id)})})]},s))}),e.jsxs("div",{className:"card p-6",children:[e.jsx("h3",{className:"text-lg font-semibold mb-4",children:a("escalation.howItWorks.title")}),e.jsx("div",{className:"space-y-4 text-sm text-[var(--text-secondary)]",children:[1,2,3,4].map(s=>e.jsxs("div",{className:"flex gap-3",children:[e.jsx("div",{className:"w-6 h-6 rounded-full bg-[var(--info-bg)] text-[var(--info-text)] flex items-center justify-center text-xs font-bold flex-shrink-0",children:s}),e.jsx("p",{children:a(`escalation.howItWorks.step${s}`)})]},s))})]})]})]})}exports.EscalationConfigPage=T;
|
|
2
|
+
//# sourceMappingURL=EscalationConfigPage-DnjLFXnL.js.map
|