@atlashub/smartstack 3.21.0 → 3.25.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-7si3Ng8e.js → AgentSkillsPage-BWQSCYl-.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js.map → AgentSkillsPage-BWQSCYl-.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js → AgentSkillsPage-IQcMnBaD.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js.map → AgentSkillsPage-IQcMnBaD.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js → AgentWorkloadPage-DqrjkvWL.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js.map → AgentWorkloadPage-DqrjkvWL.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js → AgentWorkloadPage-w-HiyFYP.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js.map → AgentWorkloadPage-w-HiyFYP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js → ApiCatalogDetailPage-D3L8Yf4G.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js.map → ApiCatalogDetailPage-D3L8Yf4G.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js → ApiCatalogDetailPage-MPT3Kz6H.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js.map → ApiCatalogDetailPage-MPT3Kz6H.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js → ApiCatalogPage-D4Hg3uiS.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js.map → ApiCatalogPage-D4Hg3uiS.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js → ApiCatalogPage-DRg5Cz0r.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js.map → ApiCatalogPage-DRg5Cz0r.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js → ApplicationDetailPage-Caizuyn2.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js.map → ApplicationDetailPage-Caizuyn2.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js → ApplicationDetailPage-CuCW6aMB.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js.map → ApplicationDetailPage-CuCW6aMB.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js → ApplicationsDashboardPage-B2MW8-Kc.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js.map → ApplicationsDashboardPage-B2MW8-Kc.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js → ApplicationsDashboardPage-BDIjFIYZ.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js.map → ApplicationsDashboardPage-BDIjFIYZ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js → ApplicationsGridPage-DV-FihKj.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js.map → ApplicationsGridPage-DV-FihKj.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js → ApplicationsGridPage-DXsTfXPI.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js.map → ApplicationsGridPage-DXsTfXPI.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js → ApplicationsListPage--CGkyBuJ.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js.map → ApplicationsListPage--CGkyBuJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js → ApplicationsListPage-JUX823bh.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js.map → ApplicationsListPage-JUX823bh.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js → ApplicationsPage-6zgFye6w.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js.map → ApplicationsPage-6zgFye6w.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js → ApplicationsPage-CQPuuiO6.js} +4 -4
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js.map → ApplicationsPage-CQPuuiO6.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js → AssignmentRulesPage-CFffeEbo.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js.map → AssignmentRulesPage-CFffeEbo.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js → AssignmentRulesPage-D78UeUId.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js.map → AssignmentRulesPage-D78UeUId.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js → AssignmentsPage-Cww2ifZF.js} +2 -2
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js.map → AssignmentsPage-Cww2ifZF.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js → AssignmentsPage-DE_QS2LO.js} +2 -2
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js.map → AssignmentsPage-DE_QS2LO.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js → AuthCallbackPage-CA2nO6DG.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js.map → AuthCallbackPage-CA2nO6DG.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js → AuthCallbackPage-CDUAoX-N.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js.map → AuthCallbackPage-CDUAoX-N.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js → ConfirmEmailPage-BqsILAYH.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js.map → ConfirmEmailPage-BqsILAYH.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js → ConfirmEmailPage-INeHCuMB.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js.map → ConfirmEmailPage-INeHCuMB.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js → CreateSupportTicketPage-BWeuV2aU.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js.map → CreateSupportTicketPage-BWeuV2aU.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js → CreateSupportTicketPage-OBwF4v7b.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js.map → CreateSupportTicketPage-OBwF4v7b.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZ80NGV.js → DashboardPage-CKHqWrdS.js} +3 -3
- package/dist/chunks/{DashboardPage-CUZ80NGV.js.map → DashboardPage-CKHqWrdS.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CaNOAstg.js → DashboardPage-COmc9b__.js} +3 -3
- package/dist/chunks/{DashboardPage-CaNOAstg.js.map → DashboardPage-COmc9b__.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B48_rQFi.js → DashboardPage-CfKZHiSj.js} +2 -2
- package/dist/chunks/{DashboardPage-B48_rQFi.js.map → DashboardPage-CfKZHiSj.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZV1J9t.js → DashboardPage-CwEZZ3jx.js} +2 -2
- package/dist/chunks/{DashboardPage-CUZV1J9t.js.map → DashboardPage-CwEZZ3jx.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js → EscalationConfigPage--7lgZ0kJ.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js.map → EscalationConfigPage--7lgZ0kJ.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js → EscalationConfigPage-DPyiBcqV.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js.map → EscalationConfigPage-DPyiBcqV.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js → ForceChangePasswordPage-BE-6umub.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js.map → ForceChangePasswordPage-BE-6umub.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js → ForceChangePasswordPage-CnsYoWmV.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js.map → ForceChangePasswordPage-CnsYoWmV.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js → ForgotPasswordPage-CSq4DnFF.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js.map → ForgotPasswordPage-CSq4DnFF.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js → ForgotPasswordPage-DZLVolAC.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js.map → ForgotPasswordPage-DZLVolAC.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js → GroupDetailPage-Bf9Wb_2j.js} +5 -5
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js.map → GroupDetailPage-Bf9Wb_2j.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js → GroupDetailPage-R-hf3rJ7.js} +2 -2
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js.map → GroupDetailPage-R-hf3rJ7.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js → MyAccessRequestsPage-BIisvWM6.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js.map → MyAccessRequestsPage-BIisvWM6.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js → MyAccessRequestsPage-BLSV7Tbx.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js.map → MyAccessRequestsPage-BLSV7Tbx.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js → MyTenantsPage-D-7k9CP1.js} +3 -3
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js.map → MyTenantsPage-D-7k9CP1.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js → MyTenantsPage-DqGW6aDt.js} +2 -2
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js.map → MyTenantsPage-DqGW6aDt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js → MyTicketsPage--DgDsnZA.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js.map → MyTicketsPage--DgDsnZA.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js → MyTicketsPage-CqJ3Aqob.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js.map → MyTicketsPage-CqJ3Aqob.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js → NavigationAppsPage-Bebis_RT.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js.map → NavigationAppsPage-Bebis_RT.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js → NavigationAppsPage-THNPOAjv.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js.map → NavigationAppsPage-THNPOAjv.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-C29Lln5o.js → NotificationsPage-CAbNW_Cn.js} +2 -2
- package/dist/chunks/{NotificationsPage-C29Lln5o.js.map → NotificationsPage-CAbNW_Cn.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js → NotificationsPage-DxwizUhL.js} +2 -2
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js.map → NotificationsPage-DxwizUhL.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js → OnboardingWizardPage-C6HlbJ3K.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js.map → OnboardingWizardPage-C6HlbJ3K.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js → OnboardingWizardPage-CyC2zONO.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js.map → OnboardingWizardPage-CyC2zONO.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js → PermissionDetailPage-BDHiNgky.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js.map → PermissionDetailPage-BDHiNgky.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js → PermissionDetailPage-C5K17ydY.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js.map → PermissionDetailPage-C5K17ydY.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js → PermissionsPage-COI5LJPo.js} +2 -2
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js.map → PermissionsPage-COI5LJPo.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js → PermissionsPage-CkOwH2_d.js} +2 -2
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js.map → PermissionsPage-CkOwH2_d.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js → PortalDashboardPage-CoEC4CmC.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js.map → PortalDashboardPage-CoEC4CmC.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js → PortalDashboardPage-DrYymEf-.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js.map → PortalDashboardPage-DrYymEf-.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js → PreferencesPage-CJRaU3ba.js} +2 -2
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js.map → PreferencesPage-CJRaU3ba.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-B81MsNV1.js → PreferencesPage-Cqr9mAab.js} +2 -2
- package/dist/chunks/{PreferencesPage-B81MsNV1.js.map → PreferencesPage-Cqr9mAab.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DDrl10zj.js → ProfilePage-BZVpg6-l.js} +2 -2
- package/dist/chunks/{ProfilePage-DDrl10zj.js.map → ProfilePage-BZVpg6-l.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DPoXwdnc.js → ProfilePage-Cu_FITeL.js} +2 -2
- package/dist/chunks/{ProfilePage-DPoXwdnc.js.map → ProfilePage-Cu_FITeL.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js → ReferencesManagementPage-DUlVk9Ps.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js.map → ReferencesManagementPage-DUlVk9Ps.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js → ReferencesManagementPage-ZCuYtqd7.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js.map → ReferencesManagementPage-ZCuYtqd7.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CiQib3-6.js → RegisterPage-C4xmVwh9.js} +2 -2
- package/dist/chunks/{RegisterPage-CiQib3-6.js.map → RegisterPage-C4xmVwh9.js.map} +1 -1
- package/dist/chunks/{RegisterPage-bXCcJD88.js → RegisterPage-DGyzoIHT.js} +2 -2
- package/dist/chunks/{RegisterPage-bXCcJD88.js.map → RegisterPage-DGyzoIHT.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js → ResetPasswordPage-DqDD6VPR.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js.map → ResetPasswordPage-DqDD6VPR.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js → ResetPasswordPage-Glu-aeqv.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js.map → ResetPasswordPage-Glu-aeqv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js → ResolutionModal-CxjANAOP.js} +2 -2
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js.map → ResolutionModal-CxjANAOP.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js → ResolutionModal-Duat18qV.js} +2 -2
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js.map → ResolutionModal-Duat18qV.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js → RoleDetailPage-BQffUSnt.js} +3 -3
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js.map → RoleDetailPage-BQffUSnt.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js → RoleDetailPage-JTm5lD1_.js} +2 -2
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js.map → RoleDetailPage-JTm5lD1_.js.map} +1 -1
- package/dist/chunks/{RolesPage-Pm-RN3lP.js → RolesPage-B9rRzciI.js} +2 -2
- package/dist/chunks/{RolesPage-Pm-RN3lP.js.map → RolesPage-B9rRzciI.js.map} +1 -1
- package/dist/chunks/{RolesPage-Cb8joqdJ.js → RolesPage-BN8_zMOC.js} +2 -2
- package/dist/chunks/{RolesPage-Cb8joqdJ.js.map → RolesPage-BN8_zMOC.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-B86McKM6.js → SlaConfigPage-B7kZNig4.js} +2 -2
- package/dist/chunks/{SlaConfigPage-B86McKM6.js.map → SlaConfigPage-B7kZNig4.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js → SlaConfigPage-okvZfA_K.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js.map → SlaConfigPage-okvZfA_K.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js → SupportPermissionsPage-DGAPqJbl.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js.map → SupportPermissionsPage-DGAPqJbl.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js → SupportPermissionsPage-Dg_wLOme.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js.map → SupportPermissionsPage-Dg_wLOme.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-BDguJ401.js → TemplatesPage-DT9fhlAU.js} +2 -2
- package/dist/chunks/{TemplatesPage-BDguJ401.js.map → TemplatesPage-DT9fhlAU.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DdnGgioU.js → TemplatesPage-DiEk538p.js} +2 -2
- package/dist/chunks/{TemplatesPage-DdnGgioU.js.map → TemplatesPage-DiEk538p.js.map} +1 -1
- package/dist/chunks/{TenantCard-ffwWsgFQ.js → TenantCard-BbSYk9_Z.js} +2 -2
- package/dist/chunks/{TenantCard-ffwWsgFQ.js.map → TenantCard-BbSYk9_Z.js.map} +1 -1
- package/dist/chunks/{TenantCard-CUjb6og9.js → TenantCard-CEkiKxcZ.js} +2 -2
- package/dist/chunks/{TenantCard-CUjb6og9.js.map → TenantCard-CEkiKxcZ.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js → TenantScopeSelector-BWfYxvEa.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js.map → TenantScopeSelector-BWfYxvEa.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js → TenantScopeSelector-D-BKgQPV.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js.map → TenantScopeSelector-D-BKgQPV.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js → TicketDetailPage-C1mNS9Up.js} +2 -2
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js.map → TicketDetailPage-C1mNS9Up.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js → TicketDetailPage-ieVDRh42.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js.map → TicketDetailPage-ieVDRh42.js.map} +1 -1
- package/dist/chunks/{TicketsPage-Bqd6moQy.js → TicketsPage-CnuWsnIW.js} +2 -2
- package/dist/chunks/{TicketsPage-Bqd6moQy.js.map → TicketsPage-CnuWsnIW.js.map} +1 -1
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js → TicketsPage-jjyY15_D.js} +2 -2
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js.map → TicketsPage-jjyY15_D.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js → UserCreateTicketPage-B8Tvf-ag.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js.map → UserCreateTicketPage-B8Tvf-ag.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js → UserCreateTicketPage-DnOsDlfO.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js.map → UserCreateTicketPage-DnOsDlfO.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js → UserDashboardPage-BrtkJ-NB.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js.map → UserDashboardPage-BrtkJ-NB.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js → UserDashboardPage-KLB5CQP5.js} +2 -2
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js.map → UserDashboardPage-KLB5CQP5.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-B110bmGX.js → UserDetailPage-U7smBQoF.js} +5 -5
- package/dist/chunks/{UserDetailPage-B110bmGX.js.map → UserDetailPage-U7smBQoF.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-CV2VCE46.js → UserDetailPage-_J6lcKAU.js} +2 -2
- package/dist/chunks/{UserDetailPage-CV2VCE46.js.map → UserDetailPage-_J6lcKAU.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js → UserTicketDetailPage-CWoYQgH-.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js.map → UserTicketDetailPage-CWoYQgH-.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js → UserTicketDetailPage-DkufSlvZ.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js.map → UserTicketDetailPage-DkufSlvZ.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js → UsersGroupsPage-C38s2-Rq.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js.map → UsersGroupsPage-C38s2-Rq.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js → UsersGroupsPage-Dq3rAteo.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js.map → UsersGroupsPage-Dq3rAteo.js.map} +1 -1
- package/dist/chunks/{UsersPage-Bg7033pp.js → UsersPage-B5C5KEUR.js} +2 -2
- package/dist/chunks/{UsersPage-Bg7033pp.js.map → UsersPage-B5C5KEUR.js.map} +1 -1
- package/dist/chunks/{UsersPage-TYAfwPY1.js → UsersPage-CXC9Hvq6.js} +2 -2
- package/dist/chunks/{UsersPage-TYAfwPY1.js.map → UsersPage-CXC9Hvq6.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js → accessRequestsApi-B-4TJ5_U.js} +2 -2
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js.map → accessRequestsApi-B-4TJ5_U.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js → accessRequestsApi-DZSfThpd.js} +2 -2
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js.map → accessRequestsApi-DZSfThpd.js.map} +1 -1
- package/dist/chunks/{aiApi-CsH8DXgs.js → aiApi-B20Teu2v.js} +2 -2
- package/dist/chunks/{aiApi-CsH8DXgs.js.map → aiApi-B20Teu2v.js.map} +1 -1
- package/dist/chunks/{aiApi-CVPzFTXa.js → aiApi-DMGz-RPM.js} +2 -2
- package/dist/chunks/{aiApi-CVPzFTXa.js.map → aiApi-DMGz-RPM.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js → applicationAnalyticsApi-Bwa75Fzd.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js.map → applicationAnalyticsApi-Bwa75Fzd.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js → applicationAnalyticsApi-CLBqRPfN.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js.map → applicationAnalyticsApi-CLBqRPfN.js.map} +1 -1
- package/dist/chunks/{groupsApi-BgCk2fsp.js → groupsApi-QzXI-5xu.js} +2 -2
- package/dist/chunks/{groupsApi-BgCk2fsp.js.map → groupsApi-QzXI-5xu.js.map} +1 -1
- package/dist/chunks/{groupsApi-BIbG665N.js → groupsApi-hB9kSWEd.js} +2 -2
- package/dist/chunks/{groupsApi-BIbG665N.js.map → groupsApi-hB9kSWEd.js.map} +1 -1
- package/dist/chunks/{index-Cb3LotuT.js → index--NGcBYUu.js} +3 -3
- package/dist/chunks/{index-Cb3LotuT.js.map → index--NGcBYUu.js.map} +1 -1
- package/dist/chunks/{index-C33zcyF4.js → index--aPwOFjF.js} +2 -2
- package/dist/chunks/{index-C33zcyF4.js.map → index--aPwOFjF.js.map} +1 -1
- package/dist/chunks/{index-sMr9qND_.js → index-0VrOtwP0.js} +2 -2
- package/dist/chunks/{index-sMr9qND_.js.map → index-0VrOtwP0.js.map} +1 -1
- package/dist/chunks/{index-DDKetfKq.js → index-37U271aw.js} +2 -2
- package/dist/chunks/{index-DDKetfKq.js.map → index-37U271aw.js.map} +1 -1
- package/dist/chunks/{index-B9fS7ir6.js → index-B7qZTuQ-.js} +2 -2
- package/dist/chunks/{index-B9fS7ir6.js.map → index-B7qZTuQ-.js.map} +1 -1
- package/dist/chunks/{index-CdjBY7L8.js → index-Bedzmqr-.js} +2 -2
- package/dist/chunks/{index-CdjBY7L8.js.map → index-Bedzmqr-.js.map} +1 -1
- package/dist/chunks/{index-CHG_O1fS.js → index-Betxo5g5.js} +2 -2
- package/dist/chunks/{index-CHG_O1fS.js.map → index-Betxo5g5.js.map} +1 -1
- package/dist/chunks/{index-jiGu-H8x.js → index-BmaJz475.js} +2 -2
- package/dist/chunks/{index-jiGu-H8x.js.map → index-BmaJz475.js.map} +1 -1
- package/dist/chunks/{index-C53JoVNk.js → index-Buhqag3v.js} +2 -2
- package/dist/chunks/{index-C53JoVNk.js.map → index-Buhqag3v.js.map} +1 -1
- package/dist/chunks/{index-DO0Rw7hX.js → index-C3VxlfKq.js} +2 -2
- package/dist/chunks/{index-DO0Rw7hX.js.map → index-C3VxlfKq.js.map} +1 -1
- package/dist/chunks/{index-CSQ60fpG.js → index-CgpRo8Oe.js} +2 -2
- package/dist/chunks/{index-CSQ60fpG.js.map → index-CgpRo8Oe.js.map} +1 -1
- package/dist/chunks/{index-B-e-ELsf.js → index-DOY0w8Iu.js} +8 -8
- package/dist/chunks/{index-B-e-ELsf.js.map → index-DOY0w8Iu.js.map} +1 -1
- package/dist/chunks/{index-D2REDIRX.js → index-DwuvIOrQ.js} +2 -2
- package/dist/chunks/{index-D2REDIRX.js.map → index-DwuvIOrQ.js.map} +1 -1
- package/dist/chunks/{index-DCcl7Qof.js → index-DzedSLdI.js} +2 -2
- package/dist/chunks/{index-DCcl7Qof.js.map → index-DzedSLdI.js.map} +1 -1
- package/dist/chunks/{index-2wUhd9Lu.js → index-IgLVXPg8.js} +10 -10
- package/dist/chunks/index-IgLVXPg8.js.map +1 -0
- package/dist/chunks/{index-CwSaRXXg.js → index-lpIzhufD.js} +1916 -1900
- package/dist/chunks/index-lpIzhufD.js.map +1 -0
- package/dist/chunks/{index-Cuwn2q-f.js → index-mLUKwbGl.js} +4 -4
- package/dist/chunks/{index-Cuwn2q-f.js.map → index-mLUKwbGl.js.map} +1 -1
- package/dist/chunks/{index-B0mk2tNY.js → index-tO6MMIFB.js} +2 -2
- package/dist/chunks/{index-B0mk2tNY.js.map → index-tO6MMIFB.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js → tenantIconMap-BQD9byc8.js} +2 -2
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js.map → tenantIconMap-BQD9byc8.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js → tenantIconMap-CTMuSt18.js} +2 -2
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js.map → tenantIconMap-CTMuSt18.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js → ticketingApi-BNIdox5t.js} +2 -2
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js.map → ticketingApi-BNIdox5t.js.map} +1 -1
- package/dist/chunks/{ticketingApi-r4Avm9iS.js → ticketingApi-J0vC_t7r.js} +2 -2
- package/dist/chunks/{ticketingApi-r4Avm9iS.js.map → ticketingApi-J0vC_t7r.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-B9bF4swg.js → useAccessRequests-DCNNLnxk.js} +3 -3
- package/dist/chunks/{useAccessRequests-B9bF4swg.js.map → useAccessRequests-DCNNLnxk.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js → useAccessRequests-DT7X4FAK.js} +2 -2
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js.map → useAccessRequests-DT7X4FAK.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js → useUserAccessRequests-BYbmG4c7.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js.map → useUserAccessRequests-BYbmG4c7.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js → useUserAccessRequests-CylKxRN6.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js.map → useUserAccessRequests-CylKxRN6.js.map} +1 -1
- package/dist/hooks/useCollapsibleState.d.ts +5 -2
- package/dist/hooks/useCollapsibleState.d.ts.map +1 -1
- package/dist/i18n/config.d.ts +1 -0
- package/dist/i18n/config.d.ts.map +1 -1
- package/dist/main.d.ts +0 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/dist/utils/permissions.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-2wUhd9Lu.js.map +0 -1
- package/dist/chunks/index-CwSaRXXg.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage-CaNOAstg.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-COmc9b__.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":";;;;;;;AAQA,MAAMA,IAA+C;AAAA,EACnD,SAAS,gBAAAC,EAACC,GAAA,EAAQ,WAAU,UAAA,CAAU;AAAA,EACtC,QAAQ,gBAAAD,EAACE,IAAA,EAAW,WAAU,UAAA,CAAU;AAAA,EACxC,QAAQ,gBAAAF,EAACG,IAAA,EAAO,WAAU,UAAA,CAAU;AAAA,EACpC,SAAS,gBAAAH,EAACC,GAAA,EAAQ,WAAU,qBAAA,CAAqB;AACnD,GAEMG,IAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEMC,IAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEaC,KAA4D,CAAC,EAAE,MAAAC,QACtE,CAACA,KAAS,CAACA,EAAK,cAAc,UAAU,CAACA,EAAK,WAAW,SAEzD,gBAAAP,EAAC,OAAA,EAAI,WAAU,iDAAgD,UAAA,4BAE/D,IAKF,gBAAAQ,EAAC,OAAA,EAAI,WAAU,yCAEb,UAAA;AAAA,EAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,yDAAwD,UAAA,kBAEtE;AAAA,IACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,aACZ,UAAAO,EAAK,aAAa,IAAI,CAACE,GAAQC,MAC9B,gBAAAF,EAAC,OAAA,EAA4B,WAAU,2BACrC,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACZ,UAAA;AAAA,QAAAT,EAAYU,EAAO,UAAU,KAAKV,EAAY;AAAA,QAC/C,gBAAAC,EAAC,QAAA,EAAK,WAAU,WAAW,YAAO,WAAA,CAAW;AAAA,MAAA,GAC/C;AAAA,MACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,oEACb,UAAA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,OAAO,GAAGS,EAAO,UAAU;AAAA,YAC3B,iBAAiBL,EAAaM,IAAQN,EAAa,MAAM;AAAA,UAAA;AAAA,QAC3D;AAAA,MAAA,GAEJ;AAAA,MACA,gBAAAI,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,eAAe,UAAAS,EAAO,OAAM;AAAA,QAC5C,gBAAAD,EAAC,QAAA,EAAK,WAAU,6CAA4C,UAAA;AAAA,UAAA;AAAA,UACxDC,EAAO,WAAW,QAAQ,CAAC;AAAA,UAAE;AAAA,QAAA,EAAA,CACjC;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,KAnBQA,EAAO,UAoBjB,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAAA,oBAGC,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAT,EAAC,MAAA,EAAG,WAAU,yDAAwD,UAAA,cAEtE;AAAA,IACA,gBAAAA,EAAC,SAAI,WAAU,aACZ,YAAK,UAAU,IAAI,CAACW,GAASD,MAAU;AACtC,YAAME,IAAW,KAAK,IAAI,GAAGL,EAAK,UAAU,IAAI,CAAAM,MAAKA,EAAE,KAAK,GAAG,CAAC,GAC1DC,IAAcH,EAAQ,QAAQC,IAAY;AAEhD,aACE,gBAAAJ,EAAC,OAAA,EAA0B,WAAU,2BACnC,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,gBAAgB,UAAAW,EAAQ,SAAQ;AAAA,QAC/C,gBAAAX,EAAC,OAAA,EAAI,WAAU,oEACb,UAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,OAAO,GAAGc,CAAU;AAAA,cACpB,iBAAiBT,EAAcK,IAAQL,EAAc,MAAM;AAAA,YAAA;AAAA,UAC7D;AAAA,QAAA,GAEJ;AAAA,QACA,gBAAAL,EAAC,OAAA,EAAI,WAAU,+BAA+B,YAAQ,MAAA,CAAM;AAAA,MAAA,EAAA,GAXpDW,EAAQ,OAYlB;AAAA,IAEJ,CAAC,EAAA,CACH;AAAA,EAAA,EAAA,CACF;AAAA,GACF,GC9FEI,IAAgB,CAAC,WAAW,WAAW,WAAW,SAAS,GAEpDC,KAA8D,CAAC,EAAE,MAAAT,QAAW;AACvF,MAAI,CAACA;AACH,WACE,gBAAAP,EAAC,OAAA,EAAI,WAAU,iDAAgD,UAAA,gCAE/D;AAIJ,QAAMiB,IAAiB,KAAK,IAAI,GAAGV,EAAK,oBAAoB,IAAI,CAAAM,MAAKA,EAAE,KAAK,GAAG,CAAC,GAC1EK,IAAe,KAAK,IAAI,GAAGX,EAAK,eAAe,IAAI,CAAAY,MAAKA,EAAE,WAAW,GAAG,CAAC;AAE/E,SACE,gBAAAX,EAAC,OAAA,EAAI,WAAU,aAEb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,yDAAwD,UAAA,iCAEtE;AAAA,MACA,gBAAAA,EAAC,SAAI,WAAU,aACZ,YAAK,oBAAoB,IAAI,CAACoB,GAAQV,MAAU;AAC/C,cAAMI,IAAcM,EAAO,QAAQH,IAAkB;AAErD,eACE,gBAAAT,EAAC,OAAA,EAAwB,WAAU,2BACjC,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,gBAAgB,UAAAoB,EAAO,OAAM;AAAA,UAC5C,gBAAApB,EAAC,OAAA,EAAI,WAAU,oEACb,UAAA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,GAAGc,CAAU;AAAA,gBACpB,iBAAiBC,EAAcL,IAAQK,EAAc,MAAM;AAAA,cAAA;AAAA,YAC7D;AAAA,UAAA,GAEJ;AAAA,UACA,gBAAAP,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,eAAe,UAAAoB,EAAO,OAAM;AAAA,YAC5C,gBAAApB,EAAC,QAAA,EAAK,WAAU,6CAA4C,UAAA,WAAA,CAE5D;AAAA,UAAA,EAAA,CACF;AAAA,QAAA,EAAA,GAhBQoB,EAAO,MAiBjB;AAAA,MAEJ,CAAC,EAAA,CACH;AAAA,IAAA,GACF;AAAA,sBAGC,OAAA,EACC,UAAA;AAAA,MAAA,gBAAApB,EAAC,MAAA,EAAG,WAAU,yDAAwD,UAAA,oBAEtE;AAAA,MACA,gBAAAA,EAAC,SAAI,WAAU,kDACZ,YAAK,eAAe,IAAI,CAACqB,MAAa;AACrC,cAAMC,IAAoBD,EAAS,cAAcH,IAAgB;AAEjE,eACE,gBAAAV;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAR;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,QAAQ,GAAGsB,CAAgB;AAAA,oBAC3B,WAAWD,EAAS,cAAc,IAAI,QAAQ;AAAA,kBAAA;AAAA,kBAEhD,OAAO,GAAGA,EAAS,IAAI,MAAMA,EAAS,WAAW;AAAA,gBAAA;AAAA,cAAA;AAAA,cAElDA,EAAS,OAAO,MAAM,KACrB,gBAAAb,EAAC,QAAA,EAAK,WAAU,wCACb,UAAA;AAAA,gBAAAa,EAAS;AAAA,gBAAK;AAAA,cAAA,EAAA,CACjB;AAAA,YAAA;AAAA,UAAA;AAAA,UAdGA,EAAS;AAAA,QAAA;AAAA,MAkBpB,CAAC,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IAGA,gBAAAb,EAAC,OAAA,EAAI,WAAU,qEACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,oCACZ,UAAAO,EAAK,kBACR;AAAA,QACA,gBAAAP,EAAC,OAAA,EAAI,WAAU,6CAA4C,UAAA,qBAAA,CAE3D;AAAA,MAAA,GACF;AAAA,MACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qCACX,UAAA;AAAA,WAAAD,EAAK,gBAAgB,KAAK,QAAQ,CAAC;AAAA,UAAE;AAAA,QAAA,GACzC;AAAA,QACA,gBAAAP,EAAC,OAAA,EAAI,WAAU,6CAA4C,UAAA,iBAAA,CAE3D;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ,GCzEMuB,KAAuC;AAAA,EAC3C,QAAQ;AAAA,EACR,UAAU;AACZ;AAEO,SAASC,KAAmC;AACjD,QAAM,EAAE,GAAAC,EAAA,IAAMC,GAAe,CAAC,SAAS,YAAY,CAAC,GAC9CC,IAAWC,GAAA,GACX,EAAE,eAAAC,GAAe,cAAAC,EAAA,IAAiBC,GAAA,GAClC,CAACC,GAASC,CAAU,IAAIC,EAAS,EAAI,GACrC,CAACC,GAAYC,CAAa,IAAIF,EAAS,EAAK,GAC5C,CAACG,GAAQC,CAAS,IAAIJ,EAAS,EAAE,GAEjC,CAACK,GAAUC,CAAW,IAAIN,EAA0C,IAAI,GACxE,CAACO,GAAYC,CAAa,IAAIR,EAA+B,CAAA,CAAE,GAC/D,CAACS,GAAUC,CAAW,IAAIV,EAAoC,CAAA,CAAE,GAChE,CAACW,GAAQC,CAAS,IAAIZ,EAAyB,CAAA,CAAE,GACjD,CAACa,GAAgBC,CAAiB,IAAId,EAAmC,CAAA,CAAE,GAC3E,CAACe,GAAgBC,CAAiB,IAAIhB,EAA6B,CAAA,CAAE,GACrE,CAACiB,GAAcC,CAAe,IAAIlB,EAAwC,IAAI,GAC9E,CAACmB,GAAaC,CAAc,IAAIpB,EAAoC,IAAI,GACxE,CAACqB,GAAmBC,EAAoB,IAAItB,EAAsC,IAAI,GACtF,CAACuB,GAAOC,CAAQ,IAAIxB,EAAwB,IAAI,GAGhDyB,IAAqBC,GAA+B,IAAI,GAExDC,IAAWC,GAAY,OAAOC,MAAyB;AAC3D,QAAI;AACF,MAAAL,EAAS,IAAI;AACb,YAAM;AAAA,QACJM;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,MAAA,IACE,MAAM,QAAQ,IAAI;AAAA,QACpBC,EAAS,UAAU,YAAYpC,GAAQ,EAAE,QAAA0B,GAAQ;AAAA,QACjDU,EAAS,UAAU,YAAY,EAAE,QAAAV,GAAQ;AAAA,QACzCU,EAAS,UAAU,UAAU,EAAE,QAAAV,GAAQ;AAAA,QACvCU,EAAS,UAAU,UAAUpC,GAAQ,EAAE,QAAA0B,GAAQ;AAAA,QAC/CU,EAAS,UAAU,wBAAwB,GAAG,EAAE,QAAAV,GAAQ;AAAA,QACxDU,EAAS,UAAU,kBAAkB,GAAG,IAAI,EAAE,QAAAV,GAAQ;AAAA,QACtDU,EAAS,UAAU,kBAAkB,EAAE,QAAAV,GAAQ;AAAA,QAC/CW,EAAwB,eAAerC,GAAQ,EAAE,QAAA0B,GAAQ;AAAA,QACzDW,EAAwB,qBAAqBrC,GAAQ,EAAE,QAAA0B,GAAQ;AAAA,MAAA,CAChE;AAGD,MAAKA,GAAQ,YACXvB,EAAYwB,KAAe,IAAI,GAC/BtB,EAAcuB,KAAa,EAAE,GAC7BrB,EAAYsB,KAAW,EAAE,GACzBpB,EAAUqB,KAAa,EAAE,GACzBnB,EAAkBoB,KAAqB,EAAE,GACzClB,EAAkBmB,MAAa,EAAE,GACjCjB,EAAgBkB,MAAe,IAAI,GACnChB,EAAeiB,MAAa,IAAI,GAChCf,GAAqBgB,MAAiB,IAAI;AAAA,IAE9C,SAASG,GAAc;AAErB,UAAIA,aAAe,SAASA,EAAI,SAAS;AACvC;AAEF,cAAQ,MAAM,kCAAkCA,CAAG;AACnD,YAAMC,IAAaD;AACnB,MAAIC,EAAW,UAAU,WAAW,MAClClB,EAAS,6CAA6C,IAC7CkB,EAAW,UAAU,WAAW,MACzClB,EAAS,wEAAyE,IAElFA,EAAS,2EAA4E;AAAA,IAEzF,UAAA;AACE,MAAKK,GAAQ,YACX9B,EAAW,EAAK,GAChBG,EAAc,EAAK;AAAA,IAEvB;AAAA,EACF,GAAG,CAACC,GAAQR,GAAe,IAAIC,CAAY,CAAC;AAE5C,EAAA+C,GAAU,MAAM;AAEd,IAAAlB,EAAmB,SAAS,MAAA;AAC5B,UAAMmB,IAAa,IAAI,gBAAA;AACvB,WAAAnB,EAAmB,UAAUmB,GAE7BjB,EAASiB,EAAW,MAAM,GAGnB,MAAM;AACX,MAAAA,EAAW,MAAA;AAAA,IACb;AAAA,EACF,GAAG,CAACjB,CAAQ,CAAC;AAEb,QAAMkB,IAAgB,MAAM;AAE1B,IAAApB,EAAmB,SAAS,MAAA;AAC5B,UAAMmB,IAAa,IAAI,gBAAA;AACvB,IAAAnB,EAAmB,UAAUmB,GAE7B1C,EAAc,EAAI,GAClByB,EAASiB,EAAW,MAAM;AAAA,EAC5B;AAEA,SAAI9C,IAEA,gBAAAhC,EAAC,SAAI,WAAU,kDACb,4BAACgF,IAAA,EAAQ,WAAU,wDAAuD,EAAA,CAC5E,IAKF,gBAAAxE,EAAC,OAAA,EAAI,WAAU,aAEb,UAAA;AAAA,IAAA,gBAAAR;AAAA,MAACiF;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,EAAE,OAAOxD,EAAE,cAAc,EAAA;AAAA,UACzB,EAAE,OAAOA,EAAE,iBAAiB,EAAA;AAAA,QAAE;AAAA,MAChC;AAAA,IAAA;AAAA,IAIDgC,KACC,gBAAAjD,EAAC,OAAA,EAAI,WAAU,iHACb,UAAA;AAAA,MAAA,gBAAAR,EAACkF,GAAA,EAAc,WAAU,uDAAA,CAAuD;AAAA,MAChF,gBAAAlF,EAAC,SAAI,WAAU,UACb,4BAAC,KAAA,EAAE,WAAU,8CAA8C,UAAAyD,EAAA,CAAM,EAAA,CACnE;AAAA,MACA,gBAAAzD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS+E;AAAA,UACT,WAAU;AAAA,UAEV,UAAA,gBAAA/E,EAACmF,GAAA,EAAU,WAAU,UAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACjC,GACF;AAAA,IAIF,gBAAA3E,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,yEACZ,UAAA;AAAA,UAAA,gBAAAR,EAACoF,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,UAC1B3D,EAAE,oBAAoB;AAAA,QAAA,GACzB;AAAA,QACA,gBAAAzB,EAAC,KAAA,EAAE,WAAU,qCAAoC,UAAA,gDAAA,CAEjD;AAAA,MAAA,GACF;AAAA,MACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO6B;AAAA,YACP,UAAU,CAACgD,MAAM/C,EAAU,OAAO+C,EAAE,OAAO,KAAK,CAAC;AAAA,YACjD,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAArF,EAAC,UAAA,EAAO,OAAO,GAAG,UAAA,oBAAgB;AAAA,cAClC,gBAAAA,EAAC,UAAA,EAAO,OAAO,IAAI,UAAA,qBAAiB;AAAA,cACpC,gBAAAA,EAAC,UAAA,EAAO,OAAO,IAAI,UAAA,oBAAA,CAAiB;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEtC,gBAAAQ;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASuE;AAAA,YACT,UAAU5C;AAAA,YACV,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAnC,EAACmF,KAAU,WAAW,WAAWhD,IAAa,iBAAiB,EAAE,IAAI;AAAA,cAAE;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEzE,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGA,gBAAA3B,EAAC,OAAA,EAAI,WAAU,wDACb,UAAA;AAAA,MAAA,gBAAAR;AAAA,QAACsF;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO/C,GAAU,cAAc;AAAA,UAC/B,MAAM,gBAAAvC,EAACoF,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,UACjC,OAAM;AAAA,QAAA;AAAA,MAAA;AAAA,MAER,gBAAApF;AAAA,QAACsF;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO/C,GAAU,eAAe;AAAA,UAChC,MAAM,gBAAAvC,EAACuF,GAAA,EAAU,WAAU,UAAA,CAAU;AAAA,UACrC,OAAM;AAAA,QAAA;AAAA,MAAA;AAAA,MAER,gBAAAvF;AAAA,QAACsF;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO/C,GAAU,iBAAiB;AAAA,UAClC,MAAM,gBAAAvC,EAACwF,IAAA,EAAM,WAAU,UAAA,CAAU;AAAA,UACjC,OAAM;AAAA,QAAA;AAAA,MAAA;AAAA,MAER,gBAAAxF;AAAA,QAACsF;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO/C,GAAU,YAAY;AAAA,UAC7B,MAAM,gBAAAvC,EAACyF,IAAA,EAAS,WAAU,UAAA,CAAU;AAAA,UACpC,OAAM;AAAA,UACN,UAAU,GAAGpD,CAAM;AAAA,QAAA;AAAA,MAAA;AAAA,MAErB,gBAAArC;AAAA,QAACsF;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO/C,GAAU,iBAAiB;AAAA,UAClC,MAAM,gBAAAvC,EAAC0F,GAAA,EAAS,WAAU,UAAA,CAAU;AAAA,UACpC,OAAM;AAAA,UACN,UAAU,GAAGrD,CAAM;AAAA,QAAA;AAAA,MAAA;AAAA,MAErB,gBAAArC;AAAA,QAACsF;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,OAAO/C,GAAU,gBAAgB;AAAA,UACjC,MAAM,gBAAAvC,EAACkF,GAAA,EAAc,WAAU,UAAA,CAAU;AAAA,UACzC,QAAQ3C,GAAU,gBAAgB,KAAK,KAAK,QAAQ;AAAA,UACpD,UAAU,GAAGF,CAAM;AAAA,QAAA;AAAA,MAAA;AAAA,IACrB,GACF;AAAA,KAGEY,GAAgB,UAAU,KAAK,KAC/B,gBAAAzC,EAAC,OAAA,EAAI,WAAU,sCACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,2DACZ,UAAA;AAAA,QAAA,gBAAAR,EAACkF,GAAA,EAAc,WAAU,UAAA,CAAU;AAAA,QAAE;AAAA,QAClBjC,GAAgB,UAAU;AAAA,QAAE;AAAA,MAAA,GACjD;AAAA,MACA,gBAAAjD,EAAC,OAAA,EAAI,WAAU,sCACX,WAAAiD,KAAkB,CAAA,GAAI,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC0C,MACvC,gBAAAnF;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UAEL,WAAU;AAAA,UACV,SAAS,MAAMmB,EAAS,yBAAyBgE,EAAM,MAAM,EAAE;AAAA,UAE/D,UAAA;AAAA,YAAA,gBAAAnF,EAAC,OAAA,EACC,UAAA;AAAA,cAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,eAAe,UAAA2F,EAAM,UAAS;AAAA,cAC9C,gBAAA3F,EAAC,QAAA,EAAK,WAAU,6CAA6C,YAAM,MAAA,CAAM;AAAA,YAAA,GAC3E;AAAA,YACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,oCACb,UAAA;AAAA,gBAAAmF,EAAM;AAAA,gBAAe;AAAA,cAAA,GACxB;AAAA,cACA,gBAAAnF,EAAC,QAAA,EAAK,WAAU,wCACb,UAAA;AAAA,gBAAAmF,EAAM,aAAa,UAAU;AAAA,gBAAE;AAAA,cAAA,EAAA,CAClC;AAAA,YAAA,EAAA,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,QAfKA,EAAM;AAAA,MAAA,CAiBd,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IAIF,gBAAAnF,EAAC,OAAA,EAAI,WAAU,yCAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,UAAA,gBAAAR,EAACuF,GAAA,EAAU,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,GAEnC;AAAA,QACA,gBAAAvF,EAAC,SAAI,WAAU,aACX,gBAAc,CAAA,GAAI,IAAI,CAAC4F,MAAS;AAChC,gBAAMC,KAASpD,KAAc,CAAA,GAAI,OAAO,CAACqD,GAAKC,MAAMD,IAAMC,EAAE,OAAO,CAAC,GAC9DjF,IAAa+E,IAAQ,IAAKD,EAAK,QAAQC,IAAS,MAAM;AAC5D,iBACE,gBAAArF,EAAC,OAAA,EAAsB,WAAU,2BAC/B,UAAA;AAAA,YAAA,gBAAAR,EAAC,SAAI,WAAU,gBAAgB,YAAK,WAAW,WAAW,WAAW,WAAA,CAAW;AAAA,YAChF,gBAAAA,EAAC,OAAA,EAAI,WAAU,oEACb,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,OAAO,GAAGc,CAAU;AAAA,kBACpB,iBAAiBS,GAAaqE,EAAK,MAAM,KAAK;AAAA,gBAAA;AAAA,cAChD;AAAA,YAAA,GAEJ;AAAA,YACA,gBAAApF,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,cAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,eAAe,UAAA4F,EAAK,OAAM;AAAA,cAC1C,gBAAApF,EAAC,QAAA,EAAK,WAAU,6CAA4C,UAAA;AAAA,gBAAA;AAAA,gBACxDM,EAAW,QAAQ,CAAC;AAAA,gBAAE;AAAA,cAAA,EAAA,CAC1B;AAAA,YAAA,EAAA,CACF;AAAA,UAAA,EAAA,GAhBQ8E,EAAK,MAiBf;AAAA,QAEJ,CAAC,EAAA,CACH;AAAA,MAAA,GACF;AAAA,MAGA,gBAAApF,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,UAAA,gBAAAR,EAACgG,IAAA,EAAI,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,GAE7B;AAAA,QACA,gBAAAhG,EAAC,OAAA,EAAI,WAAU,aACX,cAAU,UAAU,KAAK,KACxB2C,KAAY,CAAA,GAAI,IAAI,CAACiD,GAAMlF,MAAU;AACpC,gBAAME,IAAW,KAAK,IAAI,IAAI+B,KAAY,CAAA,GAAI,IAAI,CAAAsD,MAAKA,EAAE,KAAK,GAAG,CAAC,GAC5DnF,IAAc8E,EAAK,QAAQhF,IAAY,KACvCsF,IAAS,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AACrE,iBACE,gBAAA1F,EAAC,OAAA,EAAwB,WAAU,2BACjC,UAAA;AAAA,YAAA,gBAAAR,EAAC,SAAI,WAAU,yBAAwB,OAAO4F,EAAK,UAAW,YAAK,SAAA,CAAS;AAAA,YAC5E,gBAAA5F,EAAC,OAAA,EAAI,WAAU,oEACb,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,OAAO,GAAGc,CAAU;AAAA,kBACpB,iBAAiBoF,EAAOxF,IAAQwF,EAAO,MAAM;AAAA,gBAAA;AAAA,cAC/C;AAAA,YAAA,GAEJ;AAAA,YACA,gBAAAlG,EAAC,OAAA,EAAI,WAAU,+BAA+B,YAAK,MAAA,CAAM;AAAA,UAAA,EAAA,GAXjD4F,EAAK,QAYf;AAAA,QAEJ,CAAC,IAED,gBAAA5F,EAAC,SAAI,WAAU,iDAAgD,kCAE/D,EAAA,CAEJ;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,yCAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,UAAA,gBAAAR,EAACmG,IAAA,EAAO,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,GAEhC;AAAA,QACA,gBAAA3F,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,sCAAsC,UAAAuC,GAAU,cAAc,GAAE;AAAA,YAC/E,gBAAAvC,EAAC,OAAA,EAAI,WAAU,wCAAuC,UAAA,QAAA,CAAK;AAAA,UAAA,GAC7D;AAAA,UACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,qCAAqC,UAAAuC,GAAU,oBAAoB,GAAE;AAAA,YACpF,gBAAAvC,EAAC,OAAA,EAAI,WAAU,wCAAuC,UAAA,cAAA,CAAW;AAAA,UAAA,GACnE;AAAA,UACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,oCAAoC,UAAAuC,GAAU,yBAAyB,GAAE;AAAA,YACxF,gBAAAvC,EAAC,OAAA,EAAI,WAAU,wCAAuC,UAAA,sBAAA,CAAmB;AAAA,UAAA,GAC3E;AAAA,UACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,sCAAsC,UAAAmD,GAAc,uBAAuB,GAAE;AAAA,YAC5F,gBAAAnD,EAAC,OAAA,EAAI,WAAU,wCAAuC,UAAA,mBAAA,CAAgB;AAAA,UAAA,EAAA,CACxE;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,UAAA,gBAAAR,EAACC,GAAA,EAAQ,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,GAEjC;AAAA,QACCkD,OAAkBA,EAAa,WAAW,UAAU,KAAK,MAAMA,EAAa,WAAW,UAAU,KAAK,KACrG,gBAAA3C,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,YAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,yDAAwD,UAAA,kBAAc;AAAA,YACpF,gBAAAA,EAAC,OAAA,EAAI,WAAU,aACX,aAAa,aAAa,CAAA,GAAI,IAAI,CAAC4F,MACnC,gBAAApF,EAAC,OAAA,EAAuB,WAAU,6CAChC,UAAA;AAAA,cAAA,gBAAAR,EAAC,QAAA,EAAM,YAAK,QAAA,CAAQ;AAAA,cACpB,gBAAAA,EAAC,QAAA,EAAK,WAAU,eAAe,YAAK,MAAA,CAAM;AAAA,YAAA,KAFlC4F,EAAK,OAGf,CACD,EAAA,CACH;AAAA,UAAA,GACF;AAAA,4BACC,OAAA,EACC,UAAA;AAAA,YAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,iFACZ,UAAA;AAAA,cAAA,gBAAAR,EAACoG,IAAA,EAAM,WAAU,UAAA,CAAU;AAAA,cAAE;AAAA,YAAA,GAC/B;AAAA,8BACC,OAAA,EAAI,WAAU,aACX,WAAAjD,EAAa,WAAW,UAAU,KAAK,KACtCA,EAAa,aAAa,CAAA,GAAI,IAAI,CAACyC,MAClC,gBAAApF,EAAC,OAAA,EAAuB,WAAU,6CAChC,UAAA;AAAA,cAAA,gBAAAR,EAAC,QAAA,EAAM,YAAK,QAAA,CAAQ;AAAA,cACpB,gBAAAA,EAAC,QAAA,EAAK,WAAU,eAAe,YAAK,MAAA,CAAM;AAAA,YAAA,EAAA,GAFlC4F,EAAK,OAGf,CACD,sBAEA,QAAA,EAAK,WAAU,wCAAuC,UAAA,iBAAA,CAAc,EAAA,CAEzE;AAAA,UAAA,EAAA,CACF;AAAA,QAAA,EAAA,CACF,IAEA,gBAAA5F,EAAC,OAAA,EAAI,WAAU,iDAAgD,UAAA,wBAAA,CAE/D;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,GACF;AAAA,IAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,yCAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,UAAA,gBAAAR,EAACC,GAAA,EAAQ,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,GAEjC;AAAA,QACA,gBAAAD,EAACM,IAAA,EAAqB,MAAM+C,EAAA,CAAa;AAAA,MAAA,GAC3C;AAAA,MAGA,gBAAA7C,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,UAAA,gBAAAR,EAAC0F,GAAA,EAAS,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,GAElC;AAAA,QACA,gBAAA1F,EAACgB,IAAA,EAAsB,MAAMuC,EAAA,CAAmB;AAAA,MAAA,EAAA,CAClD;AAAA,IAAA,GACF;AAAA,IAGA,gBAAA/C,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,QAAA,gBAAAR,EAACqG,IAAA,EAAW,WAAU,UAAA,CAAU;AAAA,QAAE;AAAA,QACtBhE;AAAA,QAAO;AAAA,MAAA,GACrB;AAAA,MACA,gBAAArC,EAAC,OAAA,EAAI,WAAU,QACb,UAAA,gBAAAA,EAACsG,MAAW,MAAMzD,KAAU,CAAA,EAAC,CAAG,EAAA,CAClC;AAAA,IAAA,GACF;AAAA,IAGA,gBAAArC,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,8CACZ,UAAA;AAAA,QAAA,gBAAAR,EAACuG,IAAA,EAAM,WAAU,UAAA,CAAU;AAAA,QAAE;AAAA,MAAA,GAE/B;AAAA,OACExD,GAAgB,UAAU,KAAK,IAC/B,gBAAA/C,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA,gBAAAQ,EAAC,SAAA,EAAM,WAAU,UACf,UAAA;AAAA,QAAA,gBAAAR,EAAC,SAAA,EACC,UAAA,gBAAAQ,EAAC,MAAA,EAAG,WAAU,yCACZ,UAAA;AAAA,UAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,6BAA4B,UAAA,eAAW;AAAA,UACrD,gBAAAA,EAAC,MAAA,EAAG,WAAU,8BAA6B,UAAA,QAAA,CAAK;AAAA,QAAA,EAAA,CAClD,EAAA,CACF;AAAA,0BACC,SAAA,EACG,WAAA+C,KAAkB,IAAI,IAAI,CAACyD,MAC3B,gBAAAhG;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAU;AAAA,YACV,SAAS,MAAMmB,EAAS,yBAAyB6E,EAAQ,MAAM,EAAE;AAAA,YAEjE,UAAA;AAAA,cAAA,gBAAAxG,EAAC,MAAA,EAAG,WAAU,mBAAmB,UAAAwG,EAAQ,UAAS;AAAA,cAClD,gBAAAxG,EAAC,MAAA,EAAG,WAAU,kBACZ,UAAA,gBAAAA,EAAC,UAAK,WAAU,8GACb,UAAAwG,EAAQ,SAAA,CACX,EAAA,CACF;AAAA,YAAA;AAAA,UAAA;AAAA,UATKA,EAAQ,SAASA,EAAQ;AAAA,QAAA,CAWjC,EAAA,CACH;AAAA,MAAA,GACF,GACF,IAEA,gBAAAxG,EAAC,OAAA,EAAI,WAAU,iDAAgD,UAAA,wBAAA,CAE/D;AAAA,IAAA,EAAA,CAEJ;AAAA,EAAA,GACF;AAEJ;AAEA,SAASsF,EAAQ;AAAA,EACf,OAAAmB;AAAA,EACA,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AACF,GAMG;AAQD,2BACG,OAAA,EAAI,WAAW,mBARG;AAAA,IACnB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,EAAA,EAI2CD,CAAK,CAAC,IACpD,UAAA;AAAA,IAAA,gBAAApG,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,kCAAkC,UAAAyG,GAAM;AAAA,MACvDE;AAAA,IAAA,GACH;AAAA,IACA,gBAAA3G,EAAC,OAAA,EAAI,WAAU,sBAAsB,UAAA0G,GAAM;AAAA,IAC1CG,KAAY,gBAAA7G,EAAC,OAAA,EAAI,WAAU,2BAA2B,UAAA6G,EAAA,CAAS;AAAA,EAAA,GAClE;AAEJ;AAEA,SAASP,GAAW,EAAE,MAAA/F,KAAkC;AACtD,MAAIA,EAAK,WAAW;AAClB,WACE,gBAAAP,EAAC,OAAA,EAAI,WAAU,wEAAuE,UAAA,wCAEtF;AAIJ,QAAM8G,IAAW,KAAK,IAAI,GAAGvG,EAAK,QAAQ,CAACwG,MAAM,CAACA,EAAE,UAAUA,EAAE,MAAM,CAAC,GAAG,CAAC;AAE3E,SACE,gBAAAvG,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,8BAAA,CAA8B;AAAA,QAC7C,gBAAAA,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,wBAAA,CAAqB;AAAA,MAAA,GACjD;AAAA,MACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,+BAAA,CAA+B;AAAA,QAC9C,gBAAAA,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,aAAA,CAAU;AAAA,MAAA,EAAA,CACtC;AAAA,IAAA,GACF;AAAA,IACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,oDACZ,UAAAO,EAAK,IAAI,CAACqF,MACT,gBAAApF,EAAC,OAAA,EAAyB,WAAU,oCAClC,UAAA;AAAA,MAAA,gBAAAR;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,QAAQ,GAAI4F,EAAK,WAAWkB,IAAY,GAAG;AAAA,YAC3C,WAAWlB,EAAK,WAAW,IAAI,QAAQ;AAAA,UAAA;AAAA,UAEzC,OAAO,aAAaA,EAAK,QAAQ;AAAA,QAAA;AAAA,MAAA;AAAA,MAEnC,gBAAA5F;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,QAAQ,GAAI4F,EAAK,SAASkB,IAAY,GAAG;AAAA,YACzC,WAAWlB,EAAK,SAAS,IAAI,QAAQ;AAAA,UAAA;AAAA,UAEvC,OAAO,eAAeA,EAAK,MAAM;AAAA,QAAA;AAAA,MAAA;AAAA,IACnC,EAAA,GAhBQ,GAAGA,EAAK,IAAI,EAiBtB,CACD,EAAA,CACH;AAAA,IACA,gBAAApF,EAAC,OAAA,EAAI,WAAU,kEACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,QAAA,EAAM,UAAAO,EAAK,CAAC,KAAK,IAAI,KAAKA,EAAK,CAAC,EAAE,IAAI,EAAE,mBAAmB,OAAO,EAAA,CAAE;AAAA,wBACpE,QAAA,EAAM,UAAAA,EAAK,GAAG,EAAE,KAAK,IAAI,KAAKA,EAAK,GAAG,EAAE,EAAG,IAAI,EAAE,mBAAmB,OAAO,EAAA,CAAE;AAAA,IAAA,EAAA,CAChF;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),c=require("react"),_=require("react-router-dom"),ee=require("react-i18next"),a=require("lucide-react"),h=require("./index-2wUhd9Lu.js"),D=require("./applicationAnalyticsApi-Ce_1qOk-.js"),$={Desktop:e.jsx(a.Monitor,{className:"w-4 h-4"}),Mobile:e.jsx(a.Smartphone,{className:"w-4 h-4"}),Tablet:e.jsx(a.Tablet,{className:"w-4 h-4"}),Unknown:e.jsx(a.Monitor,{className:"w-4 h-4 opacity-50"})},M=["#3b82f6","#22c55e","#f59e0b","#6b7280"],P=["#3b82f6","#8b5cf6","#22c55e","#f59e0b","#ef4444"],se=({data:t})=>!t||!t.byDeviceType?.length&&!t.byBrowser?.length?e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"No device data available"}):e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"By Device Type"}),e.jsx("div",{className:"space-y-3",children:t.byDeviceType.map((l,n)=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 w-28",children:[$[l.deviceType]||$.Unknown,e.jsx("span",{className:"text-sm",children:l.deviceType})]}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${l.percentage}%`,backgroundColor:M[n%M.length]}})}),e.jsxs("div",{className:"w-20 text-right",children:[e.jsx("span",{className:"font-medium",children:l.count}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)] ml-1",children:["(",l.percentage.toFixed(1),"%)"]})]})]},l.deviceType))})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"By Browser"}),e.jsx("div",{className:"space-y-3",children:t.byBrowser.map((l,n)=>{const r=Math.max(...t.byBrowser.map(u=>u.count),1),d=l.count/r*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:l.browser}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${d}%`,backgroundColor:P[n%P.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium",children:l.count})]},l.browser)})})]})]}),B=["#ef4444","#f59e0b","#22c55e","#3b82f6"],te=({data:t})=>{if(!t)return e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"No engagement data available"});const l=Math.max(...t.sessionDistribution.map(r=>r.count),1),n=Math.max(...t.peakUsageHours.map(r=>r.accessCount),1);return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"Session Duration Distribution"}),e.jsx("div",{className:"space-y-3",children:t.sessionDistribution.map((r,d)=>{const u=r.count/l*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-20 text-sm",children:r.label}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${u}%`,backgroundColor:B[d%B.length]}})}),e.jsxs("div",{className:"w-16 text-right",children:[e.jsx("span",{className:"font-medium",children:r.count}),e.jsx("span",{className:"text-xs text-[var(--text-secondary)] ml-1",children:"sessions"})]})]},r.bucket)})})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"Peak Usage Hours"}),e.jsx("div",{className:"flex items-end gap-1 h-32 overflow-x-auto pb-2",children:t.peakUsageHours.map(r=>{const d=r.accessCount/n*100;return e.jsxs("div",{className:"flex-1 min-w-[20px] flex flex-col items-center gap-1",children:[e.jsx("div",{className:"w-full bg-gradient-to-t from-blue-500 to-cyan-500 rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${d}%`,minHeight:r.accessCount>0?"4px":"0"},title:`${r.hour}h: ${r.accessCount} accesses`}),r.hour%3===0&&e.jsxs("span",{className:"text-xs text-[var(--text-secondary)]",children:[r.hour,"h"]})]},r.hour)})})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4 pt-4 border-t border-[var(--border-color)]",children:[e.jsxs("div",{className:"text-center p-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-2xl font-bold text-blue-600",children:t.dailyActiveUsers}),e.jsx("div",{className:"text-xs text-[var(--text-secondary)] mt-1",children:"Daily Active Users"})]}),e.jsxs("div",{className:"text-center p-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:"text-2xl font-bold text-green-600",children:[(t.retentionRate*100).toFixed(1),"%"]}),e.jsx("div",{className:"text-xs text-[var(--text-secondary)] mt-1",children:"Retention Rate"})]})]})]})},ae={Active:"#22c55e",Inactive:"#ef4444"};function re(){const{t}=ee.useTranslation(["admin","navigation"]),l=_.useNavigate(),{currentTenant:n,isGlobalView:r}=h.useTenant(),[d,u]=c.useState(!0),[C,S]=c.useState(!1),[o,I]=c.useState(30),[x,E]=c.useState(null),[k,L]=c.useState([]),[f,q]=c.useState([]),[H,F]=c.useState([]),[R,V]=c.useState([]),[y,z]=c.useState([]),[v,O]=c.useState(null),[G,K]=c.useState(null),[X,J]=c.useState(null),[U,p]=c.useState(null),N=c.useRef(null),w=c.useCallback(async s=>{try{p(null);const[i,m,b,g,A,Q,W,Y,Z]=await Promise.all([h.adminApi.dashboard.getOverview(o,{signal:s}),h.adminApi.dashboard.getByStatus({signal:s}),h.adminApi.dashboard.getByRole({signal:s}),h.adminApi.dashboard.getTrends(o,{signal:s}),h.adminApi.dashboard.getLatestActiveSessions(5,{signal:s}),h.adminApi.dashboard.getSecurityAlerts(3,24,{signal:s}),h.adminApi.dashboard.getActiveSessions({signal:s}),D.applicationAnalyticsApi.getDeviceStats(o,{signal:s}),D.applicationAnalyticsApi.getEngagementMetrics(o,{signal:s})]);s?.aborted||(E(i??null),L(m??[]),q(b??[]),F(g??[]),V(A??[]),z(Q??[]),O(W??null),K(Y??null),J(Z??null))}catch(i){if(i instanceof Error&&i.name==="CanceledError")return;console.error("Failed to load dashboard data:",i);const m=i;m.response?.status===401?p("Session expirée. Veuillez vous reconnecter."):m.response?.status===403?p("Vous n'avez pas les permissions nécessaires pour accéder au dashboard."):p("Erreur lors du chargement des données. Vérifiez que l'API est accessible.")}finally{s?.aborted||(u(!1),S(!1))}},[o,n?.id,r]);c.useEffect(()=>{N.current?.abort();const s=new AbortController;return N.current=s,w(s.signal),()=>{s.abort()}},[w]);const T=()=>{N.current?.abort();const s=new AbortController;N.current=s,S(!0),w(s.signal)};return d?e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(a.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-primary-600)]"})}):e.jsxs("div",{className:"space-y-6",children:[e.jsx(h.Breadcrumb,{items:[{label:t("header.title")},{label:t("dashboard.title")}]}),U&&e.jsxs("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",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-red-800 dark:text-red-200 font-medium",children:U})}),e.jsx("button",{onClick:T,className:"text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200",children:e.jsx(a.RefreshCw,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-[var(--text-primary)] flex items-center gap-2",children:[e.jsx(a.Users,{className:"w-6 h-6"}),t("admin:header.title")]}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:"Vue d'ensemble de la gestion des utilisateurs"})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("select",{value:o,onChange:s=>I(Number(s.target.value)),className:"input",children:[e.jsx("option",{value:7,children:"7 derniers jours"}),e.jsx("option",{value:30,children:"30 derniers jours"}),e.jsx("option",{value:90,children:"90 derniers jours"})]}),e.jsxs("button",{onClick:T,disabled:C,className:"btn btn-secondary flex items-center gap-2",children:[e.jsx(a.RefreshCw,{className:`w-4 h-4 ${C?"animate-spin":""}`}),"Actualiser"]})]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4",children:[e.jsx(j,{title:"Total Utilisateurs",value:x?.totalUsers??0,icon:e.jsx(a.Users,{className:"w-5 h-5"}),color:"blue"}),e.jsx(j,{title:"Actifs",value:x?.activeUsers??0,icon:e.jsx(a.UserCheck,{className:"w-5 h-5"}),color:"green"}),e.jsx(j,{title:"Inactifs",value:x?.inactiveUsers??0,icon:e.jsx(a.UserX,{className:"w-5 h-5"}),color:"red"}),e.jsx(j,{title:"Nouveaux",value:x?.newUsers??0,icon:e.jsx(a.UserPlus,{className:"w-5 h-5"}),color:"blue",subtitle:`${o} derniers jours`}),e.jsx(j,{title:"Sessions",value:x?.totalSessions??0,icon:e.jsx(a.Activity,{className:"w-5 h-5"}),color:"green",subtitle:`${o} derniers jours`}),e.jsx(j,{title:"Connexions Echouées",value:x?.failedLogins??0,icon:e.jsx(a.AlertTriangle,{className:"w-5 h-5"}),color:(x?.failedLogins??0)>10?"red":"yellow",subtitle:`${o} derniers jours`})]}),(y?.length??0)>0&&e.jsxs("div",{className:"card p-4 border-l-4 border-red-500",children:[e.jsxs("h3",{className:"font-semibold text-red-600 flex items-center gap-2 mb-3",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5"}),"Alertes Sécurité (",y?.length??0,")"]}),e.jsx("div",{className:"space-y-2 max-h-40 overflow-y-auto",children:(y??[]).slice(0,5).map(s=>e.jsxs("button",{type:"button",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",onClick:()=>l(`/administration/users/${s.userId}`),children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:s.fullName}),e.jsx("span",{className:"ml-2 text-sm text-[var(--text-secondary)]",children:s.email})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"text-xs text-red-600 font-medium",children:[s.failedAttempts," échecs"]}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)]",children:[s.ipAddresses?.length??0," IP(s)"]})]})]},s.userId))})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.UserCheck,{className:"w-5 h-5"}),"Utilisateurs par Statut"]}),e.jsx("div",{className:"space-y-3",children:(k??[]).map(s=>{const i=(k??[]).reduce((b,g)=>b+g.count,0),m=i>0?s.count/i*100:0;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:s.status==="Active"?"Actifs":"Inactifs"}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${m}%`,backgroundColor:ae[s.status]||"#6b7280"}})}),e.jsxs("div",{className:"w-20 text-right",children:[e.jsx("span",{className:"font-medium",children:s.count}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)] ml-1",children:["(",m.toFixed(0),"%)"]})]})]},s.status)})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Key,{className:"w-5 h-5"}),"Utilisateurs par Rôle"]}),e.jsx("div",{className:"space-y-3",children:(f?.length??0)>0?(f??[]).map((s,i)=>{const m=Math.max(...(f??[]).map(A=>A.count),1),b=s.count/m*100,g=["#3b82f6","#8b5cf6","#22c55e","#f59e0b","#ef4444"];return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-32 text-sm truncate",title:s.roleName,children:s.roleName}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${b}%`,backgroundColor:g[i%g.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium",children:s.count})]},s.roleName)}):e.jsx("div",{className:"text-center py-4 text-[var(--text-secondary)]",children:"Aucun rôle configuré"})})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Shield,{className:"w-5 h-5"}),"Configuration Système"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-purple-600",children:x?.totalRoles??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Rôles"})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-green-600",children:x?.totalPermissions??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Permissions"})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-blue-600",children:x?.usersLoggedInRecently??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Connectés récemment"})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-orange-600",children:v?.totalActiveSessions??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Sessions actives"})]})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Monitor,{className:"w-5 h-5"}),"Sessions Actives"]}),v&&((v.byBrowser?.length??0)>0||(v.byCountry?.length??0)>0)?e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-2",children:"Par Navigateur"}),e.jsx("div",{className:"space-y-2",children:(v.byBrowser??[]).map(s=>e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{children:s.browser}),e.jsx("span",{className:"font-medium",children:s.count})]},s.browser))})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-2 flex items-center gap-1",children:[e.jsx(a.Globe,{className:"w-4 h-4"})," Par Pays"]}),e.jsx("div",{className:"space-y-2",children:(v.byCountry?.length??0)>0?(v.byCountry??[]).map(s=>e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{children:s.country}),e.jsx("span",{className:"font-medium",children:s.count})]},s.country)):e.jsx("span",{className:"text-[var(--text-secondary)] text-sm",children:"Non disponible"})})]})]}):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"Aucune session active"})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Monitor,{className:"w-5 h-5"}),"Appareils & Navigateurs"]}),e.jsx(se,{data:G})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Activity,{className:"w-5 h-5"}),"Engagement Utilisateurs"]}),e.jsx(te,{data:X})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.TrendingUp,{className:"w-5 h-5"}),"Tendances (",o," derniers jours)"]}),e.jsx("div",{className:"h-64",children:e.jsx(le,{data:H??[]})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Clock,{className:"w-5 h-5"}),"Dernières Sessions Actives"]}),(R?.length??0)>0?e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[var(--border-color)]",children:[e.jsx("th",{className:"text-left p-3 font-medium",children:"Utilisateur"}),e.jsx("th",{className:"text-right p-3 font-medium",children:"Durée"})]})}),e.jsx("tbody",{children:(R??[]).map(s=>e.jsxs("tr",{className:"border-b border-[var(--border-color)] hover:bg-[var(--bg-secondary)] cursor-pointer",onClick:()=>l(`/administration/users/${s.userId}`),children:[e.jsx("td",{className:"p-3 font-medium",children:s.fullName}),e.jsx("td",{className:"p-3 text-right",children:e.jsx("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",children:s.duration})})]},s.userId+s.loginAt))})]})}):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"Aucune session active"})]})]})}function j({title:t,value:l,icon:n,color:r,subtitle:d}){const u={blue:"bg-blue-50 text-blue-600 border-blue-200 dark:bg-blue-900/20 dark:border-blue-800",green:"bg-green-50 text-green-600 border-green-200 dark:bg-green-900/20 dark:border-green-800",yellow:"bg-yellow-50 text-yellow-600 border-yellow-200 dark:bg-yellow-900/20 dark:border-yellow-800",red:"bg-red-50 text-red-600 border-red-200 dark:bg-red-900/20 dark:border-red-800"};return e.jsxs("div",{className:`card p-4 border ${u[r]}`,children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium opacity-80",children:t}),n]}),e.jsx("div",{className:"text-2xl font-bold",children:l}),d&&e.jsx("div",{className:"text-xs opacity-70 mt-1",children:d})]})}function le({data:t}){if(t.length===0)return e.jsx("div",{className:"flex items-center justify-center h-full text-[var(--text-secondary)]",children:"Aucune donnée de tendance disponible"});const l=Math.max(...t.flatMap(n=>[n.newUsers,n.logins]),1);return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"flex items-center gap-4 mb-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-blue-500"}),e.jsx("span",{className:"text-sm",children:"Nouveaux utilisateurs"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-green-500"}),e.jsx("span",{className:"text-sm",children:"Connexions"})]})]}),e.jsx("div",{className:"flex-1 flex items-end gap-1 overflow-x-auto pb-4",children:t.map(n=>e.jsxs("div",{className:"flex-1 min-w-[20px] flex gap-0.5",children:[e.jsx("div",{className:"flex-1 bg-blue-500 rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${n.newUsers/l*100}%`,minHeight:n.newUsers>0?"4px":"0"},title:`Nouveaux: ${n.newUsers}`}),e.jsx("div",{className:"flex-1 bg-green-500 rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${n.logins/l*100}%`,minHeight:n.logins>0?"4px":"0"},title:`Connexions: ${n.logins}`})]},`${n.date}`))}),e.jsxs("div",{className:"flex justify-between text-xs text-[var(--text-secondary)] mt-2",children:[e.jsx("span",{children:t[0]&&new Date(t[0].date).toLocaleDateString("fr-FR")}),e.jsx("span",{children:t.at(-1)&&new Date(t.at(-1).date).toLocaleDateString("fr-FR")})]})]})}exports.AdminDashboardPage=re;
|
|
2
|
-
//# sourceMappingURL=DashboardPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),c=require("react"),_=require("react-router-dom"),ee=require("react-i18next"),a=require("lucide-react"),h=require("./index-IgLVXPg8.js"),D=require("./applicationAnalyticsApi-CLBqRPfN.js"),$={Desktop:e.jsx(a.Monitor,{className:"w-4 h-4"}),Mobile:e.jsx(a.Smartphone,{className:"w-4 h-4"}),Tablet:e.jsx(a.Tablet,{className:"w-4 h-4"}),Unknown:e.jsx(a.Monitor,{className:"w-4 h-4 opacity-50"})},M=["#3b82f6","#22c55e","#f59e0b","#6b7280"],P=["#3b82f6","#8b5cf6","#22c55e","#f59e0b","#ef4444"],se=({data:t})=>!t||!t.byDeviceType?.length&&!t.byBrowser?.length?e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"No device data available"}):e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"By Device Type"}),e.jsx("div",{className:"space-y-3",children:t.byDeviceType.map((l,n)=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 w-28",children:[$[l.deviceType]||$.Unknown,e.jsx("span",{className:"text-sm",children:l.deviceType})]}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${l.percentage}%`,backgroundColor:M[n%M.length]}})}),e.jsxs("div",{className:"w-20 text-right",children:[e.jsx("span",{className:"font-medium",children:l.count}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)] ml-1",children:["(",l.percentage.toFixed(1),"%)"]})]})]},l.deviceType))})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"By Browser"}),e.jsx("div",{className:"space-y-3",children:t.byBrowser.map((l,n)=>{const r=Math.max(...t.byBrowser.map(u=>u.count),1),d=l.count/r*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:l.browser}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${d}%`,backgroundColor:P[n%P.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium",children:l.count})]},l.browser)})})]})]}),B=["#ef4444","#f59e0b","#22c55e","#3b82f6"],te=({data:t})=>{if(!t)return e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"No engagement data available"});const l=Math.max(...t.sessionDistribution.map(r=>r.count),1),n=Math.max(...t.peakUsageHours.map(r=>r.accessCount),1);return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"Session Duration Distribution"}),e.jsx("div",{className:"space-y-3",children:t.sessionDistribution.map((r,d)=>{const u=r.count/l*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-20 text-sm",children:r.label}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${u}%`,backgroundColor:B[d%B.length]}})}),e.jsxs("div",{className:"w-16 text-right",children:[e.jsx("span",{className:"font-medium",children:r.count}),e.jsx("span",{className:"text-xs text-[var(--text-secondary)] ml-1",children:"sessions"})]})]},r.bucket)})})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:"Peak Usage Hours"}),e.jsx("div",{className:"flex items-end gap-1 h-32 overflow-x-auto pb-2",children:t.peakUsageHours.map(r=>{const d=r.accessCount/n*100;return e.jsxs("div",{className:"flex-1 min-w-[20px] flex flex-col items-center gap-1",children:[e.jsx("div",{className:"w-full bg-gradient-to-t from-blue-500 to-cyan-500 rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${d}%`,minHeight:r.accessCount>0?"4px":"0"},title:`${r.hour}h: ${r.accessCount} accesses`}),r.hour%3===0&&e.jsxs("span",{className:"text-xs text-[var(--text-secondary)]",children:[r.hour,"h"]})]},r.hour)})})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4 pt-4 border-t border-[var(--border-color)]",children:[e.jsxs("div",{className:"text-center p-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-2xl font-bold text-blue-600",children:t.dailyActiveUsers}),e.jsx("div",{className:"text-xs text-[var(--text-secondary)] mt-1",children:"Daily Active Users"})]}),e.jsxs("div",{className:"text-center p-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:"text-2xl font-bold text-green-600",children:[(t.retentionRate*100).toFixed(1),"%"]}),e.jsx("div",{className:"text-xs text-[var(--text-secondary)] mt-1",children:"Retention Rate"})]})]})]})},ae={Active:"#22c55e",Inactive:"#ef4444"};function re(){const{t}=ee.useTranslation(["admin","navigation"]),l=_.useNavigate(),{currentTenant:n,isGlobalView:r}=h.useTenant(),[d,u]=c.useState(!0),[C,S]=c.useState(!1),[o,I]=c.useState(30),[x,E]=c.useState(null),[k,L]=c.useState([]),[f,q]=c.useState([]),[H,F]=c.useState([]),[R,V]=c.useState([]),[y,z]=c.useState([]),[v,O]=c.useState(null),[G,K]=c.useState(null),[X,J]=c.useState(null),[U,p]=c.useState(null),N=c.useRef(null),w=c.useCallback(async s=>{try{p(null);const[i,m,b,g,A,Q,W,Y,Z]=await Promise.all([h.adminApi.dashboard.getOverview(o,{signal:s}),h.adminApi.dashboard.getByStatus({signal:s}),h.adminApi.dashboard.getByRole({signal:s}),h.adminApi.dashboard.getTrends(o,{signal:s}),h.adminApi.dashboard.getLatestActiveSessions(5,{signal:s}),h.adminApi.dashboard.getSecurityAlerts(3,24,{signal:s}),h.adminApi.dashboard.getActiveSessions({signal:s}),D.applicationAnalyticsApi.getDeviceStats(o,{signal:s}),D.applicationAnalyticsApi.getEngagementMetrics(o,{signal:s})]);s?.aborted||(E(i??null),L(m??[]),q(b??[]),F(g??[]),V(A??[]),z(Q??[]),O(W??null),K(Y??null),J(Z??null))}catch(i){if(i instanceof Error&&i.name==="CanceledError")return;console.error("Failed to load dashboard data:",i);const m=i;m.response?.status===401?p("Session expirée. Veuillez vous reconnecter."):m.response?.status===403?p("Vous n'avez pas les permissions nécessaires pour accéder au dashboard."):p("Erreur lors du chargement des données. Vérifiez que l'API est accessible.")}finally{s?.aborted||(u(!1),S(!1))}},[o,n?.id,r]);c.useEffect(()=>{N.current?.abort();const s=new AbortController;return N.current=s,w(s.signal),()=>{s.abort()}},[w]);const T=()=>{N.current?.abort();const s=new AbortController;N.current=s,S(!0),w(s.signal)};return d?e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(a.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-primary-600)]"})}):e.jsxs("div",{className:"space-y-6",children:[e.jsx(h.Breadcrumb,{items:[{label:t("header.title")},{label:t("dashboard.title")}]}),U&&e.jsxs("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",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-red-800 dark:text-red-200 font-medium",children:U})}),e.jsx("button",{onClick:T,className:"text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200",children:e.jsx(a.RefreshCw,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-[var(--text-primary)] flex items-center gap-2",children:[e.jsx(a.Users,{className:"w-6 h-6"}),t("admin:header.title")]}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:"Vue d'ensemble de la gestion des utilisateurs"})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("select",{value:o,onChange:s=>I(Number(s.target.value)),className:"input",children:[e.jsx("option",{value:7,children:"7 derniers jours"}),e.jsx("option",{value:30,children:"30 derniers jours"}),e.jsx("option",{value:90,children:"90 derniers jours"})]}),e.jsxs("button",{onClick:T,disabled:C,className:"btn btn-secondary flex items-center gap-2",children:[e.jsx(a.RefreshCw,{className:`w-4 h-4 ${C?"animate-spin":""}`}),"Actualiser"]})]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4",children:[e.jsx(j,{title:"Total Utilisateurs",value:x?.totalUsers??0,icon:e.jsx(a.Users,{className:"w-5 h-5"}),color:"blue"}),e.jsx(j,{title:"Actifs",value:x?.activeUsers??0,icon:e.jsx(a.UserCheck,{className:"w-5 h-5"}),color:"green"}),e.jsx(j,{title:"Inactifs",value:x?.inactiveUsers??0,icon:e.jsx(a.UserX,{className:"w-5 h-5"}),color:"red"}),e.jsx(j,{title:"Nouveaux",value:x?.newUsers??0,icon:e.jsx(a.UserPlus,{className:"w-5 h-5"}),color:"blue",subtitle:`${o} derniers jours`}),e.jsx(j,{title:"Sessions",value:x?.totalSessions??0,icon:e.jsx(a.Activity,{className:"w-5 h-5"}),color:"green",subtitle:`${o} derniers jours`}),e.jsx(j,{title:"Connexions Echouées",value:x?.failedLogins??0,icon:e.jsx(a.AlertTriangle,{className:"w-5 h-5"}),color:(x?.failedLogins??0)>10?"red":"yellow",subtitle:`${o} derniers jours`})]}),(y?.length??0)>0&&e.jsxs("div",{className:"card p-4 border-l-4 border-red-500",children:[e.jsxs("h3",{className:"font-semibold text-red-600 flex items-center gap-2 mb-3",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5"}),"Alertes Sécurité (",y?.length??0,")"]}),e.jsx("div",{className:"space-y-2 max-h-40 overflow-y-auto",children:(y??[]).slice(0,5).map(s=>e.jsxs("button",{type:"button",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",onClick:()=>l(`/administration/users/${s.userId}`),children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:s.fullName}),e.jsx("span",{className:"ml-2 text-sm text-[var(--text-secondary)]",children:s.email})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"text-xs text-red-600 font-medium",children:[s.failedAttempts," échecs"]}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)]",children:[s.ipAddresses?.length??0," IP(s)"]})]})]},s.userId))})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.UserCheck,{className:"w-5 h-5"}),"Utilisateurs par Statut"]}),e.jsx("div",{className:"space-y-3",children:(k??[]).map(s=>{const i=(k??[]).reduce((b,g)=>b+g.count,0),m=i>0?s.count/i*100:0;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:s.status==="Active"?"Actifs":"Inactifs"}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${m}%`,backgroundColor:ae[s.status]||"#6b7280"}})}),e.jsxs("div",{className:"w-20 text-right",children:[e.jsx("span",{className:"font-medium",children:s.count}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)] ml-1",children:["(",m.toFixed(0),"%)"]})]})]},s.status)})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Key,{className:"w-5 h-5"}),"Utilisateurs par Rôle"]}),e.jsx("div",{className:"space-y-3",children:(f?.length??0)>0?(f??[]).map((s,i)=>{const m=Math.max(...(f??[]).map(A=>A.count),1),b=s.count/m*100,g=["#3b82f6","#8b5cf6","#22c55e","#f59e0b","#ef4444"];return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-32 text-sm truncate",title:s.roleName,children:s.roleName}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${b}%`,backgroundColor:g[i%g.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium",children:s.count})]},s.roleName)}):e.jsx("div",{className:"text-center py-4 text-[var(--text-secondary)]",children:"Aucun rôle configuré"})})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Shield,{className:"w-5 h-5"}),"Configuration Système"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-purple-600",children:x?.totalRoles??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Rôles"})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-green-600",children:x?.totalPermissions??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Permissions"})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-blue-600",children:x?.usersLoggedInRecently??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Connectés récemment"})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-orange-600",children:v?.totalActiveSessions??0}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:"Sessions actives"})]})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Monitor,{className:"w-5 h-5"}),"Sessions Actives"]}),v&&((v.byBrowser?.length??0)>0||(v.byCountry?.length??0)>0)?e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-2",children:"Par Navigateur"}),e.jsx("div",{className:"space-y-2",children:(v.byBrowser??[]).map(s=>e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{children:s.browser}),e.jsx("span",{className:"font-medium",children:s.count})]},s.browser))})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-2 flex items-center gap-1",children:[e.jsx(a.Globe,{className:"w-4 h-4"})," Par Pays"]}),e.jsx("div",{className:"space-y-2",children:(v.byCountry?.length??0)>0?(v.byCountry??[]).map(s=>e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{children:s.country}),e.jsx("span",{className:"font-medium",children:s.count})]},s.country)):e.jsx("span",{className:"text-[var(--text-secondary)] text-sm",children:"Non disponible"})})]})]}):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"Aucune session active"})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Monitor,{className:"w-5 h-5"}),"Appareils & Navigateurs"]}),e.jsx(se,{data:G})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Activity,{className:"w-5 h-5"}),"Engagement Utilisateurs"]}),e.jsx(te,{data:X})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.TrendingUp,{className:"w-5 h-5"}),"Tendances (",o," derniers jours)"]}),e.jsx("div",{className:"h-64",children:e.jsx(le,{data:H??[]})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Clock,{className:"w-5 h-5"}),"Dernières Sessions Actives"]}),(R?.length??0)>0?e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[var(--border-color)]",children:[e.jsx("th",{className:"text-left p-3 font-medium",children:"Utilisateur"}),e.jsx("th",{className:"text-right p-3 font-medium",children:"Durée"})]})}),e.jsx("tbody",{children:(R??[]).map(s=>e.jsxs("tr",{className:"border-b border-[var(--border-color)] hover:bg-[var(--bg-secondary)] cursor-pointer",onClick:()=>l(`/administration/users/${s.userId}`),children:[e.jsx("td",{className:"p-3 font-medium",children:s.fullName}),e.jsx("td",{className:"p-3 text-right",children:e.jsx("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",children:s.duration})})]},s.userId+s.loginAt))})]})}):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:"Aucune session active"})]})]})}function j({title:t,value:l,icon:n,color:r,subtitle:d}){const u={blue:"bg-blue-50 text-blue-600 border-blue-200 dark:bg-blue-900/20 dark:border-blue-800",green:"bg-green-50 text-green-600 border-green-200 dark:bg-green-900/20 dark:border-green-800",yellow:"bg-yellow-50 text-yellow-600 border-yellow-200 dark:bg-yellow-900/20 dark:border-yellow-800",red:"bg-red-50 text-red-600 border-red-200 dark:bg-red-900/20 dark:border-red-800"};return e.jsxs("div",{className:`card p-4 border ${u[r]}`,children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium opacity-80",children:t}),n]}),e.jsx("div",{className:"text-2xl font-bold",children:l}),d&&e.jsx("div",{className:"text-xs opacity-70 mt-1",children:d})]})}function le({data:t}){if(t.length===0)return e.jsx("div",{className:"flex items-center justify-center h-full text-[var(--text-secondary)]",children:"Aucune donnée de tendance disponible"});const l=Math.max(...t.flatMap(n=>[n.newUsers,n.logins]),1);return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"flex items-center gap-4 mb-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-blue-500"}),e.jsx("span",{className:"text-sm",children:"Nouveaux utilisateurs"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-green-500"}),e.jsx("span",{className:"text-sm",children:"Connexions"})]})]}),e.jsx("div",{className:"flex-1 flex items-end gap-1 overflow-x-auto pb-4",children:t.map(n=>e.jsxs("div",{className:"flex-1 min-w-[20px] flex gap-0.5",children:[e.jsx("div",{className:"flex-1 bg-blue-500 rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${n.newUsers/l*100}%`,minHeight:n.newUsers>0?"4px":"0"},title:`Nouveaux: ${n.newUsers}`}),e.jsx("div",{className:"flex-1 bg-green-500 rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${n.logins/l*100}%`,minHeight:n.logins>0?"4px":"0"},title:`Connexions: ${n.logins}`})]},`${n.date}`))}),e.jsxs("div",{className:"flex justify-between text-xs text-[var(--text-secondary)] mt-2",children:[e.jsx("span",{children:t[0]&&new Date(t[0].date).toLocaleDateString("fr-FR")}),e.jsx("span",{children:t.at(-1)&&new Date(t.at(-1).date).toLocaleDateString("fr-FR")})]})]})}exports.AdminDashboardPage=re;
|
|
2
|
+
//# sourceMappingURL=DashboardPage-CfKZHiSj.js.map
|