@atlashub/smartstack 3.30.0 → 3.31.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-CVq3qZoe.js → AgentSkillsPage-CDMhqrhE.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-CVq3qZoe.js.map → AgentSkillsPage-CDMhqrhE.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-DJb49NMA.js → AgentSkillsPage-DcvOMm5k.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-DJb49NMA.js.map → AgentSkillsPage-DcvOMm5k.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-D_nk3gKj.js → AgentWorkloadPage-DYBPNzjQ.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-D_nk3gKj.js.map → AgentWorkloadPage-DYBPNzjQ.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-oHEi-sFh.js → AgentWorkloadPage-YpJSDaWc.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-oHEi-sFh.js.map → AgentWorkloadPage-YpJSDaWc.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-Cr0q2HnB.js → ApiCatalogDetailPage-9r1axtCg.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-Cr0q2HnB.js.map → ApiCatalogDetailPage-9r1axtCg.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-DX8buBkV.js → ApiCatalogDetailPage-TjCQ8_A8.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-DX8buBkV.js.map → ApiCatalogDetailPage-TjCQ8_A8.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-DqboIzZE.js → ApiCatalogPage-COxazTnz.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-DqboIzZE.js.map → ApiCatalogPage-COxazTnz.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-DN7sazvI.js → ApiCatalogPage-QRysH0pT.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-DN7sazvI.js.map → ApiCatalogPage-QRysH0pT.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CCNjr64K.js → ApplicationDetailPage-Dbx01Ikm.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-CCNjr64K.js.map → ApplicationDetailPage-Dbx01Ikm.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage--9YwwS5A.js → ApplicationDetailPage-jSHy3MPz.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage--9YwwS5A.js.map → ApplicationDetailPage-jSHy3MPz.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-Bs-Xgca4.js → ApplicationsDashboardPage-CclKc0wI.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-Bs-Xgca4.js.map → ApplicationsDashboardPage-CclKc0wI.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BSsHN3Yj.js → ApplicationsDashboardPage-CxWmOc1x.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BSsHN3Yj.js.map → ApplicationsDashboardPage-CxWmOc1x.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-s1WEzOXS.js → ApplicationsGridPage-BJXWXwyI.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-s1WEzOXS.js.map → ApplicationsGridPage-BJXWXwyI.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-DDysNWJ5.js → ApplicationsGridPage-D2l8cM3o.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-DDysNWJ5.js.map → ApplicationsGridPage-D2l8cM3o.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B3CSMiV0.js → ApplicationsListPage-CMosl3my.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B3CSMiV0.js.map → ApplicationsListPage-CMosl3my.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B6ZCecIl.js → ApplicationsListPage-Dc6NGQ61.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B6ZCecIl.js.map → ApplicationsListPage-Dc6NGQ61.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BBaiBM--.js → ApplicationsPage-DH7tpMlF.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BBaiBM--.js.map → ApplicationsPage-DH7tpMlF.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-ztPwoAGt.js → ApplicationsPage-DI-iMqoJ.js} +4 -4
- package/dist/chunks/{ApplicationsPage-ztPwoAGt.js.map → ApplicationsPage-DI-iMqoJ.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-DFSVFFXr.js → AssignmentRulesPage-B5UbujbZ.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-DFSVFFXr.js.map → AssignmentRulesPage-B5UbujbZ.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CK4L4rBO.js → AssignmentRulesPage-E79QBSLb.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CK4L4rBO.js.map → AssignmentRulesPage-E79QBSLb.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-JCLpyg94.js → AssignmentsPage-CDFaL1gT.js} +2 -2
- package/dist/chunks/{AssignmentsPage-JCLpyg94.js.map → AssignmentsPage-CDFaL1gT.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-Bp7oQD7Q.js → AssignmentsPage-CPeKJjyK.js} +2 -2
- package/dist/chunks/{AssignmentsPage-Bp7oQD7Q.js.map → AssignmentsPage-CPeKJjyK.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-Bl9xlJ3h.js → AuthCallbackPage-BZ3Ocos5.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-Bl9xlJ3h.js.map → AuthCallbackPage-BZ3Ocos5.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-CzMHz4jy.js → AuthCallbackPage-Bml48QpH.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-CzMHz4jy.js.map → AuthCallbackPage-Bml48QpH.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-M7mJgXvn.js → ConfirmEmailPage-DP1XPaKK.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-M7mJgXvn.js.map → ConfirmEmailPage-DP1XPaKK.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-D_8T1vqV.js → ConfirmEmailPage-DyzslZ06.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-D_8T1vqV.js.map → ConfirmEmailPage-DyzslZ06.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-BNEGavlu.js → CreateSupportTicketPage-Bz2KrMik.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-BNEGavlu.js.map → CreateSupportTicketPage-Bz2KrMik.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-C2X2mfds.js → CreateSupportTicketPage-hKjKM0Bh.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-C2X2mfds.js.map → CreateSupportTicketPage-hKjKM0Bh.js.map} +1 -1
- package/dist/chunks/{DashboardPage-4oy2YqvT.js → DashboardPage-B4nAd8Tj.js} +2 -2
- package/dist/chunks/{DashboardPage-4oy2YqvT.js.map → DashboardPage-B4nAd8Tj.js.map} +1 -1
- package/dist/chunks/{DashboardPage-D5MRMxEV.js → DashboardPage-C9qgPBS-.js} +3 -3
- package/dist/chunks/{DashboardPage-D5MRMxEV.js.map → DashboardPage-C9qgPBS-.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CO-8B8EI.js → DashboardPage-CjbNGMo1.js} +3 -3
- package/dist/chunks/{DashboardPage-CO-8B8EI.js.map → DashboardPage-CjbNGMo1.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CPArUG-S.js → DashboardPage-rN7IFlTR.js} +2 -2
- package/dist/chunks/{DashboardPage-CPArUG-S.js.map → DashboardPage-rN7IFlTR.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-DnjLFXnL.js → EscalationConfigPage-CGv2L62M.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-DnjLFXnL.js.map → EscalationConfigPage-CGv2L62M.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CwdnfJbJ.js → EscalationConfigPage-DpYDmsgw.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CwdnfJbJ.js.map → EscalationConfigPage-DpYDmsgw.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-ZEIfyqwE.js → ForceChangePasswordPage-CLI_fpF4.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-ZEIfyqwE.js.map → ForceChangePasswordPage-CLI_fpF4.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-sh-3h_H9.js → ForceChangePasswordPage-Db6sOrZN.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-sh-3h_H9.js.map → ForceChangePasswordPage-Db6sOrZN.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-B4M6-xeM.js → ForgotPasswordPage-BhMz2B6A.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-B4M6-xeM.js.map → ForgotPasswordPage-BhMz2B6A.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-MIu-U7p0.js → ForgotPasswordPage-D06arMXO.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-MIu-U7p0.js.map → ForgotPasswordPage-D06arMXO.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-4XK3Bs_r.js → GroupDetailPage-BCM8KBCd.js} +5 -5
- package/dist/chunks/{GroupDetailPage-4XK3Bs_r.js.map → GroupDetailPage-BCM8KBCd.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-C-kvtd2T.js → GroupDetailPage-CGMV3bWt.js} +2 -2
- package/dist/chunks/{GroupDetailPage-C-kvtd2T.js.map → GroupDetailPage-CGMV3bWt.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-CP41FzHi.js → MyAccessRequestsPage-BBrwEomx.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-CP41FzHi.js.map → MyAccessRequestsPage-BBrwEomx.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-DzrXTrVi.js → MyAccessRequestsPage-CrlWe3gd.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-DzrXTrVi.js.map → MyAccessRequestsPage-CrlWe3gd.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-V_SwYio2.js → MyTenantsPage-BOV34_rJ.js} +3 -3
- package/dist/chunks/{MyTenantsPage-V_SwYio2.js.map → MyTenantsPage-BOV34_rJ.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-CZRkMbh8.js → MyTenantsPage-CK4-klmd.js} +2 -2
- package/dist/chunks/{MyTenantsPage-CZRkMbh8.js.map → MyTenantsPage-CK4-klmd.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DnvAIeyr.js → MyTicketsPage-CFZ1G4dG.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DnvAIeyr.js.map → MyTicketsPage-CFZ1G4dG.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DOUhaLal.js → MyTicketsPage-DuhpwhZx.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DOUhaLal.js.map → MyTicketsPage-DuhpwhZx.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-DfTa4jCG.js → NavigationAppsPage-BnNQRfBP.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-DfTa4jCG.js.map → NavigationAppsPage-BnNQRfBP.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-DXvpLsbt.js → NavigationAppsPage-DdJxEoTZ.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-DXvpLsbt.js.map → NavigationAppsPage-DdJxEoTZ.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-I1yCk7tk.js → NotificationsPage-BllOlagk.js} +2 -2
- package/dist/chunks/{NotificationsPage-I1yCk7tk.js.map → NotificationsPage-BllOlagk.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-D76MdAs-.js → NotificationsPage-D1T_ozHl.js} +2 -2
- package/dist/chunks/{NotificationsPage-D76MdAs-.js.map → NotificationsPage-D1T_ozHl.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-BRUzcl1A.js → OnboardingWizardPage-CioLaCYz.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-BRUzcl1A.js.map → OnboardingWizardPage-CioLaCYz.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-DtWUPCh3.js → OnboardingWizardPage-CrAQt7qL.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-DtWUPCh3.js.map → OnboardingWizardPage-CrAQt7qL.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-CUNKbl7t.js → PermissionDetailPage-BIG78-1-.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-CUNKbl7t.js.map → PermissionDetailPage-BIG78-1-.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-DJJGbXoX.js → PermissionDetailPage-CvPqugYu.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-DJJGbXoX.js.map → PermissionDetailPage-CvPqugYu.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-B8wmawPV.js → PermissionsPage-CDSuc8vw.js} +2 -2
- package/dist/chunks/{PermissionsPage-B8wmawPV.js.map → PermissionsPage-CDSuc8vw.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-Dbjcctuh.js → PermissionsPage-XaOrGrPZ.js} +2 -2
- package/dist/chunks/{PermissionsPage-Dbjcctuh.js.map → PermissionsPage-XaOrGrPZ.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-BeNfBZmb.js → PortalDashboardPage-BsWVXkMe.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-BeNfBZmb.js.map → PortalDashboardPage-BsWVXkMe.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-zii0ll57.js → PortalDashboardPage-oSD7oQhJ.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-zii0ll57.js.map → PortalDashboardPage-oSD7oQhJ.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BCpuIGzv.js → PreferencesPage-DD0_XWdT.js} +2 -2
- package/dist/chunks/{PreferencesPage-BCpuIGzv.js.map → PreferencesPage-DD0_XWdT.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BmvrBaAD.js → PreferencesPage-ca2BOdoH.js} +2 -2
- package/dist/chunks/{PreferencesPage-BmvrBaAD.js.map → PreferencesPage-ca2BOdoH.js.map} +1 -1
- package/dist/chunks/{ProfilePage-mf5wI0-n.js → ProfilePage-Bex_JN5N.js} +2 -2
- package/dist/chunks/{ProfilePage-mf5wI0-n.js.map → ProfilePage-Bex_JN5N.js.map} +1 -1
- package/dist/chunks/{ProfilePage-eowQd59_.js → ProfilePage-C8tUIOnb.js} +2 -2
- package/dist/chunks/{ProfilePage-eowQd59_.js.map → ProfilePage-C8tUIOnb.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-CLsaUNqA.js → ReferencesManagementPage-B-FXS2ln.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-CLsaUNqA.js.map → ReferencesManagementPage-B-FXS2ln.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-8UPgkVE8.js → ReferencesManagementPage-C8KZprkI.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-8UPgkVE8.js.map → ReferencesManagementPage-C8KZprkI.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CNyHSbqs.js → RegisterPage-BYt__zKJ.js} +2 -2
- package/dist/chunks/{RegisterPage-CNyHSbqs.js.map → RegisterPage-BYt__zKJ.js.map} +1 -1
- package/dist/chunks/{RegisterPage-57X-ILDb.js → RegisterPage-MWcVu-LY.js} +2 -2
- package/dist/chunks/{RegisterPage-57X-ILDb.js.map → RegisterPage-MWcVu-LY.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-CyV8l-Zo.js → ResetPasswordPage-DaJiMj5Z.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-CyV8l-Zo.js.map → ResetPasswordPage-DaJiMj5Z.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-JW8-mh_k.js → ResetPasswordPage-rCLUIj_T.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-JW8-mh_k.js.map → ResetPasswordPage-rCLUIj_T.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-CjwE73NX.js → ResolutionModal-DeuPnLWg.js} +2 -2
- package/dist/chunks/{ResolutionModal-CjwE73NX.js.map → ResolutionModal-DeuPnLWg.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-wddG59kg.js → ResolutionModal-j7Rp6apG.js} +2 -2
- package/dist/chunks/{ResolutionModal-wddG59kg.js.map → ResolutionModal-j7Rp6apG.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CrioVHFI.js → RoleDetailPage-CLtZWX17.js} +3 -3
- package/dist/chunks/{RoleDetailPage-CrioVHFI.js.map → RoleDetailPage-CLtZWX17.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-TUOGR1ow.js → RoleDetailPage-TGyGmLMM.js} +2 -2
- package/dist/chunks/{RoleDetailPage-TUOGR1ow.js.map → RoleDetailPage-TGyGmLMM.js.map} +1 -1
- package/dist/chunks/{RolesPage-sJBWaNff.js → RolesPage-C0c5G9e7.js} +2 -2
- package/dist/chunks/{RolesPage-sJBWaNff.js.map → RolesPage-C0c5G9e7.js.map} +1 -1
- package/dist/chunks/{RolesPage-CAcols3D.js → RolesPage-Dm03fBBf.js} +2 -2
- package/dist/chunks/{RolesPage-CAcols3D.js.map → RolesPage-Dm03fBBf.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BPGRloOS.js → SlaConfigPage-B4WDzEKi.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BPGRloOS.js.map → SlaConfigPage-B4WDzEKi.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-D5TRn7Ir.js → SlaConfigPage-Cwo9NwxH.js} +2 -2
- package/dist/chunks/{SlaConfigPage-D5TRn7Ir.js.map → SlaConfigPage-Cwo9NwxH.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-UXmYLrIq.js → SupportPermissionsPage-CL12dFy-.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-UXmYLrIq.js.map → SupportPermissionsPage-CL12dFy-.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-Dc2bWTzG.js → SupportPermissionsPage-CneIhl30.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-Dc2bWTzG.js.map → SupportPermissionsPage-CneIhl30.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-nTY85sNA.js → TemplatesPage-DStKmwHT.js} +2 -2
- package/dist/chunks/{TemplatesPage-nTY85sNA.js.map → TemplatesPage-DStKmwHT.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-dmPlqqiD.js → TemplatesPage-X4Rrhs9p.js} +2 -2
- package/dist/chunks/{TemplatesPage-dmPlqqiD.js.map → TemplatesPage-X4Rrhs9p.js.map} +1 -1
- package/dist/chunks/{TenantCard-BhT-31ls.js → TenantCard-BUBYWtvR.js} +2 -2
- package/dist/chunks/{TenantCard-BhT-31ls.js.map → TenantCard-BUBYWtvR.js.map} +1 -1
- package/dist/chunks/{TenantCard-BUXfstRZ.js → TenantCard-CAgiB-NG.js} +2 -2
- package/dist/chunks/{TenantCard-BUXfstRZ.js.map → TenantCard-CAgiB-NG.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-3_mzBLNI.js → TenantScopeSelector-B9vtpIZx.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-3_mzBLNI.js.map → TenantScopeSelector-B9vtpIZx.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-B-SRDR2R.js → TenantScopeSelector-BAoah-mL.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-B-SRDR2R.js.map → TenantScopeSelector-BAoah-mL.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-xN3wPnFL.js → TicketDetailPage-BFcP4X8s.js} +2 -2
- package/dist/chunks/{TicketDetailPage-xN3wPnFL.js.map → TicketDetailPage-BFcP4X8s.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-B4cR3rOC.js → TicketDetailPage-D_Npnt4A.js} +2 -2
- package/dist/chunks/{TicketDetailPage-B4cR3rOC.js.map → TicketDetailPage-D_Npnt4A.js.map} +1 -1
- package/dist/chunks/{TicketsPage-Dwi2xpMI.js → TicketsPage-DBP9kalU.js} +2 -2
- package/dist/chunks/{TicketsPage-Dwi2xpMI.js.map → TicketsPage-DBP9kalU.js.map} +1 -1
- package/dist/chunks/{TicketsPage-CkHgXSxU.js → TicketsPage-p21DLhUb.js} +2 -2
- package/dist/chunks/{TicketsPage-CkHgXSxU.js.map → TicketsPage-p21DLhUb.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-D2a3EOey.js → UserCreateTicketPage-DOwShnG8.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-D2a3EOey.js.map → UserCreateTicketPage-DOwShnG8.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-bcbSLglE.js → UserCreateTicketPage-lvlvp2u6.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-bcbSLglE.js.map → UserCreateTicketPage-lvlvp2u6.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-ZMsx8LWw.js → UserDashboardPage-C_tm7Pld.js} +2 -2
- package/dist/chunks/{UserDashboardPage-ZMsx8LWw.js.map → UserDashboardPage-C_tm7Pld.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-DwnDRNoW.js → UserDashboardPage-Dp6q6FEW.js} +2 -2
- package/dist/chunks/{UserDashboardPage-DwnDRNoW.js.map → UserDashboardPage-Dp6q6FEW.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-CZyV-zsg.js → UserDetailPage-6grZ6gmV.js} +5 -5
- package/dist/chunks/{UserDetailPage-CZyV-zsg.js.map → UserDetailPage-6grZ6gmV.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BRFowOFL.js → UserDetailPage-DXLxO7LF.js} +2 -2
- package/dist/chunks/{UserDetailPage-BRFowOFL.js.map → UserDetailPage-DXLxO7LF.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-BstGk_BP.js → UserTicketDetailPage-Ch9IfCPo.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-BstGk_BP.js.map → UserTicketDetailPage-Ch9IfCPo.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-DzB_pELt.js → UserTicketDetailPage-a4II5VEE.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-DzB_pELt.js.map → UserTicketDetailPage-a4II5VEE.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-BygTv_kK.js → UsersGroupsPage-B7Er0V4l.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-BygTv_kK.js.map → UsersGroupsPage-B7Er0V4l.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-DTmhzttW.js → UsersGroupsPage-BeAv4QfV.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-DTmhzttW.js.map → UsersGroupsPage-BeAv4QfV.js.map} +1 -1
- package/dist/chunks/{UsersPage-DcwLyMAX.js → UsersPage-0M1FLqOe.js} +2 -2
- package/dist/chunks/{UsersPage-DcwLyMAX.js.map → UsersPage-0M1FLqOe.js.map} +1 -1
- package/dist/chunks/{UsersPage-TIqSHgHj.js → UsersPage-ZR9r9vvf.js} +2 -2
- package/dist/chunks/{UsersPage-TIqSHgHj.js.map → UsersPage-ZR9r9vvf.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-3FjMFbpa.js → accessRequestsApi-BJH8EE1K.js} +2 -2
- package/dist/chunks/{accessRequestsApi-3FjMFbpa.js.map → accessRequestsApi-BJH8EE1K.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-B6dsJzvH.js → accessRequestsApi-CBpF5d54.js} +2 -2
- package/dist/chunks/{accessRequestsApi-B6dsJzvH.js.map → accessRequestsApi-CBpF5d54.js.map} +1 -1
- package/dist/chunks/{aiApi-9G4wG_mT.js → aiApi-CkkWAvNB.js} +2 -2
- package/dist/chunks/{aiApi-9G4wG_mT.js.map → aiApi-CkkWAvNB.js.map} +1 -1
- package/dist/chunks/{aiApi-DXOdsoxr.js → aiApi-Dl7a2lWz.js} +2 -2
- package/dist/chunks/{aiApi-DXOdsoxr.js.map → aiApi-Dl7a2lWz.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-DhOd6idI.js → applicationAnalyticsApi-BwcSE_H1.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-DhOd6idI.js.map → applicationAnalyticsApi-BwcSE_H1.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-D0DEp9Y-.js → applicationAnalyticsApi-DKMmDvWk.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-D0DEp9Y-.js.map → applicationAnalyticsApi-DKMmDvWk.js.map} +1 -1
- package/dist/chunks/{groupsApi-Db8G2lLs.js → groupsApi-BzDV3_Jc.js} +2 -2
- package/dist/chunks/{groupsApi-Db8G2lLs.js.map → groupsApi-BzDV3_Jc.js.map} +1 -1
- package/dist/chunks/{groupsApi-lbxNsHFv.js → groupsApi-CQ4vFMdP.js} +2 -2
- package/dist/chunks/{groupsApi-lbxNsHFv.js.map → groupsApi-CQ4vFMdP.js.map} +1 -1
- package/dist/chunks/{index-DEtq-xUL.js → index-BBmMbSZV.js} +8 -8
- package/dist/chunks/{index-DEtq-xUL.js.map → index-BBmMbSZV.js.map} +1 -1
- package/dist/chunks/{index-D0HS542b.js → index-BLlESTfA.js} +2 -2
- package/dist/chunks/{index-D0HS542b.js.map → index-BLlESTfA.js.map} +1 -1
- package/dist/chunks/{index-DUS-tunb.js → index-BPMjxWVx.js} +2 -2
- package/dist/chunks/{index-DUS-tunb.js.map → index-BPMjxWVx.js.map} +1 -1
- package/dist/chunks/{index-TiWOcC0g.js → index-CEbwdURd.js} +2 -2
- package/dist/chunks/{index-TiWOcC0g.js.map → index-CEbwdURd.js.map} +1 -1
- package/dist/chunks/{index-DF93KQFR.js → index-CUZygY5Q.js} +2 -2
- package/dist/chunks/{index-DF93KQFR.js.map → index-CUZygY5Q.js.map} +1 -1
- package/dist/chunks/{index-BI2dc1FS.js → index-Ci1SqFiY.js} +2 -2
- package/dist/chunks/{index-BI2dc1FS.js.map → index-Ci1SqFiY.js.map} +1 -1
- package/dist/chunks/{index-CTGSmYvs.js → index-Cib93xtp.js} +2 -2
- package/dist/chunks/{index-CTGSmYvs.js.map → index-Cib93xtp.js.map} +1 -1
- package/dist/chunks/{index-DqbVFB1H.js → index-CoHIgn5H.js} +2 -2
- package/dist/chunks/{index-DqbVFB1H.js.map → index-CoHIgn5H.js.map} +1 -1
- package/dist/chunks/{index-CN2WRyg1.js → index-CpY95_ro.js} +294 -292
- package/dist/chunks/{index-CN2WRyg1.js.map → index-CpY95_ro.js.map} +1 -1
- package/dist/chunks/{index-DjC1u2hI.js → index-D-2xSu5W.js} +3 -3
- package/dist/chunks/{index-DjC1u2hI.js.map → index-D-2xSu5W.js.map} +1 -1
- package/dist/chunks/{index-Bn8HzILk.js → index-D18t9DhC.js} +4 -4
- package/dist/chunks/{index-Bn8HzILk.js.map → index-D18t9DhC.js.map} +1 -1
- package/dist/chunks/{index-cAikSVW0.js → index-DK5czlkn.js} +9 -9
- package/dist/chunks/{index-cAikSVW0.js.map → index-DK5czlkn.js.map} +1 -1
- package/dist/chunks/{index-DLekpNSE.js → index-DQd324n7.js} +2 -2
- package/dist/chunks/{index-DLekpNSE.js.map → index-DQd324n7.js.map} +1 -1
- package/dist/chunks/{index-CgtbaFf5.js → index-Dbq-x5H9.js} +2 -2
- package/dist/chunks/{index-CgtbaFf5.js.map → index-Dbq-x5H9.js.map} +1 -1
- package/dist/chunks/{index-xhRXN1Jq.js → index-Det9dEaQ.js} +2 -2
- package/dist/chunks/{index-xhRXN1Jq.js.map → index-Det9dEaQ.js.map} +1 -1
- package/dist/chunks/{index-HsAOBno4.js → index-bgT9XOKZ.js} +2 -2
- package/dist/chunks/{index-HsAOBno4.js.map → index-bgT9XOKZ.js.map} +1 -1
- package/dist/chunks/{index-CUICSveU.js → index-h7ZrwrQg.js} +2 -2
- package/dist/chunks/{index-CUICSveU.js.map → index-h7ZrwrQg.js.map} +1 -1
- package/dist/chunks/{index-DwqLhQ8S.js → index-k4USDz2P.js} +2 -2
- package/dist/chunks/{index-DwqLhQ8S.js.map → index-k4USDz2P.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-CHeS7oLt.js → tenantIconMap-7ihIWxAh.js} +2 -2
- package/dist/chunks/{tenantIconMap-CHeS7oLt.js.map → tenantIconMap-7ihIWxAh.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-__FKj6CN.js → tenantIconMap-Dk6K-UTE.js} +2 -2
- package/dist/chunks/{tenantIconMap-__FKj6CN.js.map → tenantIconMap-Dk6K-UTE.js.map} +1 -1
- package/dist/chunks/{ticketingApi-DF4RwD_6.js → ticketingApi-BCMKkzlv.js} +2 -2
- package/dist/chunks/{ticketingApi-DF4RwD_6.js.map → ticketingApi-BCMKkzlv.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Cj239hYB.js → ticketingApi-Dwn7pl5z.js} +2 -2
- package/dist/chunks/{ticketingApi-Cj239hYB.js.map → ticketingApi-Dwn7pl5z.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CFam8zFR.js → useAccessRequests-Du7CvowE.js} +3 -3
- package/dist/chunks/{useAccessRequests-CFam8zFR.js.map → useAccessRequests-Du7CvowE.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CViOUwyF.js → useAccessRequests-gJ7yhWyi.js} +2 -2
- package/dist/chunks/{useAccessRequests-CViOUwyF.js.map → useAccessRequests-gJ7yhWyi.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-CslSQeBJ.js → useUserAccessRequests-5wWea2Jg.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-CslSQeBJ.js.map → useUserAccessRequests-5wWea2Jg.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-B-Cs6NX1.js → useUserAccessRequests-Bk_v8egy.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-B-Cs6NX1.js.map → useUserAccessRequests-Bk_v8egy.js.map} +1 -1
- package/dist/components/routing/ProtectedRoute.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/package.json +1 -1
|
@@ -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-CpY95_ro.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-BCMKkzlv.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-CjbNGMo1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage-CO-8B8EI.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-CjbNGMo1.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,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("react"),se=require("react-router-dom"),ae=require("react-i18next"),c=require("./index-cAikSVW0.js"),r=require("lucide-react"),te=require("./ticketingApi-Cj239hYB.js"),re={Low:"var(--info-text)",Medium:"var(--warning-text)",High:"var(--warning-text)",Critical:"var(--error-text)"},ne={Open:"var(--warning-text)",InProgress:"var(--info-text)",OnHold:"var(--warning-text)",Resolved:"var(--success-text)",Closed:"var(--text-secondary)",Rejected:"var(--error-text)"};function ce(){const{t:s}=ae.useTranslation("support"),l=se.useNavigate(),{hasPermission:o}=c.useAuth(),{isGlpi:t,glpiBaseUrl:m}=c.useTicketingProvider(),{currentTenant:p}=c.useTenant(),[k,L]=n.useState(!0),[$,A]=n.useState(!1),[x,E]=n.useState(30),R=o("support.sla.read"),[v,I]=n.useState(null),[P,H]=n.useState([]),[D,q]=n.useState([]),[C,G]=n.useState([]),[F,O]=n.useState([]),[g,U]=n.useState(null),[u,W]=n.useState(null),[N,V]=n.useState([]),[y,z]=n.useState([]),[i,K]=n.useState(null),[w,B]=n.useState(!1),S=n.useCallback(async()=>{try{const[a,d,h,b,f,Y,Z]=await Promise.all([c.dashboardApi.getOverview(x),c.dashboardApi.getByStatus(),c.dashboardApi.getByPriority(),c.dashboardApi.getAgentWorkload(),c.dashboardApi.getTrends(x),c.dashboardApi.getSatisfactionStats(x),c.dashboardApi.getSlaCompliance(x)]);if(I(a),H(d),q(h),G(b),O(f),U(Y),W(Z),t)try{const T=await c.supportApi.tickets.getGlpiSyncStats();K(T)}catch{}if(R){const[T,ee]=await Promise.all([c.slaApi.getBreachedTickets(),c.slaApi.getTicketsApproachingBreach(60)]);V(T),z(ee)}}catch(a){console.error("Failed to load dashboard data:",a)}finally{L(!1),A(!1)}},[x,R,t]);n.useEffect(()=>{S()},[S]);const X=()=>{A(!0),S()},_=async()=>{if(!(!p?.id||w)){B(!0);try{await te.ticketingApi.triggerSync(p.id),await S()}catch{}finally{B(!1)}}};if(k)return e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(r.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-primary-600)]"})});const J=a=>a>=95?"text-[var(--success-text)]":a>=80?"text-[var(--warning-text)]":"text-[var(--error-text)]",Q=a=>a>=4?"text-[var(--success-text)]":a>=3?"text-[var(--warning-text)]":"text-[var(--error-text)]";return e.jsxs("div",{className:"space-y-6",children:[e.jsx(c.Breadcrumb,{items:[{label:s("title","Support"),href:"/support"},{label:s("dashboard.title","Dashboard")}]}),e.jsx(c.PageHeader,{title:s("dashboard.title"),subtitle:s("dashboard.subtitle"),icon:e.jsx(r.LayoutDashboard,{className:"w-6 h-6"}),actions:e.jsxs(e.Fragment,{children:[e.jsxs("select",{value:x,onChange:a=>E(Number(a.target.value)),className:"input",children:[e.jsx("option",{value:7,children:s("dashboard.period7")}),e.jsx("option",{value:30,children:s("dashboard.period30")}),e.jsx("option",{value:90,children:s("dashboard.period90")})]}),e.jsxs("button",{onClick:X,disabled:$,className:"btn btn-secondary flex items-center gap-2",children:[e.jsx(r.RefreshCw,{className:`w-4 h-4 ${$?"animate-spin":""}`}),s("dashboard.refresh")]})]})}),t&&e.jsxs("div",{className:"flex items-center gap-3 p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] text-[var(--info-text)]",children:[e.jsx(r.Info,{className:"w-5 h-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"font-medium",children:s("glpi.managedByGlpi")}),e.jsx("p",{className:"text-sm opacity-80",children:s("glpi.dashboardSyncInfo")})]}),m&&e.jsxs("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"btn btn-secondary flex items-center gap-2 text-sm",children:[e.jsx(r.ExternalLink,{className:"w-4 h-4"}),s("glpi.openGlpi")]})]}),t&&i&&e.jsxs("div",{className:"card p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"font-semibold flex items-center gap-2",children:[e.jsx(r.RefreshCw,{className:"w-5 h-5"}),s("glpi.sync.title","GLPI Sync Status")]}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:s("glpi.sync.subtitle","Synchronization overview with GLPI")})]}),e.jsxs("button",{onClick:_,disabled:w,className:"btn btn-secondary flex items-center gap-2",children:[e.jsx(r.RefreshCw,{className:`w-4 h-4 ${w?"animate-spin":""}`}),w?s("glpi.sync.syncing","Syncing..."):s("glpi.sync.triggerSync","Sync Now")]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:[e.jsxs("div",{className:"card p-4 text-center border bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]",children:[e.jsx("div",{className:"text-2xl font-bold",children:i.totalMappedTickets}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.totalSynced","Total Synced")})]}),e.jsxs("div",{className:"card p-4 text-center border bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]",children:[e.jsx("div",{className:"text-2xl font-bold",children:i.ticketsSyncedOk}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.syncSuccess","Successful")})]}),e.jsxs("div",{className:"card p-4 text-center border bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]",children:[e.jsx("div",{className:"text-2xl font-bold",children:i.ticketsWithSyncErrors}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.syncErrors","Errors")})]}),e.jsxs("div",{className:`card p-4 text-center border ${i.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)]"}`,children:[e.jsxs("div",{className:"text-2xl font-bold",children:[i.successRate,"%"]}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.successRate","Success Rate")})]})]}),e.jsxs("div",{className:"flex items-center gap-6 text-sm text-[var(--text-secondary)]",children:[e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[s("glpi.sync.lastSync","Last Sync"),":"]})," ",i.lastSyncAt?new Date(i.lastSyncAt).toLocaleString():s("glpi.sync.never","Never")]}),e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[s("glpi.sync.syncInterval","Interval"),":"]})," ",s("glpi.sync.everyNMinutes","Every {{n}} min",{n:i.syncIntervalMinutes})]}),e.jsx("div",{children:e.jsx("span",{className:`px-2 py-0.5 rounded text-xs font-medium ${i.syncEnabled?"bg-[var(--success-bg)] text-[var(--success-text)]":"bg-[var(--bg-secondary)] text-[var(--text-secondary)]"}`,children:i.syncEnabled?s("glpi.sync.enabled","Enabled"):s("glpi.sync.disabled","Disabled")})})]}),i.lastSyncError&&e.jsxs("div",{className:"p-3 rounded-lg bg-[var(--error-bg)] border border-[var(--error-border)]",children:[e.jsx("p",{className:"text-sm font-medium text-[var(--error-text)]",children:s("glpi.sync.lastError","Last Sync Error")}),e.jsx("p",{className:"text-sm text-[var(--error-text)] opacity-80 mt-1",children:i.lastSyncError})]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4",children:[e.jsx(j,{title:s("dashboard.totalTickets"),value:v?.totalTickets??0,icon:e.jsx(r.Headphones,{className:"w-5 h-5"}),color:"blue"}),e.jsx(j,{title:s("dashboard.newTickets"),value:v?.newTickets??0,icon:e.jsx(r.TrendingUp,{className:"w-5 h-5"}),color:"green",subtitle:s("dashboard.lastNDays",{period:x})}),e.jsx(j,{title:s("dashboard.openTickets"),value:v?.openTickets??0,icon:e.jsx(r.Clock,{className:"w-5 h-5"}),color:"yellow"}),e.jsx(j,{title:s("dashboard.resolvedTickets"),value:v?.resolvedTickets??0,icon:e.jsx(r.CheckCircle,{className:"w-5 h-5"}),color:"green",subtitle:s("dashboard.lastNDays",{period:x})}),e.jsx(j,{title:s("dashboard.slaCompliance"),value:`${v?.slaCompliancePercentage?.toFixed(1)??0}%`,icon:e.jsx(r.AlertTriangle,{className:"w-5 h-5"}),color:(v?.slaCompliancePercentage??0)>=90?"green":"red"}),e.jsx(j,{title:s("dashboard.avgSatisfaction"),value:`${v?.averageSatisfaction?.toFixed(1)??0}/5`,icon:e.jsx(r.Star,{className:"w-5 h-5"}),color:(v?.averageSatisfaction??0)>=4?"green":"yellow"})]}),R&&(N.length>0||y.length>0)&&e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[N.length>0&&e.jsxs("div",{className:"card p-4 border-l-4 border-[var(--error-border)]",children:[e.jsxs("h3",{className:"font-semibold text-[var(--error-text)] flex items-center gap-2 mb-3",children:[e.jsx(r.XCircle,{className:"w-5 h-5"}),s("dashboard.slaBreached")," (",N.length,")"]}),e.jsx("div",{className:"space-y-2 max-h-40 overflow-y-auto",children:N.slice(0,5).map(a=>e.jsxs("button",{type:"button",className:"w-full flex items-center justify-between p-2 bg-[var(--error-bg)] rounded cursor-pointer hover:opacity-80 text-left",onClick:()=>l(`/support/tickets/${a.ticketId}`),children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-mono text-sm",children:a.ticketNumber}),e.jsx("span",{className:"ml-2 text-sm",children:a.ticketTitle})]}),e.jsxs("span",{className:"text-xs text-[var(--error-text)] font-medium",children:[a.responseBreached&&"Response"," ",a.resolutionBreached&&"Resolution"]})]},a.id))})]}),y.length>0&&e.jsxs("div",{className:"card p-4 border-l-4 border-[var(--warning-border)]",children:[e.jsxs("h3",{className:"font-semibold text-[var(--warning-text)] flex items-center gap-2 mb-3",children:[e.jsx(r.AlertTriangle,{className:"w-5 h-5"}),s("dashboard.approachingBreach")," (",y.length,")"]}),e.jsx("div",{className:"space-y-2 max-h-40 overflow-y-auto",children:y.slice(0,5).map(a=>e.jsxs("button",{type:"button",className:"w-full flex items-center justify-between p-2 bg-[var(--warning-bg)] rounded cursor-pointer hover:opacity-80 text-left",onClick:()=>l(`/support/tickets/${a.ticketId}`),children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-mono text-sm",children:a.ticketNumber}),e.jsx("span",{className:"ml-2 text-sm",children:a.ticketTitle})]}),e.jsxs("span",{className:"text-xs text-[var(--warning-text)] font-medium",children:[Math.round(a.responseSlaPercentage),"% Response"]})]},a.id))})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.ticketsByStatus")}),e.jsx("div",{className:"space-y-3",children:P.map(a=>{const d=P.reduce((b,f)=>b+f.count,0),h=d>0?a.count/d*100:0;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:a.status}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${h}%`,backgroundColor:ne[a.status]||"#6b7280"}})}),e.jsx("div",{className:"w-16 text-right text-sm font-medium",children:a.count})]},a.status)})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.activeTicketsByPriority")}),e.jsx("div",{className:"space-y-3",children:D.map(a=>{const d=D.reduce((b,f)=>b+f.count,0),h=d>0?a.count/d*100:0;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:a.priority}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${h}%`,backgroundColor:re[a.priority]||"#6b7280"}})}),e.jsx("div",{className:"w-16 text-right text-sm font-medium",children:a.count})]},a.priority)})})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.slaPerformance")}),u&&e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:`text-3xl font-bold ${J(u.compliancePercentage)}`,children:[u.compliancePercentage.toFixed(1),"%"]}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.complianceRate")})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold",children:u.ticketsWithinSla}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.withinSla")})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-[var(--error-text)]",children:u.ticketsBreached}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.breached")})]}),e.jsxs("div",{className:"space-y-2 p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsxs("span",{children:[s("dashboard.avgResponse"),":"]}),e.jsx("span",{className:"font-medium",children:M(u.averageResponseMinutes)})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsxs("span",{children:[s("dashboard.avgResolution"),":"]}),e.jsx("span",{className:"font-medium",children:M(u.averageResolutionMinutes)})]})]})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.customerSatisfaction")}),g&&e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:`text-3xl font-bold ${Q(g.averageRating)}`,children:g.averageRating.toFixed(1)}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.averageRating")}),e.jsx("div",{className:"flex justify-center mt-1",children:[1,2,3,4,5].map(a=>e.jsx(r.Star,{className:`w-4 h-4 ${a<=Math.round(g.averageRating)?"text-[var(--warning-text)] fill-[var(--warning-text)]":"text-[var(--text-muted)]"}`},a))})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold",children:g.totalResponses}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.totalResponses")})]}),e.jsxs("div",{className:"col-span-2 p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-sm font-medium mb-2",children:s("dashboard.ratingDistribution")}),e.jsx("div",{className:"space-y-1",children:[5,4,3,2,1].map(a=>{const d=g.ratingDistribution[a]||0,h=g.totalResponses>0?d/g.totalResponses*100:0;return e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx("span",{className:"w-4",children:a}),e.jsx(r.Star,{className:"w-3 h-3 text-[var(--warning-text)] fill-[var(--warning-text)]"}),e.jsx("div",{className:"flex-1 h-3 bg-[var(--bg-primary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full bg-[var(--warning-text)] rounded-full",style:{width:`${h}%`}})}),e.jsx("span",{className:"w-8 text-right text-xs",children:d})]},a)})})]})]})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.ticketTrends",{period:x})}),e.jsx("div",{className:"h-64",children:e.jsx(le,{data:F,t:s})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(r.Users,{className:"w-5 h-5"}),s("dashboard.agentWorkload")]}),C.length>0?e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[var(--border-color)]",children:[e.jsx("th",{className:"text-left p-3 font-medium",children:s("dashboard.agent")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.total")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.open")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.inProgress")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.onHold")}),e.jsx("th",{className:"text-left p-3 font-medium",children:s("dashboard.load")})]})}),e.jsx("tbody",{children:C.map(a=>{const d=Math.max(...C.map(b=>b.totalAssigned)),h=d>0?a.totalAssigned/d*100:0;return e.jsxs("tr",{className:"border-b border-[var(--border-color)]",children:[e.jsxs("td",{className:"p-3",children:[e.jsx("div",{className:"font-medium",children:a.name}),e.jsx("div",{className:"text-xs text-[var(--text-secondary)]",children:a.email})]}),e.jsx("td",{className:"text-center p-3 font-semibold",children:a.totalAssigned}),e.jsx("td",{className:"text-center p-3",children:e.jsx("span",{className:"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm",children:a.openCount})}),e.jsx("td",{className:"text-center p-3",children:e.jsx("span",{className:"px-2 py-1 bg-[var(--info-bg)] text-[var(--info-text)] rounded-[var(--radius-badge)] text-sm",children:a.inProgressCount})}),e.jsx("td",{className:"text-center p-3",children:e.jsx("span",{className:"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm",children:a.onHoldCount})}),e.jsx("td",{className:"p-3 w-32",children:e.jsx("div",{className:"h-2 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full bg-[var(--info-text)] rounded-full",style:{width:`${h}%`}})})})]},a.userId)})})]})}):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:s("dashboard.noAgentsAssigned")})]})]})}function j({title:s,value:l,icon:o,color:t,subtitle:m,trend:p}){const k={blue:"bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]",green:"bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]",yellow:"bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]",red:"bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]"};return e.jsxs("div",{className:`card p-4 border ${k[t]}`,children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium opacity-80",children:s}),o]}),e.jsx("div",{className:"text-2xl font-bold",children:l}),m&&e.jsx("div",{className:"text-xs opacity-70 mt-1",children:m}),p&&e.jsxs("div",{className:`flex items-center gap-1 mt-1 text-xs ${p.isUp?"text-[var(--success-text)]":"text-[var(--error-text)]"}`,children:[p.isUp?e.jsx(r.ArrowUp,{className:"w-3 h-3"}):e.jsx(r.ArrowDown,{className:"w-3 h-3"}),p.value,"%"]})]})}function le({data:s,t:l}){if(s.length===0)return e.jsx("div",{className:"flex items-center justify-center h-full text-[var(--text-secondary)]",children:l("dashboard.noTrendData")});const o=Math.max(...s.flatMap(t=>[t.created,t.resolved]),1);return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"flex items-center gap-4 mb-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-[var(--info-text)]"}),e.jsx("span",{className:"text-sm",children:l("dashboard.created")})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-[var(--success-text)]"}),e.jsx("span",{className:"text-sm",children:l("dashboard.resolved")})]})]}),e.jsx("div",{className:"flex-1 flex items-end gap-1 overflow-x-auto pb-4",children:s.map(t=>e.jsxs("div",{className:"flex-1 min-w-[20px] flex gap-0.5",children:[e.jsx("div",{className:"flex-1 bg-[var(--info-text)] rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${t.created/o*100}%`,minHeight:t.created>0?"4px":"0"},title:`Created: ${t.created}`}),e.jsx("div",{className:"flex-1 bg-[var(--success-text)] rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${t.resolved/o*100}%`,minHeight:t.resolved>0?"4px":"0"},title:`Resolved: ${t.resolved}`})]},`${t.date}`))}),e.jsxs("div",{className:"flex justify-between text-xs text-[var(--text-secondary)] mt-2",children:[e.jsx("span",{children:s[0]&&new Date(s[0].date).toLocaleDateString()}),e.jsx("span",{children:s.at(-1)&&new Date(s.at(-1).date).toLocaleDateString()})]})]})}function M(s){if(s<60)return`${Math.round(s)}m`;const l=Math.floor(s/60),o=Math.round(s%60);if(l<24)return o>0?`${l}h ${o}m`:`${l}h`;const t=Math.floor(l/24),m=l%24;return m>0?`${t}d ${m}h`:`${t}d`}exports.DashboardPage=ce;
|
|
2
|
-
//# sourceMappingURL=DashboardPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("react"),se=require("react-router-dom"),ae=require("react-i18next"),c=require("./index-DK5czlkn.js"),r=require("lucide-react"),te=require("./ticketingApi-Dwn7pl5z.js"),re={Low:"var(--info-text)",Medium:"var(--warning-text)",High:"var(--warning-text)",Critical:"var(--error-text)"},ne={Open:"var(--warning-text)",InProgress:"var(--info-text)",OnHold:"var(--warning-text)",Resolved:"var(--success-text)",Closed:"var(--text-secondary)",Rejected:"var(--error-text)"};function ce(){const{t:s}=ae.useTranslation("support"),l=se.useNavigate(),{hasPermission:o}=c.useAuth(),{isGlpi:t,glpiBaseUrl:m}=c.useTicketingProvider(),{currentTenant:p}=c.useTenant(),[k,L]=n.useState(!0),[$,A]=n.useState(!1),[x,E]=n.useState(30),R=o("support.sla.read"),[v,I]=n.useState(null),[P,H]=n.useState([]),[D,q]=n.useState([]),[C,G]=n.useState([]),[F,O]=n.useState([]),[g,U]=n.useState(null),[u,W]=n.useState(null),[N,V]=n.useState([]),[y,z]=n.useState([]),[i,K]=n.useState(null),[w,B]=n.useState(!1),S=n.useCallback(async()=>{try{const[a,d,h,b,f,Y,Z]=await Promise.all([c.dashboardApi.getOverview(x),c.dashboardApi.getByStatus(),c.dashboardApi.getByPriority(),c.dashboardApi.getAgentWorkload(),c.dashboardApi.getTrends(x),c.dashboardApi.getSatisfactionStats(x),c.dashboardApi.getSlaCompliance(x)]);if(I(a),H(d),q(h),G(b),O(f),U(Y),W(Z),t)try{const T=await c.supportApi.tickets.getGlpiSyncStats();K(T)}catch{}if(R){const[T,ee]=await Promise.all([c.slaApi.getBreachedTickets(),c.slaApi.getTicketsApproachingBreach(60)]);V(T),z(ee)}}catch(a){console.error("Failed to load dashboard data:",a)}finally{L(!1),A(!1)}},[x,R,t]);n.useEffect(()=>{S()},[S]);const X=()=>{A(!0),S()},_=async()=>{if(!(!p?.id||w)){B(!0);try{await te.ticketingApi.triggerSync(p.id),await S()}catch{}finally{B(!1)}}};if(k)return e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(r.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-primary-600)]"})});const J=a=>a>=95?"text-[var(--success-text)]":a>=80?"text-[var(--warning-text)]":"text-[var(--error-text)]",Q=a=>a>=4?"text-[var(--success-text)]":a>=3?"text-[var(--warning-text)]":"text-[var(--error-text)]";return e.jsxs("div",{className:"space-y-6",children:[e.jsx(c.Breadcrumb,{items:[{label:s("title","Support"),href:"/support"},{label:s("dashboard.title","Dashboard")}]}),e.jsx(c.PageHeader,{title:s("dashboard.title"),subtitle:s("dashboard.subtitle"),icon:e.jsx(r.LayoutDashboard,{className:"w-6 h-6"}),actions:e.jsxs(e.Fragment,{children:[e.jsxs("select",{value:x,onChange:a=>E(Number(a.target.value)),className:"input",children:[e.jsx("option",{value:7,children:s("dashboard.period7")}),e.jsx("option",{value:30,children:s("dashboard.period30")}),e.jsx("option",{value:90,children:s("dashboard.period90")})]}),e.jsxs("button",{onClick:X,disabled:$,className:"btn btn-secondary flex items-center gap-2",children:[e.jsx(r.RefreshCw,{className:`w-4 h-4 ${$?"animate-spin":""}`}),s("dashboard.refresh")]})]})}),t&&e.jsxs("div",{className:"flex items-center gap-3 p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] text-[var(--info-text)]",children:[e.jsx(r.Info,{className:"w-5 h-5 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"font-medium",children:s("glpi.managedByGlpi")}),e.jsx("p",{className:"text-sm opacity-80",children:s("glpi.dashboardSyncInfo")})]}),m&&e.jsxs("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"btn btn-secondary flex items-center gap-2 text-sm",children:[e.jsx(r.ExternalLink,{className:"w-4 h-4"}),s("glpi.openGlpi")]})]}),t&&i&&e.jsxs("div",{className:"card p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"font-semibold flex items-center gap-2",children:[e.jsx(r.RefreshCw,{className:"w-5 h-5"}),s("glpi.sync.title","GLPI Sync Status")]}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:s("glpi.sync.subtitle","Synchronization overview with GLPI")})]}),e.jsxs("button",{onClick:_,disabled:w,className:"btn btn-secondary flex items-center gap-2",children:[e.jsx(r.RefreshCw,{className:`w-4 h-4 ${w?"animate-spin":""}`}),w?s("glpi.sync.syncing","Syncing..."):s("glpi.sync.triggerSync","Sync Now")]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:[e.jsxs("div",{className:"card p-4 text-center border bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]",children:[e.jsx("div",{className:"text-2xl font-bold",children:i.totalMappedTickets}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.totalSynced","Total Synced")})]}),e.jsxs("div",{className:"card p-4 text-center border bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]",children:[e.jsx("div",{className:"text-2xl font-bold",children:i.ticketsSyncedOk}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.syncSuccess","Successful")})]}),e.jsxs("div",{className:"card p-4 text-center border bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]",children:[e.jsx("div",{className:"text-2xl font-bold",children:i.ticketsWithSyncErrors}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.syncErrors","Errors")})]}),e.jsxs("div",{className:`card p-4 text-center border ${i.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)]"}`,children:[e.jsxs("div",{className:"text-2xl font-bold",children:[i.successRate,"%"]}),e.jsx("div",{className:"text-sm opacity-80",children:s("glpi.sync.successRate","Success Rate")})]})]}),e.jsxs("div",{className:"flex items-center gap-6 text-sm text-[var(--text-secondary)]",children:[e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[s("glpi.sync.lastSync","Last Sync"),":"]})," ",i.lastSyncAt?new Date(i.lastSyncAt).toLocaleString():s("glpi.sync.never","Never")]}),e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[s("glpi.sync.syncInterval","Interval"),":"]})," ",s("glpi.sync.everyNMinutes","Every {{n}} min",{n:i.syncIntervalMinutes})]}),e.jsx("div",{children:e.jsx("span",{className:`px-2 py-0.5 rounded text-xs font-medium ${i.syncEnabled?"bg-[var(--success-bg)] text-[var(--success-text)]":"bg-[var(--bg-secondary)] text-[var(--text-secondary)]"}`,children:i.syncEnabled?s("glpi.sync.enabled","Enabled"):s("glpi.sync.disabled","Disabled")})})]}),i.lastSyncError&&e.jsxs("div",{className:"p-3 rounded-lg bg-[var(--error-bg)] border border-[var(--error-border)]",children:[e.jsx("p",{className:"text-sm font-medium text-[var(--error-text)]",children:s("glpi.sync.lastError","Last Sync Error")}),e.jsx("p",{className:"text-sm text-[var(--error-text)] opacity-80 mt-1",children:i.lastSyncError})]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4",children:[e.jsx(j,{title:s("dashboard.totalTickets"),value:v?.totalTickets??0,icon:e.jsx(r.Headphones,{className:"w-5 h-5"}),color:"blue"}),e.jsx(j,{title:s("dashboard.newTickets"),value:v?.newTickets??0,icon:e.jsx(r.TrendingUp,{className:"w-5 h-5"}),color:"green",subtitle:s("dashboard.lastNDays",{period:x})}),e.jsx(j,{title:s("dashboard.openTickets"),value:v?.openTickets??0,icon:e.jsx(r.Clock,{className:"w-5 h-5"}),color:"yellow"}),e.jsx(j,{title:s("dashboard.resolvedTickets"),value:v?.resolvedTickets??0,icon:e.jsx(r.CheckCircle,{className:"w-5 h-5"}),color:"green",subtitle:s("dashboard.lastNDays",{period:x})}),e.jsx(j,{title:s("dashboard.slaCompliance"),value:`${v?.slaCompliancePercentage?.toFixed(1)??0}%`,icon:e.jsx(r.AlertTriangle,{className:"w-5 h-5"}),color:(v?.slaCompliancePercentage??0)>=90?"green":"red"}),e.jsx(j,{title:s("dashboard.avgSatisfaction"),value:`${v?.averageSatisfaction?.toFixed(1)??0}/5`,icon:e.jsx(r.Star,{className:"w-5 h-5"}),color:(v?.averageSatisfaction??0)>=4?"green":"yellow"})]}),R&&(N.length>0||y.length>0)&&e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[N.length>0&&e.jsxs("div",{className:"card p-4 border-l-4 border-[var(--error-border)]",children:[e.jsxs("h3",{className:"font-semibold text-[var(--error-text)] flex items-center gap-2 mb-3",children:[e.jsx(r.XCircle,{className:"w-5 h-5"}),s("dashboard.slaBreached")," (",N.length,")"]}),e.jsx("div",{className:"space-y-2 max-h-40 overflow-y-auto",children:N.slice(0,5).map(a=>e.jsxs("button",{type:"button",className:"w-full flex items-center justify-between p-2 bg-[var(--error-bg)] rounded cursor-pointer hover:opacity-80 text-left",onClick:()=>l(`/support/tickets/${a.ticketId}`),children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-mono text-sm",children:a.ticketNumber}),e.jsx("span",{className:"ml-2 text-sm",children:a.ticketTitle})]}),e.jsxs("span",{className:"text-xs text-[var(--error-text)] font-medium",children:[a.responseBreached&&"Response"," ",a.resolutionBreached&&"Resolution"]})]},a.id))})]}),y.length>0&&e.jsxs("div",{className:"card p-4 border-l-4 border-[var(--warning-border)]",children:[e.jsxs("h3",{className:"font-semibold text-[var(--warning-text)] flex items-center gap-2 mb-3",children:[e.jsx(r.AlertTriangle,{className:"w-5 h-5"}),s("dashboard.approachingBreach")," (",y.length,")"]}),e.jsx("div",{className:"space-y-2 max-h-40 overflow-y-auto",children:y.slice(0,5).map(a=>e.jsxs("button",{type:"button",className:"w-full flex items-center justify-between p-2 bg-[var(--warning-bg)] rounded cursor-pointer hover:opacity-80 text-left",onClick:()=>l(`/support/tickets/${a.ticketId}`),children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-mono text-sm",children:a.ticketNumber}),e.jsx("span",{className:"ml-2 text-sm",children:a.ticketTitle})]}),e.jsxs("span",{className:"text-xs text-[var(--warning-text)] font-medium",children:[Math.round(a.responseSlaPercentage),"% Response"]})]},a.id))})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.ticketsByStatus")}),e.jsx("div",{className:"space-y-3",children:P.map(a=>{const d=P.reduce((b,f)=>b+f.count,0),h=d>0?a.count/d*100:0;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:a.status}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${h}%`,backgroundColor:ne[a.status]||"#6b7280"}})}),e.jsx("div",{className:"w-16 text-right text-sm font-medium",children:a.count})]},a.status)})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.activeTicketsByPriority")}),e.jsx("div",{className:"space-y-3",children:D.map(a=>{const d=D.reduce((b,f)=>b+f.count,0),h=d>0?a.count/d*100:0;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm",children:a.priority}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${h}%`,backgroundColor:re[a.priority]||"#6b7280"}})}),e.jsx("div",{className:"w-16 text-right text-sm font-medium",children:a.count})]},a.priority)})})]})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.slaPerformance")}),u&&e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:`text-3xl font-bold ${J(u.compliancePercentage)}`,children:[u.compliancePercentage.toFixed(1),"%"]}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.complianceRate")})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold",children:u.ticketsWithinSla}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.withinSla")})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold text-[var(--error-text)]",children:u.ticketsBreached}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.breached")})]}),e.jsxs("div",{className:"space-y-2 p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsxs("span",{children:[s("dashboard.avgResponse"),":"]}),e.jsx("span",{className:"font-medium",children:M(u.averageResponseMinutes)})]}),e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsxs("span",{children:[s("dashboard.avgResolution"),":"]}),e.jsx("span",{className:"font-medium",children:M(u.averageResolutionMinutes)})]})]})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.customerSatisfaction")}),g&&e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:`text-3xl font-bold ${Q(g.averageRating)}`,children:g.averageRating.toFixed(1)}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.averageRating")}),e.jsx("div",{className:"flex justify-center mt-1",children:[1,2,3,4,5].map(a=>e.jsx(r.Star,{className:`w-4 h-4 ${a<=Math.round(g.averageRating)?"text-[var(--warning-text)] fill-[var(--warning-text)]":"text-[var(--text-muted)]"}`},a))})]}),e.jsxs("div",{className:"text-center p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-3xl font-bold",children:g.totalResponses}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("dashboard.totalResponses")})]}),e.jsxs("div",{className:"col-span-2 p-4 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("div",{className:"text-sm font-medium mb-2",children:s("dashboard.ratingDistribution")}),e.jsx("div",{className:"space-y-1",children:[5,4,3,2,1].map(a=>{const d=g.ratingDistribution[a]||0,h=g.totalResponses>0?d/g.totalResponses*100:0;return e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx("span",{className:"w-4",children:a}),e.jsx(r.Star,{className:"w-3 h-3 text-[var(--warning-text)] fill-[var(--warning-text)]"}),e.jsx("div",{className:"flex-1 h-3 bg-[var(--bg-primary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full bg-[var(--warning-text)] rounded-full",style:{width:`${h}%`}})}),e.jsx("span",{className:"w-8 text-right text-xs",children:d})]},a)})})]})]})]})]}),e.jsxs("div",{className:"card p-4",children:[e.jsx("h3",{className:"font-semibold mb-4",children:s("dashboard.ticketTrends",{period:x})}),e.jsx("div",{className:"h-64",children:e.jsx(le,{data:F,t:s})})]}),e.jsxs("div",{className:"card p-4",children:[e.jsxs("h3",{className:"font-semibold mb-4 flex items-center gap-2",children:[e.jsx(r.Users,{className:"w-5 h-5"}),s("dashboard.agentWorkload")]}),C.length>0?e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[var(--border-color)]",children:[e.jsx("th",{className:"text-left p-3 font-medium",children:s("dashboard.agent")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.total")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.open")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.inProgress")}),e.jsx("th",{className:"text-center p-3 font-medium",children:s("dashboard.onHold")}),e.jsx("th",{className:"text-left p-3 font-medium",children:s("dashboard.load")})]})}),e.jsx("tbody",{children:C.map(a=>{const d=Math.max(...C.map(b=>b.totalAssigned)),h=d>0?a.totalAssigned/d*100:0;return e.jsxs("tr",{className:"border-b border-[var(--border-color)]",children:[e.jsxs("td",{className:"p-3",children:[e.jsx("div",{className:"font-medium",children:a.name}),e.jsx("div",{className:"text-xs text-[var(--text-secondary)]",children:a.email})]}),e.jsx("td",{className:"text-center p-3 font-semibold",children:a.totalAssigned}),e.jsx("td",{className:"text-center p-3",children:e.jsx("span",{className:"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm",children:a.openCount})}),e.jsx("td",{className:"text-center p-3",children:e.jsx("span",{className:"px-2 py-1 bg-[var(--info-bg)] text-[var(--info-text)] rounded-[var(--radius-badge)] text-sm",children:a.inProgressCount})}),e.jsx("td",{className:"text-center p-3",children:e.jsx("span",{className:"px-2 py-1 bg-[var(--warning-bg)] text-[var(--warning-text)] rounded-[var(--radius-badge)] text-sm",children:a.onHoldCount})}),e.jsx("td",{className:"p-3 w-32",children:e.jsx("div",{className:"h-2 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full bg-[var(--info-text)] rounded-full",style:{width:`${h}%`}})})})]},a.userId)})})]})}):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:s("dashboard.noAgentsAssigned")})]})]})}function j({title:s,value:l,icon:o,color:t,subtitle:m,trend:p}){const k={blue:"bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]",green:"bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]",yellow:"bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]",red:"bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]"};return e.jsxs("div",{className:`card p-4 border ${k[t]}`,children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium opacity-80",children:s}),o]}),e.jsx("div",{className:"text-2xl font-bold",children:l}),m&&e.jsx("div",{className:"text-xs opacity-70 mt-1",children:m}),p&&e.jsxs("div",{className:`flex items-center gap-1 mt-1 text-xs ${p.isUp?"text-[var(--success-text)]":"text-[var(--error-text)]"}`,children:[p.isUp?e.jsx(r.ArrowUp,{className:"w-3 h-3"}):e.jsx(r.ArrowDown,{className:"w-3 h-3"}),p.value,"%"]})]})}function le({data:s,t:l}){if(s.length===0)return e.jsx("div",{className:"flex items-center justify-center h-full text-[var(--text-secondary)]",children:l("dashboard.noTrendData")});const o=Math.max(...s.flatMap(t=>[t.created,t.resolved]),1);return e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"flex items-center gap-4 mb-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-[var(--info-text)]"}),e.jsx("span",{className:"text-sm",children:l("dashboard.created")})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded bg-[var(--success-text)]"}),e.jsx("span",{className:"text-sm",children:l("dashboard.resolved")})]})]}),e.jsx("div",{className:"flex-1 flex items-end gap-1 overflow-x-auto pb-4",children:s.map(t=>e.jsxs("div",{className:"flex-1 min-w-[20px] flex gap-0.5",children:[e.jsx("div",{className:"flex-1 bg-[var(--info-text)] rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${t.created/o*100}%`,minHeight:t.created>0?"4px":"0"},title:`Created: ${t.created}`}),e.jsx("div",{className:"flex-1 bg-[var(--success-text)] rounded-t transition-all duration-300 hover:opacity-80",style:{height:`${t.resolved/o*100}%`,minHeight:t.resolved>0?"4px":"0"},title:`Resolved: ${t.resolved}`})]},`${t.date}`))}),e.jsxs("div",{className:"flex justify-between text-xs text-[var(--text-secondary)] mt-2",children:[e.jsx("span",{children:s[0]&&new Date(s[0].date).toLocaleDateString()}),e.jsx("span",{children:s.at(-1)&&new Date(s.at(-1).date).toLocaleDateString()})]})]})}function M(s){if(s<60)return`${Math.round(s)}m`;const l=Math.floor(s/60),o=Math.round(s%60);if(l<24)return o>0?`${l}h ${o}m`:`${l}h`;const t=Math.floor(l/24),m=l%24;return m>0?`${t}d ${m}h`:`${t}d`}exports.DashboardPage=ce;
|
|
2
|
+
//# sourceMappingURL=DashboardPage-rN7IFlTR.js.map
|