@atlashub/smartstack 3.39.0-preview.1049 → 3.40.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-DgqyaZwI.js → AgentSkillsPage-BS_W2KTh.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-DgqyaZwI.js.map → AgentSkillsPage-BS_W2KTh.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js → AgentSkillsPage-CmDFLnp7.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js.map → AgentSkillsPage-CmDFLnp7.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js → AgentWorkloadPage-C8IvYfhT.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js.map → AgentWorkloadPage-C8IvYfhT.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js → AgentWorkloadPage-JXsQbwuM.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js.map → AgentWorkloadPage-JXsQbwuM.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js → ApiCatalogDetailPage-CYOt34Vy.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js.map → ApiCatalogDetailPage-CYOt34Vy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js → ApiCatalogDetailPage-wFZDsTGy.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js.map → ApiCatalogDetailPage-wFZDsTGy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js → ApiCatalogPage-Bdm3HNGP.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js.map → ApiCatalogPage-Bdm3HNGP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js → ApiCatalogPage-m_TWQyGv.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js.map → ApiCatalogPage-m_TWQyGv.js.map} +1 -1
- package/dist/chunks/ApplicationDetailPage-C2BSpEoW.js +2 -0
- package/dist/chunks/{ApplicationDetailPage-CWdz0TS4.js.map → ApplicationDetailPage-C2BSpEoW.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js → ApplicationDetailPage-CcgDAP-J.js} +503 -501
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js.map → ApplicationDetailPage-CcgDAP-J.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js → ApplicationsDashboardPage-CDIjziL3.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js.map → ApplicationsDashboardPage-CDIjziL3.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js → ApplicationsDashboardPage-DslDyNzJ.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js.map → ApplicationsDashboardPage-DslDyNzJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js → ApplicationsGridPage-BCjsQGU0.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js.map → ApplicationsGridPage-BCjsQGU0.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js → ApplicationsGridPage-CIfKiCND.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js.map → ApplicationsGridPage-CIfKiCND.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js → ApplicationsListPage-CT75kNcH.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js.map → ApplicationsListPage-CT75kNcH.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js → ApplicationsListPage-D2B4PZ5n.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js.map → ApplicationsListPage-D2B4PZ5n.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js → ApplicationsPage-CaTBtduL.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js.map → ApplicationsPage-CaTBtduL.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js → ApplicationsPage-DW1LhL0U.js} +4 -4
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js.map → ApplicationsPage-DW1LhL0U.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js → AssignmentRulesPage-Bt9M0ki7.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js.map → AssignmentRulesPage-Bt9M0ki7.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js → AssignmentRulesPage-Y7xv60NY.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js.map → AssignmentRulesPage-Y7xv60NY.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js → AssignmentsPage-1eQGTjTi.js} +2 -2
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js.map → AssignmentsPage-1eQGTjTi.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js → AssignmentsPage-RURdPvfZ.js} +2 -2
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js.map → AssignmentsPage-RURdPvfZ.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js → AuthCallbackPage-8hF0jYlK.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js.map → AuthCallbackPage-8hF0jYlK.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js → AuthCallbackPage-DPL68Asu.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js.map → AuthCallbackPage-DPL68Asu.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js → ConfirmEmailPage-BKlpZkVk.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js.map → ConfirmEmailPage-BKlpZkVk.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js → ConfirmEmailPage-CawSZypI.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js.map → ConfirmEmailPage-CawSZypI.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js → CreateSupportTicketPage-AwbMbBIH.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js.map → CreateSupportTicketPage-AwbMbBIH.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js → CreateSupportTicketPage-Dg1YW1eA.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js.map → CreateSupportTicketPage-Dg1YW1eA.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js → DashboardPage-B4YxOF-9.js} +3 -3
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js.map → DashboardPage-B4YxOF-9.js.map} +1 -1
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js → DashboardPage-BZxjinar.js} +2 -2
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js.map → DashboardPage-BZxjinar.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BAqpoxCW.js → DashboardPage-Bo09y8r7.js} +3 -3
- package/dist/chunks/{DashboardPage-BAqpoxCW.js.map → DashboardPage-Bo09y8r7.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BT5kFaQA.js → DashboardPage-Cq5adDjP.js} +2 -2
- package/dist/chunks/{DashboardPage-BT5kFaQA.js.map → DashboardPage-Cq5adDjP.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js → EscalationConfigPage-C8Hv5naz.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js.map → EscalationConfigPage-C8Hv5naz.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js → EscalationConfigPage-DNAqMRxA.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js.map → EscalationConfigPage-DNAqMRxA.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js → ForceChangePasswordPage-BURE_vNg.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js.map → ForceChangePasswordPage-BURE_vNg.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js → ForceChangePasswordPage-C6jDZshk.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js.map → ForceChangePasswordPage-C6jDZshk.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js → ForgotPasswordPage-C5HLYbz4.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js.map → ForgotPasswordPage-C5HLYbz4.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js → ForgotPasswordPage-D3ZQBtjd.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js.map → ForgotPasswordPage-D3ZQBtjd.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js → GroupDetailPage-CTuzp9Vp.js} +5 -5
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js.map → GroupDetailPage-CTuzp9Vp.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js → GroupDetailPage-NJc2zCxC.js} +2 -2
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js.map → GroupDetailPage-NJc2zCxC.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js → MyAccessRequestsPage-Cvr29Pnq.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js.map → MyAccessRequestsPage-Cvr29Pnq.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js → MyAccessRequestsPage-t6I24rHN.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js.map → MyAccessRequestsPage-t6I24rHN.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js → MyTenantsPage-Dy2RZ_Ei.js} +2 -2
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js.map → MyTenantsPage-Dy2RZ_Ei.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js → MyTenantsPage-SvDCQ4Wt.js} +3 -3
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js.map → MyTenantsPage-SvDCQ4Wt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js → MyTicketsPage-C3lEBFD9.js} +2 -2
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js.map → MyTicketsPage-C3lEBFD9.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js → MyTicketsPage-DydDgFyz.js} +2 -2
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js.map → MyTicketsPage-DydDgFyz.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js → NavigationAppsPage-Dyv767w8.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js.map → NavigationAppsPage-Dyv767w8.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js → NavigationAppsPage-WqSspaVo.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js.map → NavigationAppsPage-WqSspaVo.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-_62-bmuk.js → NotificationsPage-Di4I95PM.js} +2 -2
- package/dist/chunks/{NotificationsPage-_62-bmuk.js.map → NotificationsPage-Di4I95PM.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js → NotificationsPage-elSovpBw.js} +2 -2
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js.map → NotificationsPage-elSovpBw.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js → OnboardingWizardPage-fdWdkwiT.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js.map → OnboardingWizardPage-fdWdkwiT.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js → OnboardingWizardPage-nPLe2buQ.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js.map → OnboardingWizardPage-nPLe2buQ.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js → PermissionDetailPage-B8C7tWFP.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js.map → PermissionDetailPage-B8C7tWFP.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js → PermissionDetailPage-IUgUaTkE.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js.map → PermissionDetailPage-IUgUaTkE.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js → PermissionsPage-CmX5sQf2.js} +2 -2
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js.map → PermissionsPage-CmX5sQf2.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js → PermissionsPage-Kg0rduOM.js} +2 -2
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js.map → PermissionsPage-Kg0rduOM.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js → PortalDashboardPage-CCAYuhtI.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js.map → PortalDashboardPage-CCAYuhtI.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js → PortalDashboardPage-Dme1XmzN.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js.map → PortalDashboardPage-Dme1XmzN.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js → PreferencesPage-Ct6xWAFp.js} +2 -2
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js.map → PreferencesPage-Ct6xWAFp.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js → PreferencesPage-Db2RjMpm.js} +2 -2
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js.map → PreferencesPage-Db2RjMpm.js.map} +1 -1
- package/dist/chunks/{ProfilePage-6Gf7igUI.js → ProfilePage-D6Xb1ALH.js} +2 -2
- package/dist/chunks/{ProfilePage-6Gf7igUI.js.map → ProfilePage-D6Xb1ALH.js.map} +1 -1
- package/dist/chunks/{ProfilePage-BzBWkztf.js → ProfilePage-DN2s-lfp.js} +2 -2
- package/dist/chunks/{ProfilePage-BzBWkztf.js.map → ProfilePage-DN2s-lfp.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js → ReferencesManagementPage-B5mcshG1.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js.map → ReferencesManagementPage-B5mcshG1.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js → ReferencesManagementPage-DB975ktX.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js.map → ReferencesManagementPage-DB975ktX.js.map} +1 -1
- package/dist/chunks/{RegisterPage-asdx33fV.js → RegisterPage-ZskZrLZH.js} +2 -2
- package/dist/chunks/{RegisterPage-asdx33fV.js.map → RegisterPage-ZskZrLZH.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CIPHRYkl.js → RegisterPage-b8yIPVgh.js} +2 -2
- package/dist/chunks/{RegisterPage-CIPHRYkl.js.map → RegisterPage-b8yIPVgh.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js → ResetPasswordPage-CeAvfsE-.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js.map → ResetPasswordPage-CeAvfsE-.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js → ResetPasswordPage-Dzp5dCp8.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js.map → ResetPasswordPage-Dzp5dCp8.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Cs6T441o.js → ResolutionModal-CRVN7gHv.js} +2 -2
- package/dist/chunks/{ResolutionModal-Cs6T441o.js.map → ResolutionModal-CRVN7gHv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js → ResolutionModal-DJOw1sLT.js} +2 -2
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js.map → ResolutionModal-DJOw1sLT.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js → RoleDetailPage-CLVoFVF8.js} +2 -2
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js.map → RoleDetailPage-CLVoFVF8.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js → RoleDetailPage-XGnPD_8C.js} +3 -3
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js.map → RoleDetailPage-XGnPD_8C.js.map} +1 -1
- package/dist/chunks/{RolesPage-BHEkMR2O.js → RolesPage-BnAMpR2b.js} +2 -2
- package/dist/chunks/{RolesPage-BHEkMR2O.js.map → RolesPage-BnAMpR2b.js.map} +1 -1
- package/dist/chunks/{RolesPage-D35jwDJU.js → RolesPage-Czj9LMkL.js} +2 -2
- package/dist/chunks/{RolesPage-D35jwDJU.js.map → RolesPage-Czj9LMkL.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-DtonDehw.js → SlaConfigPage-HM0MpIlg.js} +2 -2
- package/dist/chunks/{SlaConfigPage-DtonDehw.js.map → SlaConfigPage-HM0MpIlg.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js → SlaConfigPage-ZRyAs8aY.js} +2 -2
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js.map → SlaConfigPage-ZRyAs8aY.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js → SupportPermissionsPage-CxJuGgcQ.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js.map → SupportPermissionsPage-CxJuGgcQ.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js → SupportPermissionsPage-DNd323OK.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js.map → SupportPermissionsPage-DNd323OK.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js → TemplatesPage-CdwPLsHj.js} +2 -2
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js.map → TemplatesPage-CdwPLsHj.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DlY91VO_.js → TemplatesPage-Co3ygZvF.js} +2 -2
- package/dist/chunks/{TemplatesPage-DlY91VO_.js.map → TemplatesPage-Co3ygZvF.js.map} +1 -1
- package/dist/chunks/{TenantCard-BHLcv2gD.js → TenantCard-CmCfIK2F.js} +2 -2
- package/dist/chunks/{TenantCard-BHLcv2gD.js.map → TenantCard-CmCfIK2F.js.map} +1 -1
- package/dist/chunks/{TenantCard-DGCKVvKI.js → TenantCard-DI66acce.js} +2 -2
- package/dist/chunks/{TenantCard-DGCKVvKI.js.map → TenantCard-DI66acce.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js → TenantScopeSelector-5NOwmFX2.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js.map → TenantScopeSelector-5NOwmFX2.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js → TenantScopeSelector-CEFgxiWt.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js.map → TenantScopeSelector-CEFgxiWt.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js → TicketDetailPage-BhZ-mpv7.js} +2 -2
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js.map → TicketDetailPage-BhZ-mpv7.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js → TicketDetailPage-BxOiOG22.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js.map → TicketDetailPage-BxOiOG22.js.map} +1 -1
- package/dist/chunks/{TicketsPage-CufUJctx.js → TicketsPage-BiTvIcM8.js} +2 -2
- package/dist/chunks/{TicketsPage-CufUJctx.js.map → TicketsPage-BiTvIcM8.js.map} +1 -1
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js → TicketsPage-CSiinHME.js} +2 -2
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js.map → TicketsPage-CSiinHME.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js → UserCreateTicketPage-B3TW1oV7.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js.map → UserCreateTicketPage-B3TW1oV7.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js → UserCreateTicketPage-BszUd_WZ.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js.map → UserCreateTicketPage-BszUd_WZ.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js → UserDashboardPage-C6MvatAb.js} +2 -2
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js.map → UserDashboardPage-C6MvatAb.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js → UserDashboardPage-Dtt9VzG_.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js.map → UserDashboardPage-Dtt9VzG_.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-C97e-Dax.js → UserDetailPage-BEEV2vlJ.js} +5 -5
- package/dist/chunks/{UserDetailPage-C97e-Dax.js.map → UserDetailPage-BEEV2vlJ.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js → UserDetailPage-Dw5OHheZ.js} +2 -2
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js.map → UserDetailPage-Dw5OHheZ.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js → UserTicketDetailPage-B4YkzzbR.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js.map → UserTicketDetailPage-B4YkzzbR.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js → UserTicketDetailPage-DCFV-0ny.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js.map → UserTicketDetailPage-DCFV-0ny.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js → UsersGroupsPage-CY-l9fTp.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js.map → UsersGroupsPage-CY-l9fTp.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js → UsersGroupsPage-c28vYHN9.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js.map → UsersGroupsPage-c28vYHN9.js.map} +1 -1
- package/dist/chunks/{UsersPage-BIXWHFmG.js → UsersPage-1sLlq9QD.js} +2 -2
- package/dist/chunks/{UsersPage-BIXWHFmG.js.map → UsersPage-1sLlq9QD.js.map} +1 -1
- package/dist/chunks/{UsersPage-DS8aWUKj.js → UsersPage-Bm-uNxh0.js} +2 -2
- package/dist/chunks/{UsersPage-DS8aWUKj.js.map → UsersPage-Bm-uNxh0.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js → accessRequestsApi-CJPjyEkH.js} +2 -2
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js.map → accessRequestsApi-CJPjyEkH.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js → accessRequestsApi-D_pj1wl6.js} +2 -2
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js.map → accessRequestsApi-D_pj1wl6.js.map} +1 -1
- package/dist/chunks/{aiApi-B-H-76wM.js → aiApi-ByF-oo1J.js} +2 -2
- package/dist/chunks/{aiApi-B-H-76wM.js.map → aiApi-ByF-oo1J.js.map} +1 -1
- package/dist/chunks/{aiApi-CcdrBILv.js → aiApi-Dt3fj0dU.js} +2 -2
- package/dist/chunks/{aiApi-CcdrBILv.js.map → aiApi-Dt3fj0dU.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js → applicationAnalyticsApi-BgG3SGJm.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js.map → applicationAnalyticsApi-BgG3SGJm.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js → applicationAnalyticsApi-ktD65iLO.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js.map → applicationAnalyticsApi-ktD65iLO.js.map} +1 -1
- package/dist/chunks/{groupsApi-DExOJZPF.js → groupsApi-C-FLWPCO.js} +2 -2
- package/dist/chunks/{groupsApi-DExOJZPF.js.map → groupsApi-C-FLWPCO.js.map} +1 -1
- package/dist/chunks/{groupsApi-CyqyYsmi.js → groupsApi-CBI5vMLa.js} +2 -2
- package/dist/chunks/{groupsApi-CyqyYsmi.js.map → groupsApi-CBI5vMLa.js.map} +1 -1
- package/dist/chunks/{index-DtAReZI6.js → index-B727-QSU.js} +2 -2
- package/dist/chunks/{index-DtAReZI6.js.map → index-B727-QSU.js.map} +1 -1
- package/dist/chunks/{index-BlOgmQzc.js → index-B9q3vx13.js} +2 -2
- package/dist/chunks/{index-BlOgmQzc.js.map → index-B9q3vx13.js.map} +1 -1
- package/dist/chunks/{index-VSQ2prtJ.js → index-BD-REzV9.js} +2 -2
- package/dist/chunks/{index-VSQ2prtJ.js.map → index-BD-REzV9.js.map} +1 -1
- package/dist/chunks/{index-XOOiD_zY.js → index-BDRogQH_.js} +3 -3
- package/dist/chunks/{index-XOOiD_zY.js.map → index-BDRogQH_.js.map} +1 -1
- package/dist/chunks/{index-DOQyf5yZ.js → index-C-DYxdvd.js} +8 -8
- package/dist/chunks/{index-DOQyf5yZ.js.map → index-C-DYxdvd.js.map} +1 -1
- package/dist/chunks/{index-Cq80YBne.js → index-CBtjGPod.js} +105 -105
- package/dist/chunks/{index-Cq80YBne.js.map → index-CBtjGPod.js.map} +1 -1
- package/dist/chunks/{index-dlXYTPWH.js → index-CF1cvNUL.js} +4 -4
- package/dist/chunks/{index-dlXYTPWH.js.map → index-CF1cvNUL.js.map} +1 -1
- package/dist/chunks/{index-COA_xJVJ.js → index-CH0pTHy1.js} +2 -2
- package/dist/chunks/{index-COA_xJVJ.js.map → index-CH0pTHy1.js.map} +1 -1
- package/dist/chunks/{index-DjZQ6ZG_.js → index-Ca88RIuT.js} +2 -2
- package/dist/chunks/{index-DjZQ6ZG_.js.map → index-Ca88RIuT.js.map} +1 -1
- package/dist/chunks/{index-Cj-9tGpd.js → index-CkWvsvKW.js} +2 -2
- package/dist/chunks/{index-Cj-9tGpd.js.map → index-CkWvsvKW.js.map} +1 -1
- package/dist/chunks/{index-EL_ZNnMH.js → index-CzYKE5fL.js} +2 -2
- package/dist/chunks/{index-EL_ZNnMH.js.map → index-CzYKE5fL.js.map} +1 -1
- package/dist/chunks/{index-qXfYaEmV.js → index-D32ol7lq.js} +2 -2
- package/dist/chunks/{index-qXfYaEmV.js.map → index-D32ol7lq.js.map} +1 -1
- package/dist/chunks/{index-DMQQ0KyA.js → index-D7hmx9IX.js} +2 -2
- package/dist/chunks/{index-DMQQ0KyA.js.map → index-D7hmx9IX.js.map} +1 -1
- package/dist/chunks/{index-BetDcNZm.js → index-DThcQmwZ.js} +2 -2
- package/dist/chunks/{index-BetDcNZm.js.map → index-DThcQmwZ.js.map} +1 -1
- package/dist/chunks/{index-C7h5yvcP.js → index-D_3J6ziZ.js} +2 -2
- package/dist/chunks/{index-C7h5yvcP.js.map → index-D_3J6ziZ.js.map} +1 -1
- package/dist/chunks/{index-C_nDTEP5.js → index-JSjfMShT.js} +2 -2
- package/dist/chunks/{index-C_nDTEP5.js.map → index-JSjfMShT.js.map} +1 -1
- package/dist/chunks/{index-COXxU0FH.js → index-gzXJw_ow.js} +3 -3
- package/dist/chunks/{index-COXxU0FH.js.map → index-gzXJw_ow.js.map} +1 -1
- package/dist/chunks/{index-jJxtz2bs.js → index-rRAbl04H.js} +2 -2
- package/dist/chunks/{index-jJxtz2bs.js.map → index-rRAbl04H.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js → tenantIconMap-Cw-hQ9n4.js} +2 -2
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js.map → tenantIconMap-Cw-hQ9n4.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js → tenantIconMap-DinwojNW.js} +2 -2
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js.map → tenantIconMap-DinwojNW.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js → ticketingApi-CcWdebXv.js} +2 -2
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js.map → ticketingApi-CcWdebXv.js.map} +1 -1
- package/dist/chunks/{ticketingApi-D6s75rOB.js → ticketingApi-x0BwZ1NH.js} +2 -2
- package/dist/chunks/{ticketingApi-D6s75rOB.js.map → ticketingApi-x0BwZ1NH.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js → useAccessRequests-BBTIYht3.js} +2 -2
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js.map → useAccessRequests-BBTIYht3.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CanI2ypo.js → useAccessRequests-BBUj9XY9.js} +71 -71
- package/dist/chunks/{useAccessRequests-CanI2ypo.js.map → useAccessRequests-BBUj9XY9.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js → useUserAccessRequests-BKQxcOXH.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js.map → useUserAccessRequests-BKQxcOXH.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js → useUserAccessRequests-BPUPiP55.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js.map → useUserAccessRequests-BPUPiP55.js.map} +1 -1
- package/dist/pages/platform/administration/applications/ApplicationDetailPage.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/ApplicationDetailPage-CWdz0TS4.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage-wEKZ_DWf.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 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 [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]);\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","useTranslation","navigate","useNavigate","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","colorClasses","maxValue","d"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardPage-BZxjinar.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 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 [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]);\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","useTranslation","navigate","useNavigate","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","colorClasses","maxValue","d"],"mappings":"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"}
|
|
@@ -2,9 +2,9 @@ import { jsx as e, jsxs as a, Fragment as ne } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState as l, useCallback as le, useEffect as ce } from "react";
|
|
3
3
|
import { useNavigate as ie } from "react-router-dom";
|
|
4
4
|
import { useTranslation as de } from "react-i18next";
|
|
5
|
-
import { o as oe, W as me, a as he, X as u, Y as ve, Z as L, B as ge, C as xe } from "./index-
|
|
5
|
+
import { o as oe, W as me, a as he, X as u, Y as ve, Z as L, B as ge, C as xe } from "./index-CBtjGPod.js";
|
|
6
6
|
import { Loader2 as pe, RefreshCw as $, LayoutDashboard as be, Info as ue, ExternalLink as fe, Headphones as Ne, TrendingUp as ye, Clock as we, CheckCircle as Se, AlertTriangle as I, Star as P, XCircle as ke, Users as Re, ArrowUp as Ce, ArrowDown as Te } from "lucide-react";
|
|
7
|
-
import { t as $e } from "./ticketingApi-
|
|
7
|
+
import { t as $e } from "./ticketingApi-CcWdebXv.js";
|
|
8
8
|
const Pe = {
|
|
9
9
|
Low: "var(--info-text)",
|
|
10
10
|
Medium: "var(--warning-text)",
|
|
@@ -561,4 +561,4 @@ function H(t) {
|
|
|
561
561
|
export {
|
|
562
562
|
Ge as DashboardPage
|
|
563
563
|
};
|
|
564
|
-
//# sourceMappingURL=DashboardPage-
|
|
564
|
+
//# sourceMappingURL=DashboardPage-Bo09y8r7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage-BAqpoxCW.js","sources":["../../src/pages/platform/support/DashboardPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n LayoutDashboard,\r\n Headphones,\r\n Clock,\r\n AlertTriangle,\r\n TrendingUp,\r\n Users,\r\n Star,\r\n CheckCircle,\r\n XCircle,\r\n ArrowUp,\r\n ArrowDown,\r\n Loader2,\r\n RefreshCw,\r\n ExternalLink,\r\n Info,\r\n} from 'lucide-react';\r\nimport { PageHeader } from '@/components/ui/PageHeader';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useTicketingProvider } from '@/hooks/useTicketingProvider';\r\nimport { supportApi, type GlpiSyncStatsDto } from '@/services/api/ticketApi';\r\nimport { ticketingApi } from '@/services/api/ticketingApi';\r\nimport {\r\n dashboardApi,\r\n slaApi,\r\n type DashboardOverviewDto,\r\n type StatusCountDto,\r\n type PriorityCountDto,\r\n type AgentWorkloadDto,\r\n type TrendDataDto,\r\n type SatisfactionStatsDto,\r\n type SlaComplianceDto,\r\n type TicketSlaDto,\r\n} from '@/services/api/supportApi';\r\n\r\nconst priorityColors: Record<string, string> = {\r\n Low: 'var(--info-text)',\r\n Medium: 'var(--warning-text)',\r\n High: 'var(--warning-text)',\r\n Critical: 'var(--error-text)',\r\n};\r\n\r\nconst statusColors: Record<string, string> = {\r\n Open: 'var(--warning-text)',\r\n InProgress: 'var(--info-text)',\r\n OnHold: 'var(--warning-text)',\r\n Resolved: 'var(--success-text)',\r\n Closed: 'var(--text-secondary)',\r\n Rejected: 'var(--error-text)',\r\n};\r\n\r\nexport function DashboardPage(): ReactElement {\r\n const { t } = useTranslation('support');\r\n const navigate = useNavigate();\r\n const { hasPermission } = useAuth();\r\n const { isGlpi, glpiBaseUrl } = useTicketingProvider();\r\n const { currentTenant } = 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 // Permission checks\r\n const canViewSla = hasPermission('support.sla.read');\r\n\r\n // Data states\r\n const [overview, setOverview] = useState<DashboardOverviewDto | null>(null);\r\n const [statusData, setStatusData] = useState<StatusCountDto[]>([]);\r\n const [priorityData, setPriorityData] = useState<PriorityCountDto[]>([]);\r\n const [agentWorkload, setAgentWorkload] = useState<AgentWorkloadDto[]>([]);\r\n const [trends, setTrends] = useState<TrendDataDto[]>([]);\r\n const [satisfaction, setSatisfaction] = useState<SatisfactionStatsDto | null>(null);\r\n const [slaCompliance, setSlaCompliance] = useState<SlaComplianceDto | null>(null);\r\n const [breachedTickets, setBreachedTickets] = useState<TicketSlaDto[]>([]);\r\n const [approachingBreach, setApproachingBreach] = useState<TicketSlaDto[]>([]);\r\n const [glpiSyncStats, setGlpiSyncStats] = useState<GlpiSyncStatsDto | null>(null);\r\n const [syncing, setSyncing] = useState(false);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n const [\r\n overviewRes,\r\n statusRes,\r\n priorityRes,\r\n workloadRes,\r\n trendsRes,\r\n satisfactionRes,\r\n slaRes,\r\n ] = await Promise.all([\r\n dashboardApi.getOverview(period),\r\n dashboardApi.getByStatus(),\r\n dashboardApi.getByPriority(),\r\n dashboardApi.getAgentWorkload(),\r\n dashboardApi.getTrends(period),\r\n dashboardApi.getSatisfactionStats(period),\r\n dashboardApi.getSlaCompliance(period),\r\n ]);\r\n\r\n setOverview(overviewRes);\r\n setStatusData(statusRes);\r\n setPriorityData(priorityRes);\r\n setAgentWorkload(workloadRes);\r\n setTrends(trendsRes);\r\n setSatisfaction(satisfactionRes);\r\n setSlaCompliance(slaRes);\r\n\r\n // Load GLPI sync stats if GLPI is provider\r\n if (isGlpi) {\r\n try {\r\n const syncStats = await supportApi.tickets.getGlpiSyncStats();\r\n setGlpiSyncStats(syncStats);\r\n } catch {\r\n // Sync stats are optional\r\n }\r\n }\r\n\r\n // SLA detail endpoints require support.sla.read permission\r\n if (canViewSla) {\r\n const [breachedRes, approachingRes] = await Promise.all([\r\n slaApi.getBreachedTickets(),\r\n slaApi.getTicketsApproachingBreach(60),\r\n ]);\r\n setBreachedTickets(breachedRes);\r\n setApproachingBreach(approachingRes);\r\n }\r\n } catch (error) {\r\n console.error('Failed to load dashboard data:', error);\r\n } finally {\r\n setLoading(false);\r\n setRefreshing(false);\r\n }\r\n }, [period, canViewSla, isGlpi]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleRefresh = () => {\r\n setRefreshing(true);\r\n loadData();\r\n };\r\n\r\n const handleTriggerSync = async () => {\r\n if (!currentTenant?.id || syncing) return;\r\n setSyncing(true);\r\n try {\r\n await ticketingApi.triggerSync(currentTenant.id);\r\n // Reload data after sync\r\n await loadData();\r\n } catch {\r\n // Error handled silently\r\n } finally {\r\n setSyncing(false);\r\n }\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 const getComplianceColor = (percentage: number) => {\r\n if (percentage >= 95) return 'text-[var(--success-text)]';\r\n if (percentage >= 80) return 'text-[var(--warning-text)]';\r\n return 'text-[var(--error-text)]';\r\n };\r\n\r\n const getRatingColor = (rating: number) => {\r\n if (rating >= 4) return 'text-[var(--success-text)]';\r\n if (rating >= 3) return 'text-[var(--warning-text)]';\r\n return 'text-[var(--error-text)]';\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('title', 'Support'), href: '/support' },\r\n { label: t('dashboard.title', 'Dashboard') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <PageHeader\r\n title={t('dashboard.title')}\r\n subtitle={t('dashboard.subtitle')}\r\n icon={<LayoutDashboard className=\"w-6 h-6\" />}\r\n actions={\r\n <>\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}>{t('dashboard.period7')}</option>\r\n <option value={30}>{t('dashboard.period30')}</option>\r\n <option value={90}>{t('dashboard.period90')}</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 {t('dashboard.refresh')}\r\n </button>\r\n </>\r\n }\r\n />\r\n\r\n {/* GLPI Provider Banner */}\r\n {isGlpi && (\r\n <div className=\"flex items-center gap-3 p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] text-[var(--info-text)]\">\r\n <Info className=\"w-5 h-5 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"font-medium\">{t('glpi.managedByGlpi')}</p>\r\n <p className=\"text-sm opacity-80\">{t('glpi.dashboardSyncInfo')}</p>\r\n </div>\r\n {glpiBaseUrl && (\r\n <a\r\n href={glpiBaseUrl}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"btn btn-secondary flex items-center gap-2 text-sm\"\r\n >\r\n <ExternalLink className=\"w-4 h-4\" />\r\n {t('glpi.openGlpi')}\r\n </a>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* GLPI Sync Status */}\r\n {isGlpi && glpiSyncStats && (\r\n <div className=\"card p-4 space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold flex items-center gap-2\">\r\n <RefreshCw className=\"w-5 h-5\" />\r\n {t('glpi.sync.title', 'GLPI Sync Status')}\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">{t('glpi.sync.subtitle', 'Synchronization overview with GLPI')}</p>\r\n </div>\r\n <button\r\n onClick={handleTriggerSync}\r\n disabled={syncing}\r\n className=\"btn btn-secondary flex items-center gap-2\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${syncing ? 'animate-spin' : ''}`} />\r\n {syncing ? t('glpi.sync.syncing', 'Syncing...') : t('glpi.sync.triggerSync', 'Sync Now')}\r\n </button>\r\n </div>\r\n\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n <div className=\"card p-4 text-center border bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]\">\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.totalMappedTickets}</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.totalSynced', 'Total Synced')}</div>\r\n </div>\r\n <div className=\"card p-4 text-center border bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]\">\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.ticketsSyncedOk}</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.syncSuccess', 'Successful')}</div>\r\n </div>\r\n <div className=\"card p-4 text-center border bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]\">\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.ticketsWithSyncErrors}</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.syncErrors', 'Errors')}</div>\r\n </div>\r\n <div className={`card p-4 text-center border ${glpiSyncStats.successRate >= 90 ? 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]' : 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]'}`}>\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.successRate}%</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.successRate', 'Success Rate')}</div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-6 text-sm text-[var(--text-secondary)]\">\r\n <div>\r\n <span className=\"font-medium\">{t('glpi.sync.lastSync', 'Last Sync')}:</span>{' '}\r\n {glpiSyncStats.lastSyncAt\r\n ? new Date(glpiSyncStats.lastSyncAt).toLocaleString()\r\n : t('glpi.sync.never', 'Never')}\r\n </div>\r\n <div>\r\n <span className=\"font-medium\">{t('glpi.sync.syncInterval', 'Interval')}:</span>{' '}\r\n {t('glpi.sync.everyNMinutes', 'Every {{n}} min', { n: glpiSyncStats.syncIntervalMinutes })}\r\n </div>\r\n <div>\r\n <span className={`px-2 py-0.5 rounded text-xs font-medium ${glpiSyncStats.syncEnabled ? 'bg-[var(--success-bg)] text-[var(--success-text)]' : 'bg-[var(--bg-secondary)] text-[var(--text-secondary)]'}`}>\r\n {glpiSyncStats.syncEnabled ? t('glpi.sync.enabled', 'Enabled') : t('glpi.sync.disabled', 'Disabled')}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {glpiSyncStats.lastSyncError && (\r\n <div className=\"p-3 rounded-lg bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <p className=\"text-sm font-medium text-[var(--error-text)]\">{t('glpi.sync.lastError', 'Last Sync Error')}</p>\r\n <p className=\"text-sm text-[var(--error-text)] opacity-80 mt-1\">{glpiSyncStats.lastSyncError}</p>\r\n </div>\r\n )}\r\n </div>\r\n )}\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={t('dashboard.totalTickets')}\r\n value={overview?.totalTickets ?? 0}\r\n icon={<Headphones className=\"w-5 h-5\" />}\r\n color=\"blue\"\r\n />\r\n <KpiCard\r\n title={t('dashboard.newTickets')}\r\n value={overview?.newTickets ?? 0}\r\n icon={<TrendingUp className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n subtitle={t('dashboard.lastNDays', { period })}\r\n />\r\n <KpiCard\r\n title={t('dashboard.openTickets')}\r\n value={overview?.openTickets ?? 0}\r\n icon={<Clock className=\"w-5 h-5\" />}\r\n color=\"yellow\"\r\n />\r\n <KpiCard\r\n title={t('dashboard.resolvedTickets')}\r\n value={overview?.resolvedTickets ?? 0}\r\n icon={<CheckCircle className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n subtitle={t('dashboard.lastNDays', { period })}\r\n />\r\n <KpiCard\r\n title={t('dashboard.slaCompliance')}\r\n value={`${overview?.slaCompliancePercentage?.toFixed(1) ?? 0}%`}\r\n icon={<AlertTriangle className=\"w-5 h-5\" />}\r\n color={(overview?.slaCompliancePercentage ?? 0) >= 90 ? 'green' : 'red'}\r\n />\r\n <KpiCard\r\n title={t('dashboard.avgSatisfaction')}\r\n value={`${overview?.averageSatisfaction?.toFixed(1) ?? 0}/5`}\r\n icon={<Star className=\"w-5 h-5\" />}\r\n color={(overview?.averageSatisfaction ?? 0) >= 4 ? 'green' : 'yellow'}\r\n />\r\n </div>\r\n\r\n {/* SLA Alerts - only visible with support.sla.read permission */}\r\n {canViewSla && (breachedTickets.length > 0 || approachingBreach.length > 0) && (\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {breachedTickets.length > 0 && (\r\n <div className=\"card p-4 border-l-4 border-[var(--error-border)]\">\r\n <h3 className=\"font-semibold text-[var(--error-text)] flex items-center gap-2 mb-3\">\r\n <XCircle className=\"w-5 h-5\" />\r\n {t('dashboard.slaBreached')} ({breachedTickets.length})\r\n </h3>\r\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\r\n {breachedTickets.slice(0, 5).map((ticket) => (\r\n <button\r\n type=\"button\"\r\n key={ticket.id}\r\n className=\"w-full flex items-center justify-between p-2 bg-[var(--error-bg)] rounded cursor-pointer hover:opacity-80 text-left\"\r\n onClick={() => navigate(`/support/tickets/${ticket.ticketId}`)}\r\n >\r\n <div>\r\n <span className=\"font-mono text-sm\">{ticket.ticketNumber}</span>\r\n <span className=\"ml-2 text-sm\">{ticket.ticketTitle}</span>\r\n </div>\r\n <span className=\"text-xs text-[var(--error-text)] font-medium\">\r\n {ticket.responseBreached && 'Response'}{' '}\r\n {ticket.resolutionBreached && 'Resolution'}\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {approachingBreach.length > 0 && (\r\n <div className=\"card p-4 border-l-4 border-[var(--warning-border)]\">\r\n <h3 className=\"font-semibold text-[var(--warning-text)] flex items-center gap-2 mb-3\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n {t('dashboard.approachingBreach')} ({approachingBreach.length})\r\n </h3>\r\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\r\n {approachingBreach.slice(0, 5).map((ticket) => (\r\n <button\r\n type=\"button\"\r\n key={ticket.id}\r\n className=\"w-full flex items-center justify-between p-2 bg-[var(--warning-bg)] rounded cursor-pointer hover:opacity-80 text-left\"\r\n onClick={() => navigate(`/support/tickets/${ticket.ticketId}`)}\r\n >\r\n <div>\r\n <span className=\"font-mono text-sm\">{ticket.ticketNumber}</span>\r\n <span className=\"ml-2 text-sm\">{ticket.ticketTitle}</span>\r\n </div>\r\n <span className=\"text-xs text-[var(--warning-text)] font-medium\">\r\n {Math.round(ticket.responseSlaPercentage)}% Response\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\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\">{t('dashboard.ticketsByStatus')}</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}</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-16 text-right text-sm font-medium\">{item.count}</div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Priority Distribution */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4\">{t('dashboard.activeTicketsByPriority')}</h3>\r\n <div className=\"space-y-3\">\r\n {priorityData.map((item) => {\r\n const total = priorityData.reduce((sum, p) => sum + p.count, 0);\r\n const percentage = total > 0 ? (item.count / total) * 100 : 0;\r\n return (\r\n <div key={item.priority} className=\"flex items-center gap-3\">\r\n <div className=\"w-24 text-sm\">{item.priority}</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: priorityColors[item.priority] || '#6b7280',\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-16 text-right text-sm font-medium\">{item.count}</div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* SLA & Satisfaction Row */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* SLA Compliance */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4\">{t('dashboard.slaPerformance')}</h3>\r\n {slaCompliance && (\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 ${getComplianceColor(slaCompliance.compliancePercentage)}`}>\r\n {slaCompliance.compliancePercentage.toFixed(1)}%\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.complianceRate')}</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\">{slaCompliance.ticketsWithinSla}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.withinSla')}</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-[var(--error-text)]\">{slaCompliance.ticketsBreached}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.breached')}</div>\r\n </div>\r\n <div className=\"space-y-2 p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"flex justify-between text-sm\">\r\n <span>{t('dashboard.avgResponse')}:</span>\r\n <span className=\"font-medium\">{formatDuration(slaCompliance.averageResponseMinutes)}</span>\r\n </div>\r\n <div className=\"flex justify-between text-sm\">\r\n <span>{t('dashboard.avgResolution')}:</span>\r\n <span className=\"font-medium\">{formatDuration(slaCompliance.averageResolutionMinutes)}</span>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Satisfaction */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4\">{t('dashboard.customerSatisfaction')}</h3>\r\n {satisfaction && (\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 ${getRatingColor(satisfaction.averageRating)}`}>\r\n {satisfaction.averageRating.toFixed(1)}\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.averageRating')}</div>\r\n <div className=\"flex justify-center mt-1\">\r\n {[1, 2, 3, 4, 5].map((star) => (\r\n <Star\r\n key={star}\r\n className={`w-4 h-4 ${star <= Math.round(satisfaction.averageRating)\r\n ? 'text-[var(--warning-text)] fill-[var(--warning-text)]'\r\n : 'text-[var(--text-muted)]'\r\n }`}\r\n />\r\n ))}\r\n </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\">{satisfaction.totalResponses}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.totalResponses')}</div>\r\n </div>\r\n <div className=\"col-span-2 p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-sm font-medium mb-2\">{t('dashboard.ratingDistribution')}</div>\r\n <div className=\"space-y-1\">\r\n {[5, 4, 3, 2, 1].map((rating) => {\r\n const count = satisfaction.ratingDistribution[rating] || 0;\r\n const percentage =\r\n satisfaction.totalResponses > 0\r\n ? (count / satisfaction.totalResponses) * 100\r\n : 0;\r\n return (\r\n <div key={rating} className=\"flex items-center gap-2 text-sm\">\r\n <span className=\"w-4\">{rating}</span>\r\n <Star className=\"w-3 h-3 text-[var(--warning-text)] fill-[var(--warning-text)]\" />\r\n <div className=\"flex-1 h-3 bg-[var(--bg-primary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-[var(--warning-text)] rounded-full\"\r\n style={{ width: `${percentage}%` }}\r\n />\r\n </div>\r\n <span className=\"w-8 text-right text-xs\">{count}</span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n )}\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\">{t('dashboard.ticketTrends', { period })}</h3>\r\n <div className=\"h-64\">\r\n <TrendChart data={trends} t={t} />\r\n </div>\r\n </div>\r\n\r\n {/* Agent Workload */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('dashboard.agentWorkload')}\r\n </h3>\r\n {agentWorkload.length > 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\">{t('dashboard.agent')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.total')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.open')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.inProgress')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.onHold')}</th>\r\n <th className=\"text-left p-3 font-medium\">{t('dashboard.load')}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {agentWorkload.map((agent) => {\r\n const maxLoad = Math.max(...agentWorkload.map((a) => a.totalAssigned));\r\n const loadPercentage = maxLoad > 0 ? (agent.totalAssigned / maxLoad) * 100 : 0;\r\n return (\r\n <tr key={agent.userId} className=\"border-b border-[var(--border-color)]\">\r\n <td className=\"p-3\">\r\n <div className=\"font-medium\">{agent.name}</div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">{agent.email}</div>\r\n </td>\r\n <td className=\"text-center p-3 font-semibold\">{agent.totalAssigned}</td>\r\n <td className=\"text-center p-3\">\r\n <span className=\"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm\">\r\n {agent.openCount}\r\n </span>\r\n </td>\r\n <td className=\"text-center p-3\">\r\n <span className=\"px-2 py-1 bg-[var(--info-bg)] text-[var(--info-text)] rounded-[var(--radius-badge)] text-sm\">\r\n {agent.inProgressCount}\r\n </span>\r\n </td>\r\n <td className=\"text-center p-3\">\r\n <span className=\"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm\">\r\n {agent.onHoldCount}\r\n </span>\r\n </td>\r\n <td className=\"p-3 w-32\">\r\n <div className=\"h-2 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-[var(--info-text)] rounded-full\"\r\n style={{ width: `${loadPercentage}%` }}\r\n />\r\n </div>\r\n </td>\r\n </tr>\r\n );\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 {t('dashboard.noAgentsAssigned')}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// KPI Card Component\r\nfunction KpiCard({\r\n title,\r\n value,\r\n icon,\r\n color,\r\n subtitle,\r\n trend,\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 trend?: { value: number; isUp: boolean };\r\n}) {\r\n const colorClasses = {\r\n blue: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n green: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n yellow: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n red: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\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 {trend && (\r\n <div className={`flex items-center gap-1 mt-1 text-xs ${trend.isUp ? 'text-[var(--success-text)]' : 'text-[var(--error-text)]'}`}>\r\n {trend.isUp ? <ArrowUp className=\"w-3 h-3\" /> : <ArrowDown className=\"w-3 h-3\" />}\r\n {trend.value}%\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// Simple Trend Chart Component\r\ntype TrendTFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\nfunction TrendChart({ data, t }: { data: TrendDataDto[]; t: TrendTFunction }) {\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 {t('dashboard.noTrendData')}\r\n </div>\r\n );\r\n }\r\n\r\n const maxValue = Math.max(...data.flatMap((d) => [d.created, d.resolved]), 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-[var(--info-text)]\" />\r\n <span className=\"text-sm\">{t('dashboard.created')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"w-3 h-3 rounded bg-[var(--success-text)]\" />\r\n <span className=\"text-sm\">{t('dashboard.resolved')}</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-[var(--info-text)] rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{ height: `${(item.created / maxValue) * 100}%`, minHeight: item.created > 0 ? '4px' : '0' }}\r\n title={`Created: ${item.created}`}\r\n />\r\n <div\r\n className=\"flex-1 bg-[var(--success-text)] rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{ height: `${(item.resolved / maxValue) * 100}%`, minHeight: item.resolved > 0 ? '4px' : '0' }}\r\n title={`Resolved: ${item.resolved}`}\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()}</span>\r\n <span>{data.at(-1) && new Date(data.at(-1)!.date).toLocaleDateString()}</span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// Format duration helper\r\nfunction formatDuration(minutes: number): string {\r\n if (minutes < 60) return `${Math.round(minutes)}m`;\r\n const hours = Math.floor(minutes / 60);\r\n const mins = Math.round(minutes % 60);\r\n if (hours < 24) return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;\r\n const days = Math.floor(hours / 24);\r\n const remainingHours = hours % 24;\r\n return remainingHours > 0 ? `${days}d ${remainingHours}h` : `${days}d`;\r\n}\r\n"],"names":["priorityColors","statusColors","DashboardPage","useTranslation","navigate","useNavigate","hasPermission","useAuth","isGlpi","glpiBaseUrl","useTicketingProvider","currentTenant","useTenant","loading","setLoading","useState","refreshing","setRefreshing","period","setPeriod","canViewSla","overview","setOverview","statusData","setStatusData","priorityData","setPriorityData","agentWorkload","setAgentWorkload","trends","setTrends","satisfaction","setSatisfaction","slaCompliance","setSlaCompliance","breachedTickets","setBreachedTickets","approachingBreach","setApproachingBreach","glpiSyncStats","setGlpiSyncStats","syncing","setSyncing","loadData","useCallback","overviewRes","statusRes","priorityRes","workloadRes","trendsRes","satisfactionRes","slaRes","dashboardApi","syncStats","supportApi","breachedRes","approachingRes","slaApi","error","useEffect","handleRefresh","handleTriggerSync","ticketingApi","jsx","Loader2","getComplianceColor","percentage","getRatingColor","rating","jsxs","Breadcrumb","PageHeader","LayoutDashboard","Fragment","e","RefreshCw","Info","ExternalLink","KpiCard","Headphones","TrendingUp","Clock","CheckCircle","AlertTriangle","Star","XCircle","ticket","item","total","sum","s","p","formatDuration","star","count","TrendChart","Users","agent","maxLoad","a","loadPercentage","title","value","icon","color","subtitle","trend","ArrowUp","ArrowDown","data","t","maxValue","d","minutes","hours","mins","days","remainingHours"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardPage-Bo09y8r7.js","sources":["../../src/pages/platform/support/DashboardPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n LayoutDashboard,\r\n Headphones,\r\n Clock,\r\n AlertTriangle,\r\n TrendingUp,\r\n Users,\r\n Star,\r\n CheckCircle,\r\n XCircle,\r\n ArrowUp,\r\n ArrowDown,\r\n Loader2,\r\n RefreshCw,\r\n ExternalLink,\r\n Info,\r\n} from 'lucide-react';\r\nimport { PageHeader } from '@/components/ui/PageHeader';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useTicketingProvider } from '@/hooks/useTicketingProvider';\r\nimport { supportApi, type GlpiSyncStatsDto } from '@/services/api/ticketApi';\r\nimport { ticketingApi } from '@/services/api/ticketingApi';\r\nimport {\r\n dashboardApi,\r\n slaApi,\r\n type DashboardOverviewDto,\r\n type StatusCountDto,\r\n type PriorityCountDto,\r\n type AgentWorkloadDto,\r\n type TrendDataDto,\r\n type SatisfactionStatsDto,\r\n type SlaComplianceDto,\r\n type TicketSlaDto,\r\n} from '@/services/api/supportApi';\r\n\r\nconst priorityColors: Record<string, string> = {\r\n Low: 'var(--info-text)',\r\n Medium: 'var(--warning-text)',\r\n High: 'var(--warning-text)',\r\n Critical: 'var(--error-text)',\r\n};\r\n\r\nconst statusColors: Record<string, string> = {\r\n Open: 'var(--warning-text)',\r\n InProgress: 'var(--info-text)',\r\n OnHold: 'var(--warning-text)',\r\n Resolved: 'var(--success-text)',\r\n Closed: 'var(--text-secondary)',\r\n Rejected: 'var(--error-text)',\r\n};\r\n\r\nexport function DashboardPage(): ReactElement {\r\n const { t } = useTranslation('support');\r\n const navigate = useNavigate();\r\n const { hasPermission } = useAuth();\r\n const { isGlpi, glpiBaseUrl } = useTicketingProvider();\r\n const { currentTenant } = 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 // Permission checks\r\n const canViewSla = hasPermission('support.sla.read');\r\n\r\n // Data states\r\n const [overview, setOverview] = useState<DashboardOverviewDto | null>(null);\r\n const [statusData, setStatusData] = useState<StatusCountDto[]>([]);\r\n const [priorityData, setPriorityData] = useState<PriorityCountDto[]>([]);\r\n const [agentWorkload, setAgentWorkload] = useState<AgentWorkloadDto[]>([]);\r\n const [trends, setTrends] = useState<TrendDataDto[]>([]);\r\n const [satisfaction, setSatisfaction] = useState<SatisfactionStatsDto | null>(null);\r\n const [slaCompliance, setSlaCompliance] = useState<SlaComplianceDto | null>(null);\r\n const [breachedTickets, setBreachedTickets] = useState<TicketSlaDto[]>([]);\r\n const [approachingBreach, setApproachingBreach] = useState<TicketSlaDto[]>([]);\r\n const [glpiSyncStats, setGlpiSyncStats] = useState<GlpiSyncStatsDto | null>(null);\r\n const [syncing, setSyncing] = useState(false);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n const [\r\n overviewRes,\r\n statusRes,\r\n priorityRes,\r\n workloadRes,\r\n trendsRes,\r\n satisfactionRes,\r\n slaRes,\r\n ] = await Promise.all([\r\n dashboardApi.getOverview(period),\r\n dashboardApi.getByStatus(),\r\n dashboardApi.getByPriority(),\r\n dashboardApi.getAgentWorkload(),\r\n dashboardApi.getTrends(period),\r\n dashboardApi.getSatisfactionStats(period),\r\n dashboardApi.getSlaCompliance(period),\r\n ]);\r\n\r\n setOverview(overviewRes);\r\n setStatusData(statusRes);\r\n setPriorityData(priorityRes);\r\n setAgentWorkload(workloadRes);\r\n setTrends(trendsRes);\r\n setSatisfaction(satisfactionRes);\r\n setSlaCompliance(slaRes);\r\n\r\n // Load GLPI sync stats if GLPI is provider\r\n if (isGlpi) {\r\n try {\r\n const syncStats = await supportApi.tickets.getGlpiSyncStats();\r\n setGlpiSyncStats(syncStats);\r\n } catch {\r\n // Sync stats are optional\r\n }\r\n }\r\n\r\n // SLA detail endpoints require support.sla.read permission\r\n if (canViewSla) {\r\n const [breachedRes, approachingRes] = await Promise.all([\r\n slaApi.getBreachedTickets(),\r\n slaApi.getTicketsApproachingBreach(60),\r\n ]);\r\n setBreachedTickets(breachedRes);\r\n setApproachingBreach(approachingRes);\r\n }\r\n } catch (error) {\r\n console.error('Failed to load dashboard data:', error);\r\n } finally {\r\n setLoading(false);\r\n setRefreshing(false);\r\n }\r\n }, [period, canViewSla, isGlpi]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleRefresh = () => {\r\n setRefreshing(true);\r\n loadData();\r\n };\r\n\r\n const handleTriggerSync = async () => {\r\n if (!currentTenant?.id || syncing) return;\r\n setSyncing(true);\r\n try {\r\n await ticketingApi.triggerSync(currentTenant.id);\r\n // Reload data after sync\r\n await loadData();\r\n } catch {\r\n // Error handled silently\r\n } finally {\r\n setSyncing(false);\r\n }\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 const getComplianceColor = (percentage: number) => {\r\n if (percentage >= 95) return 'text-[var(--success-text)]';\r\n if (percentage >= 80) return 'text-[var(--warning-text)]';\r\n return 'text-[var(--error-text)]';\r\n };\r\n\r\n const getRatingColor = (rating: number) => {\r\n if (rating >= 4) return 'text-[var(--success-text)]';\r\n if (rating >= 3) return 'text-[var(--warning-text)]';\r\n return 'text-[var(--error-text)]';\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('title', 'Support'), href: '/support' },\r\n { label: t('dashboard.title', 'Dashboard') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <PageHeader\r\n title={t('dashboard.title')}\r\n subtitle={t('dashboard.subtitle')}\r\n icon={<LayoutDashboard className=\"w-6 h-6\" />}\r\n actions={\r\n <>\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}>{t('dashboard.period7')}</option>\r\n <option value={30}>{t('dashboard.period30')}</option>\r\n <option value={90}>{t('dashboard.period90')}</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 {t('dashboard.refresh')}\r\n </button>\r\n </>\r\n }\r\n />\r\n\r\n {/* GLPI Provider Banner */}\r\n {isGlpi && (\r\n <div className=\"flex items-center gap-3 p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] text-[var(--info-text)]\">\r\n <Info className=\"w-5 h-5 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"font-medium\">{t('glpi.managedByGlpi')}</p>\r\n <p className=\"text-sm opacity-80\">{t('glpi.dashboardSyncInfo')}</p>\r\n </div>\r\n {glpiBaseUrl && (\r\n <a\r\n href={glpiBaseUrl}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"btn btn-secondary flex items-center gap-2 text-sm\"\r\n >\r\n <ExternalLink className=\"w-4 h-4\" />\r\n {t('glpi.openGlpi')}\r\n </a>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* GLPI Sync Status */}\r\n {isGlpi && glpiSyncStats && (\r\n <div className=\"card p-4 space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold flex items-center gap-2\">\r\n <RefreshCw className=\"w-5 h-5\" />\r\n {t('glpi.sync.title', 'GLPI Sync Status')}\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">{t('glpi.sync.subtitle', 'Synchronization overview with GLPI')}</p>\r\n </div>\r\n <button\r\n onClick={handleTriggerSync}\r\n disabled={syncing}\r\n className=\"btn btn-secondary flex items-center gap-2\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${syncing ? 'animate-spin' : ''}`} />\r\n {syncing ? t('glpi.sync.syncing', 'Syncing...') : t('glpi.sync.triggerSync', 'Sync Now')}\r\n </button>\r\n </div>\r\n\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n <div className=\"card p-4 text-center border bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]\">\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.totalMappedTickets}</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.totalSynced', 'Total Synced')}</div>\r\n </div>\r\n <div className=\"card p-4 text-center border bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]\">\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.ticketsSyncedOk}</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.syncSuccess', 'Successful')}</div>\r\n </div>\r\n <div className=\"card p-4 text-center border bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]\">\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.ticketsWithSyncErrors}</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.syncErrors', 'Errors')}</div>\r\n </div>\r\n <div className={`card p-4 text-center border ${glpiSyncStats.successRate >= 90 ? 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]' : 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]'}`}>\r\n <div className=\"text-2xl font-bold\">{glpiSyncStats.successRate}%</div>\r\n <div className=\"text-sm opacity-80\">{t('glpi.sync.successRate', 'Success Rate')}</div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-6 text-sm text-[var(--text-secondary)]\">\r\n <div>\r\n <span className=\"font-medium\">{t('glpi.sync.lastSync', 'Last Sync')}:</span>{' '}\r\n {glpiSyncStats.lastSyncAt\r\n ? new Date(glpiSyncStats.lastSyncAt).toLocaleString()\r\n : t('glpi.sync.never', 'Never')}\r\n </div>\r\n <div>\r\n <span className=\"font-medium\">{t('glpi.sync.syncInterval', 'Interval')}:</span>{' '}\r\n {t('glpi.sync.everyNMinutes', 'Every {{n}} min', { n: glpiSyncStats.syncIntervalMinutes })}\r\n </div>\r\n <div>\r\n <span className={`px-2 py-0.5 rounded text-xs font-medium ${glpiSyncStats.syncEnabled ? 'bg-[var(--success-bg)] text-[var(--success-text)]' : 'bg-[var(--bg-secondary)] text-[var(--text-secondary)]'}`}>\r\n {glpiSyncStats.syncEnabled ? t('glpi.sync.enabled', 'Enabled') : t('glpi.sync.disabled', 'Disabled')}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {glpiSyncStats.lastSyncError && (\r\n <div className=\"p-3 rounded-lg bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <p className=\"text-sm font-medium text-[var(--error-text)]\">{t('glpi.sync.lastError', 'Last Sync Error')}</p>\r\n <p className=\"text-sm text-[var(--error-text)] opacity-80 mt-1\">{glpiSyncStats.lastSyncError}</p>\r\n </div>\r\n )}\r\n </div>\r\n )}\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={t('dashboard.totalTickets')}\r\n value={overview?.totalTickets ?? 0}\r\n icon={<Headphones className=\"w-5 h-5\" />}\r\n color=\"blue\"\r\n />\r\n <KpiCard\r\n title={t('dashboard.newTickets')}\r\n value={overview?.newTickets ?? 0}\r\n icon={<TrendingUp className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n subtitle={t('dashboard.lastNDays', { period })}\r\n />\r\n <KpiCard\r\n title={t('dashboard.openTickets')}\r\n value={overview?.openTickets ?? 0}\r\n icon={<Clock className=\"w-5 h-5\" />}\r\n color=\"yellow\"\r\n />\r\n <KpiCard\r\n title={t('dashboard.resolvedTickets')}\r\n value={overview?.resolvedTickets ?? 0}\r\n icon={<CheckCircle className=\"w-5 h-5\" />}\r\n color=\"green\"\r\n subtitle={t('dashboard.lastNDays', { period })}\r\n />\r\n <KpiCard\r\n title={t('dashboard.slaCompliance')}\r\n value={`${overview?.slaCompliancePercentage?.toFixed(1) ?? 0}%`}\r\n icon={<AlertTriangle className=\"w-5 h-5\" />}\r\n color={(overview?.slaCompliancePercentage ?? 0) >= 90 ? 'green' : 'red'}\r\n />\r\n <KpiCard\r\n title={t('dashboard.avgSatisfaction')}\r\n value={`${overview?.averageSatisfaction?.toFixed(1) ?? 0}/5`}\r\n icon={<Star className=\"w-5 h-5\" />}\r\n color={(overview?.averageSatisfaction ?? 0) >= 4 ? 'green' : 'yellow'}\r\n />\r\n </div>\r\n\r\n {/* SLA Alerts - only visible with support.sla.read permission */}\r\n {canViewSla && (breachedTickets.length > 0 || approachingBreach.length > 0) && (\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {breachedTickets.length > 0 && (\r\n <div className=\"card p-4 border-l-4 border-[var(--error-border)]\">\r\n <h3 className=\"font-semibold text-[var(--error-text)] flex items-center gap-2 mb-3\">\r\n <XCircle className=\"w-5 h-5\" />\r\n {t('dashboard.slaBreached')} ({breachedTickets.length})\r\n </h3>\r\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\r\n {breachedTickets.slice(0, 5).map((ticket) => (\r\n <button\r\n type=\"button\"\r\n key={ticket.id}\r\n className=\"w-full flex items-center justify-between p-2 bg-[var(--error-bg)] rounded cursor-pointer hover:opacity-80 text-left\"\r\n onClick={() => navigate(`/support/tickets/${ticket.ticketId}`)}\r\n >\r\n <div>\r\n <span className=\"font-mono text-sm\">{ticket.ticketNumber}</span>\r\n <span className=\"ml-2 text-sm\">{ticket.ticketTitle}</span>\r\n </div>\r\n <span className=\"text-xs text-[var(--error-text)] font-medium\">\r\n {ticket.responseBreached && 'Response'}{' '}\r\n {ticket.resolutionBreached && 'Resolution'}\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {approachingBreach.length > 0 && (\r\n <div className=\"card p-4 border-l-4 border-[var(--warning-border)]\">\r\n <h3 className=\"font-semibold text-[var(--warning-text)] flex items-center gap-2 mb-3\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n {t('dashboard.approachingBreach')} ({approachingBreach.length})\r\n </h3>\r\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\r\n {approachingBreach.slice(0, 5).map((ticket) => (\r\n <button\r\n type=\"button\"\r\n key={ticket.id}\r\n className=\"w-full flex items-center justify-between p-2 bg-[var(--warning-bg)] rounded cursor-pointer hover:opacity-80 text-left\"\r\n onClick={() => navigate(`/support/tickets/${ticket.ticketId}`)}\r\n >\r\n <div>\r\n <span className=\"font-mono text-sm\">{ticket.ticketNumber}</span>\r\n <span className=\"ml-2 text-sm\">{ticket.ticketTitle}</span>\r\n </div>\r\n <span className=\"text-xs text-[var(--warning-text)] font-medium\">\r\n {Math.round(ticket.responseSlaPercentage)}% Response\r\n </span>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\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\">{t('dashboard.ticketsByStatus')}</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}</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-16 text-right text-sm font-medium\">{item.count}</div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n {/* Priority Distribution */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4\">{t('dashboard.activeTicketsByPriority')}</h3>\r\n <div className=\"space-y-3\">\r\n {priorityData.map((item) => {\r\n const total = priorityData.reduce((sum, p) => sum + p.count, 0);\r\n const percentage = total > 0 ? (item.count / total) * 100 : 0;\r\n return (\r\n <div key={item.priority} className=\"flex items-center gap-3\">\r\n <div className=\"w-24 text-sm\">{item.priority}</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: priorityColors[item.priority] || '#6b7280',\r\n }}\r\n />\r\n </div>\r\n <div className=\"w-16 text-right text-sm font-medium\">{item.count}</div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* SLA & Satisfaction Row */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* SLA Compliance */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4\">{t('dashboard.slaPerformance')}</h3>\r\n {slaCompliance && (\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 ${getComplianceColor(slaCompliance.compliancePercentage)}`}>\r\n {slaCompliance.compliancePercentage.toFixed(1)}%\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.complianceRate')}</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\">{slaCompliance.ticketsWithinSla}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.withinSla')}</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-[var(--error-text)]\">{slaCompliance.ticketsBreached}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.breached')}</div>\r\n </div>\r\n <div className=\"space-y-2 p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"flex justify-between text-sm\">\r\n <span>{t('dashboard.avgResponse')}:</span>\r\n <span className=\"font-medium\">{formatDuration(slaCompliance.averageResponseMinutes)}</span>\r\n </div>\r\n <div className=\"flex justify-between text-sm\">\r\n <span>{t('dashboard.avgResolution')}:</span>\r\n <span className=\"font-medium\">{formatDuration(slaCompliance.averageResolutionMinutes)}</span>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Satisfaction */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4\">{t('dashboard.customerSatisfaction')}</h3>\r\n {satisfaction && (\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 ${getRatingColor(satisfaction.averageRating)}`}>\r\n {satisfaction.averageRating.toFixed(1)}\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.averageRating')}</div>\r\n <div className=\"flex justify-center mt-1\">\r\n {[1, 2, 3, 4, 5].map((star) => (\r\n <Star\r\n key={star}\r\n className={`w-4 h-4 ${star <= Math.round(satisfaction.averageRating)\r\n ? 'text-[var(--warning-text)] fill-[var(--warning-text)]'\r\n : 'text-[var(--text-muted)]'\r\n }`}\r\n />\r\n ))}\r\n </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\">{satisfaction.totalResponses}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('dashboard.totalResponses')}</div>\r\n </div>\r\n <div className=\"col-span-2 p-4 bg-[var(--bg-secondary)] rounded-lg\">\r\n <div className=\"text-sm font-medium mb-2\">{t('dashboard.ratingDistribution')}</div>\r\n <div className=\"space-y-1\">\r\n {[5, 4, 3, 2, 1].map((rating) => {\r\n const count = satisfaction.ratingDistribution[rating] || 0;\r\n const percentage =\r\n satisfaction.totalResponses > 0\r\n ? (count / satisfaction.totalResponses) * 100\r\n : 0;\r\n return (\r\n <div key={rating} className=\"flex items-center gap-2 text-sm\">\r\n <span className=\"w-4\">{rating}</span>\r\n <Star className=\"w-3 h-3 text-[var(--warning-text)] fill-[var(--warning-text)]\" />\r\n <div className=\"flex-1 h-3 bg-[var(--bg-primary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-[var(--warning-text)] rounded-full\"\r\n style={{ width: `${percentage}%` }}\r\n />\r\n </div>\r\n <span className=\"w-8 text-right text-xs\">{count}</span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n )}\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\">{t('dashboard.ticketTrends', { period })}</h3>\r\n <div className=\"h-64\">\r\n <TrendChart data={trends} t={t} />\r\n </div>\r\n </div>\r\n\r\n {/* Agent Workload */}\r\n <div className=\"card p-4\">\r\n <h3 className=\"font-semibold mb-4 flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('dashboard.agentWorkload')}\r\n </h3>\r\n {agentWorkload.length > 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\">{t('dashboard.agent')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.total')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.open')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.inProgress')}</th>\r\n <th className=\"text-center p-3 font-medium\">{t('dashboard.onHold')}</th>\r\n <th className=\"text-left p-3 font-medium\">{t('dashboard.load')}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {agentWorkload.map((agent) => {\r\n const maxLoad = Math.max(...agentWorkload.map((a) => a.totalAssigned));\r\n const loadPercentage = maxLoad > 0 ? (agent.totalAssigned / maxLoad) * 100 : 0;\r\n return (\r\n <tr key={agent.userId} className=\"border-b border-[var(--border-color)]\">\r\n <td className=\"p-3\">\r\n <div className=\"font-medium\">{agent.name}</div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">{agent.email}</div>\r\n </td>\r\n <td className=\"text-center p-3 font-semibold\">{agent.totalAssigned}</td>\r\n <td className=\"text-center p-3\">\r\n <span className=\"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm\">\r\n {agent.openCount}\r\n </span>\r\n </td>\r\n <td className=\"text-center p-3\">\r\n <span className=\"px-2 py-1 bg-[var(--info-bg)] text-[var(--info-text)] rounded-[var(--radius-badge)] text-sm\">\r\n {agent.inProgressCount}\r\n </span>\r\n </td>\r\n <td className=\"text-center p-3\">\r\n <span className=\"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm\">\r\n {agent.onHoldCount}\r\n </span>\r\n </td>\r\n <td className=\"p-3 w-32\">\r\n <div className=\"h-2 bg-[var(--bg-secondary)] rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-[var(--info-text)] rounded-full\"\r\n style={{ width: `${loadPercentage}%` }}\r\n />\r\n </div>\r\n </td>\r\n </tr>\r\n );\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 {t('dashboard.noAgentsAssigned')}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// KPI Card Component\r\nfunction KpiCard({\r\n title,\r\n value,\r\n icon,\r\n color,\r\n subtitle,\r\n trend,\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 trend?: { value: number; isUp: boolean };\r\n}) {\r\n const colorClasses = {\r\n blue: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n green: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n yellow: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n red: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\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 {trend && (\r\n <div className={`flex items-center gap-1 mt-1 text-xs ${trend.isUp ? 'text-[var(--success-text)]' : 'text-[var(--error-text)]'}`}>\r\n {trend.isUp ? <ArrowUp className=\"w-3 h-3\" /> : <ArrowDown className=\"w-3 h-3\" />}\r\n {trend.value}%\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// Simple Trend Chart Component\r\ntype TrendTFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\nfunction TrendChart({ data, t }: { data: TrendDataDto[]; t: TrendTFunction }) {\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 {t('dashboard.noTrendData')}\r\n </div>\r\n );\r\n }\r\n\r\n const maxValue = Math.max(...data.flatMap((d) => [d.created, d.resolved]), 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-[var(--info-text)]\" />\r\n <span className=\"text-sm\">{t('dashboard.created')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"w-3 h-3 rounded bg-[var(--success-text)]\" />\r\n <span className=\"text-sm\">{t('dashboard.resolved')}</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-[var(--info-text)] rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{ height: `${(item.created / maxValue) * 100}%`, minHeight: item.created > 0 ? '4px' : '0' }}\r\n title={`Created: ${item.created}`}\r\n />\r\n <div\r\n className=\"flex-1 bg-[var(--success-text)] rounded-t transition-all duration-300 hover:opacity-80\"\r\n style={{ height: `${(item.resolved / maxValue) * 100}%`, minHeight: item.resolved > 0 ? '4px' : '0' }}\r\n title={`Resolved: ${item.resolved}`}\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()}</span>\r\n <span>{data.at(-1) && new Date(data.at(-1)!.date).toLocaleDateString()}</span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// Format duration helper\r\nfunction formatDuration(minutes: number): string {\r\n if (minutes < 60) return `${Math.round(minutes)}m`;\r\n const hours = Math.floor(minutes / 60);\r\n const mins = Math.round(minutes % 60);\r\n if (hours < 24) return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;\r\n const days = Math.floor(hours / 24);\r\n const remainingHours = hours % 24;\r\n return remainingHours > 0 ? `${days}d ${remainingHours}h` : `${days}d`;\r\n}\r\n"],"names":["priorityColors","statusColors","DashboardPage","useTranslation","navigate","useNavigate","hasPermission","useAuth","isGlpi","glpiBaseUrl","useTicketingProvider","currentTenant","useTenant","loading","setLoading","useState","refreshing","setRefreshing","period","setPeriod","canViewSla","overview","setOverview","statusData","setStatusData","priorityData","setPriorityData","agentWorkload","setAgentWorkload","trends","setTrends","satisfaction","setSatisfaction","slaCompliance","setSlaCompliance","breachedTickets","setBreachedTickets","approachingBreach","setApproachingBreach","glpiSyncStats","setGlpiSyncStats","syncing","setSyncing","loadData","useCallback","overviewRes","statusRes","priorityRes","workloadRes","trendsRes","satisfactionRes","slaRes","dashboardApi","syncStats","supportApi","breachedRes","approachingRes","slaApi","error","useEffect","handleRefresh","handleTriggerSync","ticketingApi","jsx","Loader2","getComplianceColor","percentage","getRatingColor","rating","jsxs","Breadcrumb","PageHeader","LayoutDashboard","Fragment","e","RefreshCw","Info","ExternalLink","KpiCard","Headphones","TrendingUp","Clock","CheckCircle","AlertTriangle","Star","XCircle","ticket","item","total","sum","s","p","formatDuration","star","count","TrendChart","Users","agent","maxLoad","a","loadPercentage","title","value","icon","color","subtitle","trend","ArrowUp","ArrowDown","data","t","maxValue","d","minutes","hours","mins","days","remainingHours"],"mappings":"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"}
|