@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
package/dist/chunks/{UserCreateTicketPage-bcbSLglE.js.map → UserCreateTicketPage-lvlvp2u6.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserCreateTicketPage-bcbSLglE.js","sources":["../../src/pages/platform/support/UserCreateTicketPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate, useSearchParams } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n ArrowLeft, Headset, Bug, Lightbulb, AppWindow, HelpCircle, MessageSquare,\r\n Loader2, AlertTriangle, Send, Monitor, Upload, X, Image as ImageIcon,\r\n FileText, File as FileIcon, Paperclip, Info, ExternalLink, Building2, Check, Trash2\r\n} from 'lucide-react';\r\nimport { myTicketsApi, type TicketType, type TicketPriority, type ClientContextDto, type MyTicketDetailDto } from '@/services/api/ticketApi';\r\nimport { api } from '@/services/api/apiClient';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport type { UserTenantDto } from '@/services/api/adminApi';\r\nimport { browserInfoService, type BrowserInfo } from '@/services/support/browserInfoService';\r\nimport { useTicketingProvider } from '@/hooks/useTicketingProvider';\r\nimport { generateUUID } from '@/utils/uuid';\r\nimport { logService } from '@/services/logging/logService';\r\nimport { ScreenshotAnnotator } from '@/components/platform/support/ScreenshotAnnotator';\r\nimport { errorContextService } from '@/services/support/errorContextService';\r\nimport { ticketDraftService } from '@/services/support/ticketDraftService';\r\n\r\nconst ticketTypes: { value: TicketType; label: string; labelKey: string; description: string; descriptionKey: string; icon: React.ElementType }[] = [\r\n {\r\n value: 'Bug',\r\n label: 'Report a Bug',\r\n labelKey: 'tickets.types.bug',\r\n description: 'Something is not working correctly',\r\n descriptionKey: 'tickets.types.bugDescription',\r\n icon: Bug,\r\n },\r\n {\r\n value: 'FeatureRequest',\r\n label: 'Request a Feature',\r\n labelKey: 'tickets.types.featureRequest',\r\n description: 'Suggest an improvement or new feature',\r\n descriptionKey: 'tickets.types.featureRequestDescription',\r\n icon: Lightbulb,\r\n },\r\n {\r\n value: 'ApplicationRequest',\r\n label: 'Request an Application',\r\n labelKey: 'tickets.types.applicationRequest',\r\n description: 'Request access to a new application',\r\n descriptionKey: 'tickets.types.applicationRequestDescription',\r\n icon: AppWindow,\r\n },\r\n {\r\n value: 'Support',\r\n label: 'General Support',\r\n labelKey: 'tickets.types.support',\r\n description: 'Need help with something',\r\n descriptionKey: 'tickets.types.supportDescription',\r\n icon: MessageSquare,\r\n },\r\n {\r\n value: 'Question',\r\n label: 'Ask a Question',\r\n labelKey: 'tickets.types.question',\r\n description: 'Have a question about the platform',\r\n descriptionKey: 'tickets.types.questionDescription',\r\n icon: HelpCircle,\r\n },\r\n];\r\n\r\nconst priorityOptions: { value: TicketPriority; label: string; labelKey: string; description: string; descriptionKey: string }[] = [\r\n { value: 'Low', label: 'Low', labelKey: 'tickets.priority.low', description: 'Can wait, not urgent', descriptionKey: 'tickets.priority.lowDescription' },\r\n { value: 'Medium', label: 'Medium', labelKey: 'tickets.priority.medium', description: 'Normal priority', descriptionKey: 'tickets.priority.mediumDescription' },\r\n { value: 'High', label: 'High', labelKey: 'tickets.priority.high', description: 'Important, needs attention soon', descriptionKey: 'tickets.priority.highDescription' },\r\n { value: 'Critical', label: 'Critical', labelKey: 'tickets.priority.critical', description: 'Urgent, blocking work', descriptionKey: 'tickets.priority.criticalDescription' },\r\n];\r\n\r\ninterface AttachmentFile {\r\n id: string;\r\n file: File;\r\n name: string;\r\n size: number;\r\n type: string;\r\n}\r\n\r\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\r\nconst MAX_ATTACHMENTS = 5;\r\nconst ALLOWED_EXTENSIONS = ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.txt', '.csv', '.zip', '.rar', '.7z', '.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'];\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\r\n}\r\n\r\nfunction getFileIcon(type: string) {\r\n if (type.includes('pdf')) return FileText;\r\n if (type.startsWith('image/')) return ImageIcon;\r\n return FileIcon;\r\n}\r\n\r\nfunction restoreDraft(draftId: string | null, userTenants: UserTenantDto[]) {\r\n if (!draftId) return { draft: null, selectedTenant: null };\r\n\r\n const draft = ticketDraftService.getDraft(draftId);\r\n if (!draft) return { draft: null, selectedTenant: null };\r\n\r\n let selectedTenant: UserTenantDto | null = null;\r\n if (draft.tenantId && draft.tenantSlug) {\r\n const matchingTenant = userTenants.find(t => t.id === draft.tenantId);\r\n if (matchingTenant) {\r\n selectedTenant = matchingTenant;\r\n }\r\n }\r\n\r\n return { draft, selectedTenant };\r\n}\r\n\r\nfunction restoreSessionContext(sessionContext: ReturnType<typeof errorContextService.loadContext>) {\r\n if (!sessionContext?.screenshot) return { screenshot: null, autoSelectType: null };\r\n\r\n let autoSelectType: TicketType | null = null;\r\n if (sessionContext.recentErrors.length > 0) {\r\n autoSelectType = 'Bug';\r\n }\r\n\r\n return { screenshot: sessionContext.screenshot, autoSelectType };\r\n}\r\n\r\nasync function uploadScreenshot(ticketId: string, screenshot: string, selectedTenantForTicket: UserTenantDto | null) {\r\n try {\r\n const response = await fetch(screenshot);\r\n const blob = await response.blob();\r\n const file = new File([blob], 'screenshot.png', { type: 'image/png' });\r\n\r\n if (selectedTenantForTicket) {\r\n const formData = new FormData();\r\n formData.append('file', file);\r\n const tenantHeaders = { 'X-Tenant-Slug': selectedTenantForTicket.slug };\r\n await api.post(`/api/support/my-tickets/${ticketId}/attachments`, formData, {\r\n headers: { 'Content-Type': 'multipart/form-data', ...tenantHeaders },\r\n });\r\n } else {\r\n await myTicketsApi.uploadAttachment(ticketId, file);\r\n }\r\n } catch (attachmentError) {\r\n // Silent fail for attachment upload\r\n }\r\n}\r\n\r\nasync function uploadAttachments(ticketId: string, attachments: AttachmentFile[], selectedTenantForTicket: UserTenantDto | null) {\r\n for (const attachment of attachments) {\r\n try {\r\n if (selectedTenantForTicket) {\r\n const formData = new FormData();\r\n formData.append('file', attachment.file);\r\n const tenantHeaders = { 'X-Tenant-Slug': selectedTenantForTicket.slug };\r\n await api.post(`/api/support/my-tickets/${ticketId}/attachments`, formData, {\r\n headers: { 'Content-Type': 'multipart/form-data', ...tenantHeaders },\r\n });\r\n } else {\r\n await myTicketsApi.uploadAttachment(ticketId, attachment.file);\r\n }\r\n } catch (attachmentError) {\r\n // Silent fail for attachment upload\r\n }\r\n }\r\n}\r\n\r\nexport function UserCreateTicketPage(): ReactElement {\r\n const navigate = useNavigate();\r\n const [searchParams] = useSearchParams();\r\n const { t } = useTranslation(['support', 'common']);\r\n const { isGlpi, glpiBaseUrl } = useTicketingProvider();\r\n const { currentTenant, userTenants, isGlobalView } = useTenant();\r\n const screenshotInputRef = useRef<HTMLInputElement>(null);\r\n const attachmentInputRef = useRef<HTMLInputElement>(null);\r\n\r\n // When in global view (no tenant selected), allow user to pick a tenant for the ticket\r\n const [selectedTenantForTicket, setSelectedTenantForTicket] = useState<UserTenantDto | null>(null);\r\n const [showTenantPicker, setShowTenantPicker] = useState(false);\r\n\r\n // The effective tenant: either the global current tenant or the locally selected one\r\n const effectiveTenant = currentTenant ?? selectedTenantForTicket;\r\n\r\n // Show tenant picker on mount when no tenant is selected\r\n useEffect(() => {\r\n if (!currentTenant && isGlobalView && userTenants.length > 0) {\r\n setShowTenantPicker(true);\r\n }\r\n }, [currentTenant, isGlobalView, userTenants.length]);\r\n\r\n const draftId = searchParams.get('draft');\r\n\r\n const [step, setStep] = useState(1);\r\n const [selectedType, setSelectedType] = useState<TicketType | null>(null);\r\n const [title, setTitle] = useState('');\r\n const [description, setDescription] = useState('');\r\n const [priority, setPriority] = useState<TicketPriority>('Medium');\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n // Browser info state\r\n const [browserInfo, setBrowserInfo] = useState<BrowserInfo | null>(null);\r\n const [includeBrowserInfo, setIncludeBrowserInfo] = useState(true);\r\n\r\n // Screenshot state\r\n const [screenshot, setScreenshot] = useState<string | null>(null);\r\n const [annotatedScreenshot, setAnnotatedScreenshot] = useState<string | null>(null);\r\n const [isDraggingScreenshot, setIsDraggingScreenshot] = useState(false);\r\n\r\n // Attachments state\r\n const [attachments, setAttachments] = useState<AttachmentFile[]>([]);\r\n const [isDraggingAttachment, setIsDraggingAttachment] = useState(false);\r\n\r\n // Draft auto-save state\r\n const [currentDraftId, setCurrentDraftId] = useState<string | null>(draftId);\r\n const [showDraftSaved, setShowDraftSaved] = useState(false);\r\n const [showDiscardConfirm, setShowDiscardConfirm] = useState(false);\r\n const autoSaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const isInitialLoadCompleteRef = useRef(false);\r\n const hasUnsavedChangesRef = useRef(false);\r\n\r\n // Save draft function\r\n const saveDraftNow = useCallback(() => {\r\n if (!currentDraftId) return false;\r\n\r\n const result = ticketDraftService.updateDraft(currentDraftId, {\r\n type: selectedType,\r\n title,\r\n description,\r\n priority,\r\n includeScreenshot: !!annotatedScreenshot,\r\n includeErrorLogs: false,\r\n screenshot: annotatedScreenshot ?? undefined,\r\n tenantId: effectiveTenant?.id,\r\n tenantSlug: effectiveTenant?.slug,\r\n tenantName: effectiveTenant?.name,\r\n });\r\n\r\n if (result.success) {\r\n hasUnsavedChangesRef.current = false;\r\n setShowDraftSaved(true);\r\n setTimeout(() => setShowDraftSaved(false), 2000);\r\n }\r\n return result.success;\r\n }, [currentDraftId, selectedType, title, description, priority, annotatedScreenshot, effectiveTenant]);\r\n\r\n // Auto-create draft when user starts filling the form (no existing draft)\r\n const ensureDraft = useCallback(() => {\r\n if (currentDraftId) return currentDraftId;\r\n const newDraft = ticketDraftService.createDraft();\r\n setCurrentDraftId(newDraft.id);\r\n return newDraft.id;\r\n }, [currentDraftId]);\r\n\r\n // Debounced auto-save when form data changes\r\n useEffect(() => {\r\n if (!isInitialLoadCompleteRef.current) return;\r\n // Only auto-save if there's meaningful data\r\n if (!selectedType && !title && !description) return;\r\n\r\n hasUnsavedChangesRef.current = true;\r\n\r\n // Ensure a draft exists before saving\r\n if (!currentDraftId) {\r\n ensureDraft();\r\n return; // Will re-trigger on next render with currentDraftId set\r\n }\r\n\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n }\r\n\r\n autoSaveTimerRef.current = setTimeout(() => {\r\n saveDraftNow();\r\n }, 1000);\r\n\r\n return () => {\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n }\r\n };\r\n }, [selectedType, title, description, priority, annotatedScreenshot, currentDraftId, saveDraftNow, ensureDraft]);\r\n\r\n // Save on unmount + beforeunload\r\n useEffect(() => {\r\n const handleBeforeUnload = () => {\r\n if (hasUnsavedChangesRef.current && currentDraftId) {\r\n saveDraftNow();\r\n }\r\n };\r\n\r\n window.addEventListener('beforeunload', handleBeforeUnload);\r\n return () => {\r\n window.removeEventListener('beforeunload', handleBeforeUnload);\r\n if (hasUnsavedChangesRef.current && currentDraftId) {\r\n saveDraftNow();\r\n }\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n }\r\n };\r\n }, [currentDraftId, saveDraftNow]);\r\n\r\n // Discard draft handler\r\n const handleDiscardDraft = useCallback(() => {\r\n if (currentDraftId) {\r\n ticketDraftService.deleteDraft(currentDraftId);\r\n }\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n autoSaveTimerRef.current = null;\r\n }\r\n navigate(-1);\r\n }, [currentDraftId, navigate]);\r\n\r\n // Load draft, session context, URL pre-fill params, and browser info on mount\r\n useEffect(() => {\r\n // Load draft if resuming\r\n const { draft, selectedTenant } = restoreDraft(draftId, userTenants);\r\n if (draft) {\r\n if (draft.type) {\r\n setSelectedType(draft.type);\r\n setStep(2);\r\n }\r\n if (draft.title) setTitle(draft.title);\r\n if (draft.description) setDescription(draft.description);\r\n if (draft.priority) setPriority(draft.priority);\r\n if (draft.screenshot) {\r\n setScreenshot(draft.screenshot);\r\n setAnnotatedScreenshot(draft.screenshot);\r\n }\r\n if (selectedTenant) {\r\n setSelectedTenantForTicket(selectedTenant);\r\n }\r\n }\r\n\r\n // Pre-fill from URL params (e.g. from AccessDenied page) — draft takes priority\r\n if (!draft) {\r\n const validTypes: TicketType[] = ['Bug', 'FeatureRequest', 'Suggestion', 'ApplicationRequest', 'Support', 'Question'];\r\n const prefillType = searchParams.get('type') as TicketType | null;\r\n const prefillSubject = searchParams.get('subject');\r\n const prefillBody = searchParams.get('body');\r\n\r\n if (prefillType && validTypes.includes(prefillType)) {\r\n setSelectedType(prefillType);\r\n setStep(2);\r\n }\r\n if (prefillSubject) setTitle(decodeURIComponent(prefillSubject));\r\n if (prefillBody) setDescription(decodeURIComponent(prefillBody));\r\n }\r\n\r\n // Load captured screenshot from session context (from CreateTicketButton)\r\n const sessionContext = errorContextService.loadContext();\r\n const { screenshot: sessionScreenshot, autoSelectType } = restoreSessionContext(sessionContext);\r\n if (sessionScreenshot && !annotatedScreenshot) {\r\n setScreenshot(sessionScreenshot);\r\n setAnnotatedScreenshot(sessionScreenshot);\r\n\r\n if (autoSelectType && !selectedType) {\r\n setSelectedType(autoSelectType);\r\n setPriority('High');\r\n }\r\n }\r\n errorContextService.clearContext();\r\n\r\n const info = browserInfoService.captureBrowserInfo();\r\n setBrowserInfo(info);\r\n\r\n // Mark initial load complete (prevents auto-save during hydration)\r\n setTimeout(() => { isInitialLoadCompleteRef.current = true; }, 100);\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [draftId]);\r\n\r\n // Process image file for screenshot\r\n const processImageFile = useCallback((file: File) => {\r\n if (!file.type.startsWith('image/')) {\r\n setError(t('tickets.create.invalidImageType', 'Please select a valid image file'));\r\n return;\r\n }\r\n\r\n if (file.size > MAX_FILE_SIZE) {\r\n setError(t('tickets.create.imageTooLarge', 'Image must be less than 10MB'));\r\n return;\r\n }\r\n\r\n const reader = new FileReader();\r\n reader.onload = (e) => {\r\n const dataUrl = e.target?.result as string;\r\n setScreenshot(dataUrl);\r\n setAnnotatedScreenshot(dataUrl);\r\n setError(null);\r\n };\r\n reader.onerror = () => {\r\n setError(t('tickets.create.imageReadError', 'Failed to read image file'));\r\n };\r\n reader.readAsDataURL(file);\r\n }, [t]);\r\n\r\n const handleScreenshotUpload = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = event.target.files?.[0];\r\n if (file) {\r\n processImageFile(file);\r\n }\r\n }, [processImageFile]);\r\n\r\n // Drag & Drop handlers for screenshot\r\n const handleScreenshotDragOver = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingScreenshot(true);\r\n }, []);\r\n\r\n const handleScreenshotDragLeave = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingScreenshot(false);\r\n }, []);\r\n\r\n const handleScreenshotDrop = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingScreenshot(false);\r\n\r\n const files = e.dataTransfer.files;\r\n if (files.length > 0) {\r\n const file = files[0];\r\n if (file.type.startsWith('image/')) {\r\n processImageFile(file);\r\n } else {\r\n setError(t('tickets.create.invalidImageType', 'Please select a valid image file'));\r\n }\r\n }\r\n }, [processImageFile, t]);\r\n\r\n const handleRemoveScreenshot = useCallback(() => {\r\n setScreenshot(null);\r\n setAnnotatedScreenshot(null);\r\n if (screenshotInputRef.current) {\r\n screenshotInputRef.current.value = '';\r\n }\r\n }, []);\r\n\r\n const handleAnnotatedScreenshot = useCallback((dataUrl: string) => {\r\n setAnnotatedScreenshot(dataUrl);\r\n }, []);\r\n\r\n // Attachment handlers\r\n const isAllowedFileType = useCallback((file: File): boolean => {\r\n // Allow all images\r\n if (file.type.startsWith('image/')) {\r\n return true;\r\n }\r\n const extension = '.' + file.name.split('.').pop()?.toLowerCase();\r\n return ALLOWED_EXTENSIONS.includes(extension);\r\n }, []);\r\n\r\n const processAttachmentFiles = useCallback((files: FileList) => {\r\n const newAttachments: AttachmentFile[] = [];\r\n\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i];\r\n\r\n // Skip if already at max attachments\r\n if (attachments.length + newAttachments.length >= MAX_ATTACHMENTS) {\r\n setError(t('tickets.create.maxAttachments', `Maximum ${MAX_ATTACHMENTS} attachments allowed`));\r\n break;\r\n }\r\n\r\n // Check file size\r\n if (file.size > MAX_FILE_SIZE) {\r\n setError(t('tickets.create.fileTooLarge', `File \"${file.name}\" is too large (max 10MB)`));\r\n continue;\r\n }\r\n\r\n // Check file type\r\n if (!isAllowedFileType(file)) {\r\n setError(t('tickets.create.invalidFileType', `File type not allowed: ${file.name}`));\r\n continue;\r\n }\r\n\r\n // Check for duplicates\r\n const isDuplicate = attachments.some(a => a.name === file.name && a.size === file.size);\r\n if (isDuplicate) {\r\n continue;\r\n }\r\n\r\n newAttachments.push({\r\n id: generateUUID(),\r\n file,\r\n name: file.name,\r\n size: file.size,\r\n type: file.type,\r\n });\r\n }\r\n\r\n if (newAttachments.length > 0) {\r\n setAttachments(prev => [...prev, ...newAttachments]);\r\n setError(null);\r\n }\r\n }, [attachments, isAllowedFileType, t]);\r\n\r\n const handleAttachmentUpload = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = event.target.files;\r\n if (files) {\r\n processAttachmentFiles(files);\r\n }\r\n // Reset input\r\n if (attachmentInputRef.current) {\r\n attachmentInputRef.current.value = '';\r\n }\r\n }, [processAttachmentFiles]);\r\n\r\n // Drag & Drop handlers for attachments\r\n const handleAttachmentDragOver = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingAttachment(true);\r\n }, []);\r\n\r\n const handleAttachmentDragLeave = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingAttachment(false);\r\n }, []);\r\n\r\n const handleAttachmentDrop = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingAttachment(false);\r\n\r\n const files = e.dataTransfer.files;\r\n if (files.length > 0) {\r\n processAttachmentFiles(files);\r\n }\r\n }, [processAttachmentFiles]);\r\n\r\n const handleRemoveAttachment = useCallback((id: string) => {\r\n setAttachments(prev => prev.filter(a => a.id !== id));\r\n }, []);\r\n\r\n const handleSubmit = async () => {\r\n if (!selectedType || !title.trim() || !description.trim()) return;\r\n\r\n if (!effectiveTenant) {\r\n setShowTenantPicker(true);\r\n return;\r\n }\r\n\r\n try {\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n // Build description with browser info if enabled\r\n let fullDescription = description.trim();\r\n\r\n if (includeBrowserInfo && browserInfo) {\r\n fullDescription += '\\n\\n---\\n**System Information:**\\n' + browserInfoService.formatForDescription(browserInfo);\r\n }\r\n\r\n // Build structured client context for backend storage\r\n const currentBrowserInfo = browserInfo || browserInfoService.captureBrowserInfo();\r\n const recentErrors = logService.getRecentErrors().slice(0, 5);\r\n const clientContext: ClientContextDto = {\r\n sourceUrl: window.location.href,\r\n browser: {\r\n name: currentBrowserInfo.browser,\r\n version: currentBrowserInfo.browserVersion,\r\n language: currentBrowserInfo.language,\r\n },\r\n os: {\r\n name: currentBrowserInfo.os,\r\n version: currentBrowserInfo.osVersion,\r\n },\r\n device: {\r\n type: currentBrowserInfo.deviceType,\r\n screenResolution: currentBrowserInfo.screenResolution,\r\n },\r\n recentErrors: recentErrors.map((e) => ({\r\n message: e.message,\r\n stack: e.stack,\r\n component: e.component,\r\n timestamp: e.timestamp.toISOString(),\r\n })),\r\n };\r\n\r\n // If using locally selected tenant (global view), override X-Tenant-Slug header\r\n const tenantHeaders = selectedTenantForTicket\r\n ? { 'X-Tenant-Slug': selectedTenantForTicket.slug }\r\n : {};\r\n\r\n const ticket = selectedTenantForTicket\r\n ? await api.post<MyTicketDetailDto>('/api/support/my-tickets', {\r\n title: title.trim(),\r\n description: fullDescription,\r\n type: selectedType,\r\n priority,\r\n clientContext,\r\n }, { headers: tenantHeaders })\r\n : await myTicketsApi.create({\r\n title: title.trim(),\r\n description: fullDescription,\r\n type: selectedType,\r\n priority,\r\n clientContext,\r\n });\r\n\r\n // Upload screenshot as attachment if present\r\n if (annotatedScreenshot) {\r\n await uploadScreenshot(ticket.id, annotatedScreenshot, selectedTenantForTicket);\r\n }\r\n\r\n // Upload other attachments\r\n await uploadAttachments(ticket.id, attachments, selectedTenantForTicket);\r\n\r\n // Clean up draft on successful submit\r\n if (currentDraftId) {\r\n ticketDraftService.deleteDraft(currentDraftId);\r\n }\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n autoSaveTimerRef.current = null;\r\n }\r\n hasUnsavedChangesRef.current = false;\r\n\r\n navigate(`/support/my-tickets/${ticket.id}?tab=submitted`);\r\n } catch (err: unknown) {\r\n const serverMessage = err && typeof err === 'object' && 'message' in err\r\n ? (err as { message: string }).message\r\n : null;\r\n setError(serverMessage || t('tickets.create.submitError', 'Failed to create ticket. Please try again.'));\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n const renderTypeSelection = () => (\r\n <div className=\"space-y-4\">\r\n <h2 className=\"text-lg font-semibold mb-4\">{t('tickets.create.selectType', 'What type of request do you have?')}</h2>\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n {ticketTypes.map((type) => (\r\n <button\r\n key={type.value}\r\n onClick={() => {\r\n setSelectedType(type.value);\r\n setStep(2);\r\n }}\r\n className={`card p-4 text-left hover:shadow-md transition-shadow ${\r\n selectedType === type.value ? 'ring-2 ring-[var(--color-primary-600)]' : ''\r\n }`}\r\n >\r\n <div className=\"flex items-start gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <type.icon className=\"w-6 h-6\" />\r\n </div>\r\n <div>\r\n <h3 className=\"font-medium\">{t(type.labelKey, type.label)}</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">{t(type.descriptionKey, type.description)}</p>\r\n </div>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n\r\n const renderForm = () => (\r\n <div className=\"space-y-6\">\r\n <div className=\"flex items-center gap-4 mb-6\">\r\n <button onClick={() => setStep(1)} className=\"btn btn-ghost p-2\">\r\n <ArrowLeft className=\"w-5 h-5\" />\r\n </button>\r\n <div>\r\n <h2 className=\"text-lg font-semibold\">\r\n {t(ticketTypes.find((tt) => tt.value === selectedType)?.labelKey || '', { defaultValue: ticketTypes.find((tt) => tt.value === selectedType)?.label })}\r\n </h2>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('tickets.create.fillDetails', 'Fill in the details below')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n {t('tickets.form.title', 'Title')} <span className=\"text-[var(--error-text)]\">*</span>\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n placeholder={t('tickets.create.titlePlaceholder', 'Brief summary of your request')}\r\n className=\"input w-full\"\r\n maxLength={200}\r\n />\r\n <p className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n {title.length}/200 {t('common:text.characters', 'characters')}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n {t('tickets.create.description', 'Description')} <span className=\"text-[var(--error-text)]\">*</span>\r\n </label>\r\n <textarea\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n placeholder={\r\n selectedType === 'Bug'\r\n ? t('tickets.create.bugPlaceholder', 'Please describe the issue in detail. Include steps to reproduce, expected behavior, and actual behavior.')\r\n : selectedType === 'FeatureRequest'\r\n ? t('tickets.create.featurePlaceholder', 'Describe the feature you would like to see and why it would be useful.')\r\n : selectedType === 'ApplicationRequest'\r\n ? t('tickets.create.applicationPlaceholder', 'Which application do you need access to and why?')\r\n : t('tickets.create.defaultPlaceholder', 'Please provide as much detail as possible.')\r\n }\r\n className=\"input w-full h-40\"\r\n maxLength={5000}\r\n />\r\n <p className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n {description.length}/5000 {t('common:text.characters', 'characters')}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">{t('tickets.create.priority', 'Priority')}</label>\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2\">\r\n {priorityOptions.map((option) => (\r\n <button\r\n key={option.value}\r\n type=\"button\"\r\n onClick={() => setPriority(option.value)}\r\n className={`p-3 rounded-lg border text-center transition-colors ${\r\n priority === option.value\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <div className=\"font-medium\">{t(option.labelKey, option.label)}</div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">{t(option.descriptionKey, option.description)}</div>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Screenshot Upload Section */}\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n <ImageIcon className=\"w-4 h-4 inline mr-2\" />\r\n {t('tickets.create.screenshot', 'Screenshot')}\r\n <span className=\"text-[var(--text-secondary)] font-normal ml-2\">({t('common:text.optional', 'optional')})</span>\r\n </label>\r\n\r\n {!screenshot ? (\r\n <div\r\n className={`border-2 border-dashed rounded-lg p-6 text-center cursor-pointer transition-colors ${\r\n isDraggingScreenshot\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-primary-600)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n onClick={() => screenshotInputRef.current?.click()}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); screenshotInputRef.current?.click(); } }}\r\n role=\"button\"\r\n tabIndex={0}\r\n onDragOver={handleScreenshotDragOver}\r\n onDragLeave={handleScreenshotDragLeave}\r\n onDrop={handleScreenshotDrop}\r\n >\r\n <Upload className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-secondary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {isDraggingScreenshot\r\n ? t('tickets.create.dropScreenshotNow', 'Drop image here')\r\n : t('tickets.create.uploadScreenshot', 'Click or drag & drop to upload a screenshot')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)] mt-1\">\r\n {t('tickets.create.uploadScreenshotHint', 'PNG, JPG, or GIF up to 10MB')}\r\n </p>\r\n <input\r\n ref={screenshotInputRef}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n onChange={handleScreenshotUpload}\r\n className=\"hidden\"\r\n />\r\n </div>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('tickets.create.screenshotUploaded', 'Screenshot uploaded - you can annotate it below')}\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={handleRemoveScreenshot}\r\n className=\"btn btn-ghost p-2 text-[var(--error-text)]\"\r\n title={t('tickets.create.removeScreenshot', 'Remove screenshot')}\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <ScreenshotAnnotator\r\n screenshot={screenshot}\r\n onAnnotatedScreenshot={handleAnnotatedScreenshot}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Attachments Section */}\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n <Paperclip className=\"w-4 h-4 inline mr-2\" />\r\n {t('tickets.create.attachments', 'Attachments')}\r\n <span className=\"text-[var(--text-secondary)] font-normal ml-2\">({t('common:text.optional', 'optional')})</span>\r\n </label>\r\n\r\n <div\r\n className={`border-2 border-dashed rounded-lg p-4 text-center cursor-pointer transition-colors ${\r\n isDraggingAttachment\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-primary-600)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n onClick={() => attachmentInputRef.current?.click()}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); attachmentInputRef.current?.click(); } }}\r\n role=\"button\"\r\n tabIndex={0}\r\n onDragOver={handleAttachmentDragOver}\r\n onDragLeave={handleAttachmentDragLeave}\r\n onDrop={handleAttachmentDrop}\r\n >\r\n <Upload className=\"w-6 h-6 mx-auto mb-1 text-[var(--text-secondary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {isDraggingAttachment\r\n ? t('tickets.create.dropFilesNow', 'Drop files here')\r\n : t('tickets.create.uploadAttachments', 'Click or drag & drop to add documents')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)] mt-1\">\r\n {t('tickets.create.attachmentsHint', 'PDF, Word, Excel, TXT, CSV, ZIP (max 10MB each, up to 5 files)')}\r\n </p>\r\n <input\r\n ref={attachmentInputRef}\r\n type=\"file\"\r\n multiple\r\n accept=\".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.zip,.rar,.7z,image/*\"\r\n onChange={handleAttachmentUpload}\r\n className=\"hidden\"\r\n />\r\n </div>\r\n\r\n {/* Attachments List */}\r\n {attachments.length > 0 && (\r\n <div className=\"mt-3 space-y-2\">\r\n {attachments.map((attachment) => {\r\n const AttachmentIcon = getFileIcon(attachment.type);\r\n return (\r\n <div\r\n key={attachment.id}\r\n className=\"flex items-center justify-between p-2 rounded-lg bg-[var(--bg-secondary)]\"\r\n >\r\n <div className=\"flex items-center gap-2 min-w-0\">\r\n <AttachmentIcon className=\"w-4 h-4 text-[var(--text-secondary)] flex-shrink-0\" />\r\n <span className=\"text-sm truncate\">{attachment.name}</span>\r\n <span className=\"text-xs text-[var(--text-muted)] flex-shrink-0\">\r\n ({formatFileSize(attachment.size)})\r\n </span>\r\n </div>\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRemoveAttachment(attachment.id)}\r\n className=\"btn btn-ghost p-1 text-[var(--error-text)]\"\r\n title={t('tickets.create.removeAttachment', 'Remove attachment')}\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Browser Info Section */}\r\n {browserInfo && (\r\n <div className=\"border border-[var(--border-color)] rounded-lg p-4\">\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <Monitor className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n <span className=\"text-sm font-medium\">{t('tickets.create.systemInfo', 'System Information')}</span>\r\n </div>\r\n <label className=\"flex items-center gap-2 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={includeBrowserInfo}\r\n onChange={(e) => setIncludeBrowserInfo(e.target.checked)}\r\n className=\"rounded border-[var(--border-color)]\"\r\n />\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {t('tickets.create.includeSystemInfo', 'Include in ticket')}\r\n </span>\r\n </label>\r\n </div>\r\n <div className={`grid grid-cols-2 md:grid-cols-3 gap-3 text-sm ${!includeBrowserInfo ? 'opacity-50' : ''}`}>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.browser', 'Browser')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.browser} {browserInfo.browserVersion}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.os', 'OS')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.os} {browserInfo.osVersion}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.device', 'Device')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.deviceType}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.screen', 'Screen')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.screenResolution}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.language', 'Language')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.language}</span>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-[var(--error-bg)] text-[var(--error-text)] flex items-center gap-2\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n {error}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex items-center justify-between pt-4 border-t border-[var(--border-color)]\">\r\n <button onClick={() => setStep(1)} className=\"btn btn-secondary\">\r\n {t('common:buttons.back', 'Back')}\r\n </button>\r\n <button\r\n onClick={handleSubmit}\r\n disabled={!title.trim() || !description.trim() || submitting}\r\n className=\"btn btn-primary\"\r\n >\r\n {submitting ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />\r\n ) : (\r\n <Send className=\"w-4 h-4 mr-2\" />\r\n )}\r\n {t('tickets.create.submit', 'Submit Ticket')}\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n\r\n return (\r\n <div className=\"max-w-3xl mx-auto\">\r\n <div className=\"flex items-center gap-4 mb-6\">\r\n <button onClick={() => navigate(-1)} className=\"btn btn-ghost p-2\">\r\n <ArrowLeft className=\"w-5 h-5\" />\r\n </button>\r\n <div className=\"flex-1\">\r\n <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n <Headset className=\"w-6 h-6\" />\r\n {t('tickets.create.title', 'Create New Ticket')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('tickets.create.subtitle', 'Submit a support request or report an issue')}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n {/* Draft auto-save indicator */}\r\n <div className={`flex items-center gap-1 text-xs text-[var(--success-text)] transition-opacity duration-300 ${\r\n showDraftSaved ? 'opacity-100' : 'opacity-0'\r\n }`}>\r\n <Check className=\"w-3.5 h-3.5\" />\r\n <span>{t('common:drafts.autoSaved', 'Draft saved')}</span>\r\n </div>\r\n {/* Discard draft button */}\r\n {currentDraftId && (\r\n <button\r\n onClick={() => setShowDiscardConfirm(true)}\r\n className=\"btn btn-ghost p-2 text-[var(--text-secondary)] hover:text-[var(--error-text)]\"\r\n title={t('common:drafts.discard', 'Discard draft')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {isGlpi ? (\r\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <div className=\"flex items-center gap-3 mb-3\">\r\n <Info className=\"w-5 h-5 text-[var(--info-text)] flex-shrink-0\" />\r\n <p className=\"font-medium text-[var(--info-text)]\">\r\n {t('glpi.cannotCreateTicket', 'Tickets are managed by GLPI. Please create tickets directly in GLPI.')}\r\n </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-primary inline-flex items-center gap-2\"\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 <div className=\"flex items-center gap-4 mb-8\">\r\n <div className={`flex items-center gap-2 ${step >= 1 ? 'text-[var(--color-primary-600)]' : 'text-[var(--text-secondary)]'}`}>\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center ${\r\n step >= 1 ? 'bg-[var(--color-primary-600)] text-white' : 'bg-[var(--bg-secondary)]'\r\n }`}>\r\n 1\r\n </div>\r\n <span className=\"font-medium\">{t('tickets.create.stepSelectType', 'Select Type')}</span>\r\n </div>\r\n <div className={`flex-1 h-0.5 ${step >= 2 ? 'bg-[var(--color-primary-600)]' : 'bg-[var(--border-color)]'}`} />\r\n <div className={`flex items-center gap-2 ${step >= 2 ? 'text-[var(--color-primary-600)]' : 'text-[var(--text-secondary)]'}`}>\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center ${\r\n step >= 2 ? 'bg-[var(--color-primary-600)] text-white' : 'bg-[var(--bg-secondary)]'\r\n }`}>\r\n 2\r\n </div>\r\n <span className=\"font-medium\">{t('tickets.create.stepDetails', 'Details')}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Tenant context indicator (shown when using locally selected tenant in global view) */}\r\n {selectedTenantForTicket && !currentTenant && (\r\n <div className=\"mb-4 p-3 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--info-text)]\">\r\n <Building2 className=\"w-4 h-4\" />\r\n <span>{t('support:tickets.tenantPicker.creatingFor', 'Creating ticket for:')}</span>\r\n <span className=\"font-semibold\">{selectedTenantForTicket.name}</span>\r\n </div>\r\n <button\r\n onClick={() => setShowTenantPicker(true)}\r\n className=\"text-xs text-[var(--info-text)] underline hover:no-underline\"\r\n >\r\n {t('common:actions.change', 'Change')}\r\n </button>\r\n </div>\r\n )}\r\n\r\n <div className=\"card p-6\">\r\n {step === 1 && renderTypeSelection()}\r\n {step === 2 && renderForm()}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* Discard confirmation modal */}\r\n {showDiscardConfirm && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4\">\r\n <div className=\"card w-full max-w-md p-6\">\r\n <div className=\"flex items-center gap-3 mb-4\">\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--error-bg)] flex items-center justify-center\">\r\n <Trash2 className=\"w-5 h-5 text-[var(--error-text)]\" />\r\n </div>\r\n <h2 className=\"text-xl font-bold\">{t('common:drafts.discardConfirmTitle', 'Discard draft?')}</h2>\r\n </div>\r\n <p className=\"text-[var(--text-secondary)] mb-6\">{t('common:drafts.discardConfirmMessage', 'This draft will be permanently deleted. This action cannot be undone.')}</p>\r\n <div className=\"flex justify-end gap-3\">\r\n <button onClick={() => setShowDiscardConfirm(false)} className=\"btn btn-secondary\">\r\n {t('common:actions.cancel', 'Cancel')}\r\n </button>\r\n <button onClick={handleDiscardDraft} className=\"btn bg-[var(--error-text)] text-white hover:opacity-90\">\r\n {t('common:drafts.discard', 'Discard')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Tenant picker modal (shown in global view when no tenant selected) */}\r\n {showTenantPicker && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4\">\r\n <div className=\"card w-full max-w-md p-6\">\r\n <div className=\"flex items-center gap-3 mb-4\">\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--info-bg)] flex items-center justify-center\">\r\n <Building2 className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <h2 className=\"text-xl font-bold\">{t('support:tickets.tenantPicker.title', 'Select Workspace')}</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">{t('support:tickets.tenantPicker.description', 'Choose a workspace to create the ticket in')}</p>\r\n </div>\r\n </div>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {userTenants\r\n .filter(tenant => tenant.status === 'Active')\r\n .map(tenant => (\r\n <button\r\n key={tenant.id}\r\n onClick={() => {\r\n setSelectedTenantForTicket(tenant);\r\n setShowTenantPicker(false);\r\n // Immediately persist tenant to draft\r\n const id = currentDraftId || ensureDraft();\r\n if (id) {\r\n ticketDraftService.updateDraft(id, {\r\n tenantId: tenant.id,\r\n tenantSlug: tenant.slug,\r\n tenantName: tenant.name,\r\n });\r\n }\r\n }}\r\n className={`w-full p-3 rounded-lg border text-left transition-colors hover:bg-[var(--bg-hover)] ${\r\n selectedTenantForTicket?.id === tenant.id\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)]'\r\n }`}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n <Building2 className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"font-medium truncate\">{tenant.name}</div>\r\n {tenant.organisationName && (\r\n <div className=\"text-xs text-[var(--text-secondary)] truncate\">{tenant.organisationName}</div>\r\n )}\r\n </div>\r\n <span className={`text-xs px-2 py-0.5 rounded-full ${\r\n tenant.type === 'Personal'\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)]'\r\n : 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n }`}>\r\n {tenant.type === 'Personal' ? t('common:tenant.personal', 'Personal') : t('common:tenant.business', 'Business')}\r\n </span>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n <div className=\"flex justify-end gap-3 mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => {\r\n setShowTenantPicker(false);\r\n if (!effectiveTenant) navigate(-1);\r\n }}\r\n className=\"btn btn-secondary\"\r\n >\r\n {t('common:actions.cancel', 'Cancel')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ticketTypes","Bug","Lightbulb","AppWindow","MessageSquare","HelpCircle","priorityOptions","MAX_FILE_SIZE","MAX_ATTACHMENTS","ALLOWED_EXTENSIONS","formatFileSize","bytes","getFileIcon","type","FileText","ImageIcon","FileIcon","restoreDraft","draftId","userTenants","draft","ticketDraftService","selectedTenant","matchingTenant","t","restoreSessionContext","sessionContext","autoSelectType","uploadScreenshot","ticketId","screenshot","selectedTenantForTicket","blob","file","formData","tenantHeaders","api","myTicketsApi","uploadAttachments","attachments","attachment","UserCreateTicketPage","navigate","useNavigate","searchParams","useSearchParams","useTranslation","isGlpi","glpiBaseUrl","useTicketingProvider","currentTenant","isGlobalView","useTenant","screenshotInputRef","useRef","attachmentInputRef","setSelectedTenantForTicket","useState","showTenantPicker","setShowTenantPicker","effectiveTenant","useEffect","step","setStep","selectedType","setSelectedType","title","setTitle","description","setDescription","priority","setPriority","submitting","setSubmitting","error","setError","browserInfo","setBrowserInfo","includeBrowserInfo","setIncludeBrowserInfo","setScreenshot","annotatedScreenshot","setAnnotatedScreenshot","isDraggingScreenshot","setIsDraggingScreenshot","setAttachments","isDraggingAttachment","setIsDraggingAttachment","currentDraftId","setCurrentDraftId","showDraftSaved","setShowDraftSaved","showDiscardConfirm","setShowDiscardConfirm","autoSaveTimerRef","isInitialLoadCompleteRef","hasUnsavedChangesRef","saveDraftNow","useCallback","result","ensureDraft","newDraft","handleBeforeUnload","handleDiscardDraft","validTypes","prefillType","prefillSubject","prefillBody","errorContextService","sessionScreenshot","info","browserInfoService","processImageFile","reader","e","dataUrl","handleScreenshotUpload","event","handleScreenshotDragOver","handleScreenshotDragLeave","handleScreenshotDrop","files","handleRemoveScreenshot","handleAnnotatedScreenshot","isAllowedFileType","extension","processAttachmentFiles","newAttachments","i","a","generateUUID","prev","handleAttachmentUpload","handleAttachmentDragOver","handleAttachmentDragLeave","handleAttachmentDrop","handleRemoveAttachment","id","handleSubmit","fullDescription","currentBrowserInfo","recentErrors","logService","clientContext","ticket","err","serverMessage","renderTypeSelection","jsxs","jsx","renderForm","ArrowLeft","tt","option","X","ScreenshotAnnotator","Upload","Paperclip","AttachmentIcon","Monitor","AlertTriangle","Loader2","Send","Headset","Check","Trash2","Info","ExternalLink","Fragment","Building2","tenant"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UserCreateTicketPage-lvlvp2u6.js","sources":["../../src/pages/platform/support/UserCreateTicketPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate, useSearchParams } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n ArrowLeft, Headset, Bug, Lightbulb, AppWindow, HelpCircle, MessageSquare,\r\n Loader2, AlertTriangle, Send, Monitor, Upload, X, Image as ImageIcon,\r\n FileText, File as FileIcon, Paperclip, Info, ExternalLink, Building2, Check, Trash2\r\n} from 'lucide-react';\r\nimport { myTicketsApi, type TicketType, type TicketPriority, type ClientContextDto, type MyTicketDetailDto } from '@/services/api/ticketApi';\r\nimport { api } from '@/services/api/apiClient';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport type { UserTenantDto } from '@/services/api/adminApi';\r\nimport { browserInfoService, type BrowserInfo } from '@/services/support/browserInfoService';\r\nimport { useTicketingProvider } from '@/hooks/useTicketingProvider';\r\nimport { generateUUID } from '@/utils/uuid';\r\nimport { logService } from '@/services/logging/logService';\r\nimport { ScreenshotAnnotator } from '@/components/platform/support/ScreenshotAnnotator';\r\nimport { errorContextService } from '@/services/support/errorContextService';\r\nimport { ticketDraftService } from '@/services/support/ticketDraftService';\r\n\r\nconst ticketTypes: { value: TicketType; label: string; labelKey: string; description: string; descriptionKey: string; icon: React.ElementType }[] = [\r\n {\r\n value: 'Bug',\r\n label: 'Report a Bug',\r\n labelKey: 'tickets.types.bug',\r\n description: 'Something is not working correctly',\r\n descriptionKey: 'tickets.types.bugDescription',\r\n icon: Bug,\r\n },\r\n {\r\n value: 'FeatureRequest',\r\n label: 'Request a Feature',\r\n labelKey: 'tickets.types.featureRequest',\r\n description: 'Suggest an improvement or new feature',\r\n descriptionKey: 'tickets.types.featureRequestDescription',\r\n icon: Lightbulb,\r\n },\r\n {\r\n value: 'ApplicationRequest',\r\n label: 'Request an Application',\r\n labelKey: 'tickets.types.applicationRequest',\r\n description: 'Request access to a new application',\r\n descriptionKey: 'tickets.types.applicationRequestDescription',\r\n icon: AppWindow,\r\n },\r\n {\r\n value: 'Support',\r\n label: 'General Support',\r\n labelKey: 'tickets.types.support',\r\n description: 'Need help with something',\r\n descriptionKey: 'tickets.types.supportDescription',\r\n icon: MessageSquare,\r\n },\r\n {\r\n value: 'Question',\r\n label: 'Ask a Question',\r\n labelKey: 'tickets.types.question',\r\n description: 'Have a question about the platform',\r\n descriptionKey: 'tickets.types.questionDescription',\r\n icon: HelpCircle,\r\n },\r\n];\r\n\r\nconst priorityOptions: { value: TicketPriority; label: string; labelKey: string; description: string; descriptionKey: string }[] = [\r\n { value: 'Low', label: 'Low', labelKey: 'tickets.priority.low', description: 'Can wait, not urgent', descriptionKey: 'tickets.priority.lowDescription' },\r\n { value: 'Medium', label: 'Medium', labelKey: 'tickets.priority.medium', description: 'Normal priority', descriptionKey: 'tickets.priority.mediumDescription' },\r\n { value: 'High', label: 'High', labelKey: 'tickets.priority.high', description: 'Important, needs attention soon', descriptionKey: 'tickets.priority.highDescription' },\r\n { value: 'Critical', label: 'Critical', labelKey: 'tickets.priority.critical', description: 'Urgent, blocking work', descriptionKey: 'tickets.priority.criticalDescription' },\r\n];\r\n\r\ninterface AttachmentFile {\r\n id: string;\r\n file: File;\r\n name: string;\r\n size: number;\r\n type: string;\r\n}\r\n\r\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\r\nconst MAX_ATTACHMENTS = 5;\r\nconst ALLOWED_EXTENSIONS = ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.txt', '.csv', '.zip', '.rar', '.7z', '.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'];\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes} B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\r\n}\r\n\r\nfunction getFileIcon(type: string) {\r\n if (type.includes('pdf')) return FileText;\r\n if (type.startsWith('image/')) return ImageIcon;\r\n return FileIcon;\r\n}\r\n\r\nfunction restoreDraft(draftId: string | null, userTenants: UserTenantDto[]) {\r\n if (!draftId) return { draft: null, selectedTenant: null };\r\n\r\n const draft = ticketDraftService.getDraft(draftId);\r\n if (!draft) return { draft: null, selectedTenant: null };\r\n\r\n let selectedTenant: UserTenantDto | null = null;\r\n if (draft.tenantId && draft.tenantSlug) {\r\n const matchingTenant = userTenants.find(t => t.id === draft.tenantId);\r\n if (matchingTenant) {\r\n selectedTenant = matchingTenant;\r\n }\r\n }\r\n\r\n return { draft, selectedTenant };\r\n}\r\n\r\nfunction restoreSessionContext(sessionContext: ReturnType<typeof errorContextService.loadContext>) {\r\n if (!sessionContext?.screenshot) return { screenshot: null, autoSelectType: null };\r\n\r\n let autoSelectType: TicketType | null = null;\r\n if (sessionContext.recentErrors.length > 0) {\r\n autoSelectType = 'Bug';\r\n }\r\n\r\n return { screenshot: sessionContext.screenshot, autoSelectType };\r\n}\r\n\r\nasync function uploadScreenshot(ticketId: string, screenshot: string, selectedTenantForTicket: UserTenantDto | null) {\r\n try {\r\n const response = await fetch(screenshot);\r\n const blob = await response.blob();\r\n const file = new File([blob], 'screenshot.png', { type: 'image/png' });\r\n\r\n if (selectedTenantForTicket) {\r\n const formData = new FormData();\r\n formData.append('file', file);\r\n const tenantHeaders = { 'X-Tenant-Slug': selectedTenantForTicket.slug };\r\n await api.post(`/api/support/my-tickets/${ticketId}/attachments`, formData, {\r\n headers: { 'Content-Type': 'multipart/form-data', ...tenantHeaders },\r\n });\r\n } else {\r\n await myTicketsApi.uploadAttachment(ticketId, file);\r\n }\r\n } catch (attachmentError) {\r\n // Silent fail for attachment upload\r\n }\r\n}\r\n\r\nasync function uploadAttachments(ticketId: string, attachments: AttachmentFile[], selectedTenantForTicket: UserTenantDto | null) {\r\n for (const attachment of attachments) {\r\n try {\r\n if (selectedTenantForTicket) {\r\n const formData = new FormData();\r\n formData.append('file', attachment.file);\r\n const tenantHeaders = { 'X-Tenant-Slug': selectedTenantForTicket.slug };\r\n await api.post(`/api/support/my-tickets/${ticketId}/attachments`, formData, {\r\n headers: { 'Content-Type': 'multipart/form-data', ...tenantHeaders },\r\n });\r\n } else {\r\n await myTicketsApi.uploadAttachment(ticketId, attachment.file);\r\n }\r\n } catch (attachmentError) {\r\n // Silent fail for attachment upload\r\n }\r\n }\r\n}\r\n\r\nexport function UserCreateTicketPage(): ReactElement {\r\n const navigate = useNavigate();\r\n const [searchParams] = useSearchParams();\r\n const { t } = useTranslation(['support', 'common']);\r\n const { isGlpi, glpiBaseUrl } = useTicketingProvider();\r\n const { currentTenant, userTenants, isGlobalView } = useTenant();\r\n const screenshotInputRef = useRef<HTMLInputElement>(null);\r\n const attachmentInputRef = useRef<HTMLInputElement>(null);\r\n\r\n // When in global view (no tenant selected), allow user to pick a tenant for the ticket\r\n const [selectedTenantForTicket, setSelectedTenantForTicket] = useState<UserTenantDto | null>(null);\r\n const [showTenantPicker, setShowTenantPicker] = useState(false);\r\n\r\n // The effective tenant: either the global current tenant or the locally selected one\r\n const effectiveTenant = currentTenant ?? selectedTenantForTicket;\r\n\r\n // Show tenant picker on mount when no tenant is selected\r\n useEffect(() => {\r\n if (!currentTenant && isGlobalView && userTenants.length > 0) {\r\n setShowTenantPicker(true);\r\n }\r\n }, [currentTenant, isGlobalView, userTenants.length]);\r\n\r\n const draftId = searchParams.get('draft');\r\n\r\n const [step, setStep] = useState(1);\r\n const [selectedType, setSelectedType] = useState<TicketType | null>(null);\r\n const [title, setTitle] = useState('');\r\n const [description, setDescription] = useState('');\r\n const [priority, setPriority] = useState<TicketPriority>('Medium');\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n // Browser info state\r\n const [browserInfo, setBrowserInfo] = useState<BrowserInfo | null>(null);\r\n const [includeBrowserInfo, setIncludeBrowserInfo] = useState(true);\r\n\r\n // Screenshot state\r\n const [screenshot, setScreenshot] = useState<string | null>(null);\r\n const [annotatedScreenshot, setAnnotatedScreenshot] = useState<string | null>(null);\r\n const [isDraggingScreenshot, setIsDraggingScreenshot] = useState(false);\r\n\r\n // Attachments state\r\n const [attachments, setAttachments] = useState<AttachmentFile[]>([]);\r\n const [isDraggingAttachment, setIsDraggingAttachment] = useState(false);\r\n\r\n // Draft auto-save state\r\n const [currentDraftId, setCurrentDraftId] = useState<string | null>(draftId);\r\n const [showDraftSaved, setShowDraftSaved] = useState(false);\r\n const [showDiscardConfirm, setShowDiscardConfirm] = useState(false);\r\n const autoSaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const isInitialLoadCompleteRef = useRef(false);\r\n const hasUnsavedChangesRef = useRef(false);\r\n\r\n // Save draft function\r\n const saveDraftNow = useCallback(() => {\r\n if (!currentDraftId) return false;\r\n\r\n const result = ticketDraftService.updateDraft(currentDraftId, {\r\n type: selectedType,\r\n title,\r\n description,\r\n priority,\r\n includeScreenshot: !!annotatedScreenshot,\r\n includeErrorLogs: false,\r\n screenshot: annotatedScreenshot ?? undefined,\r\n tenantId: effectiveTenant?.id,\r\n tenantSlug: effectiveTenant?.slug,\r\n tenantName: effectiveTenant?.name,\r\n });\r\n\r\n if (result.success) {\r\n hasUnsavedChangesRef.current = false;\r\n setShowDraftSaved(true);\r\n setTimeout(() => setShowDraftSaved(false), 2000);\r\n }\r\n return result.success;\r\n }, [currentDraftId, selectedType, title, description, priority, annotatedScreenshot, effectiveTenant]);\r\n\r\n // Auto-create draft when user starts filling the form (no existing draft)\r\n const ensureDraft = useCallback(() => {\r\n if (currentDraftId) return currentDraftId;\r\n const newDraft = ticketDraftService.createDraft();\r\n setCurrentDraftId(newDraft.id);\r\n return newDraft.id;\r\n }, [currentDraftId]);\r\n\r\n // Debounced auto-save when form data changes\r\n useEffect(() => {\r\n if (!isInitialLoadCompleteRef.current) return;\r\n // Only auto-save if there's meaningful data\r\n if (!selectedType && !title && !description) return;\r\n\r\n hasUnsavedChangesRef.current = true;\r\n\r\n // Ensure a draft exists before saving\r\n if (!currentDraftId) {\r\n ensureDraft();\r\n return; // Will re-trigger on next render with currentDraftId set\r\n }\r\n\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n }\r\n\r\n autoSaveTimerRef.current = setTimeout(() => {\r\n saveDraftNow();\r\n }, 1000);\r\n\r\n return () => {\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n }\r\n };\r\n }, [selectedType, title, description, priority, annotatedScreenshot, currentDraftId, saveDraftNow, ensureDraft]);\r\n\r\n // Save on unmount + beforeunload\r\n useEffect(() => {\r\n const handleBeforeUnload = () => {\r\n if (hasUnsavedChangesRef.current && currentDraftId) {\r\n saveDraftNow();\r\n }\r\n };\r\n\r\n window.addEventListener('beforeunload', handleBeforeUnload);\r\n return () => {\r\n window.removeEventListener('beforeunload', handleBeforeUnload);\r\n if (hasUnsavedChangesRef.current && currentDraftId) {\r\n saveDraftNow();\r\n }\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n }\r\n };\r\n }, [currentDraftId, saveDraftNow]);\r\n\r\n // Discard draft handler\r\n const handleDiscardDraft = useCallback(() => {\r\n if (currentDraftId) {\r\n ticketDraftService.deleteDraft(currentDraftId);\r\n }\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n autoSaveTimerRef.current = null;\r\n }\r\n navigate(-1);\r\n }, [currentDraftId, navigate]);\r\n\r\n // Load draft, session context, URL pre-fill params, and browser info on mount\r\n useEffect(() => {\r\n // Load draft if resuming\r\n const { draft, selectedTenant } = restoreDraft(draftId, userTenants);\r\n if (draft) {\r\n if (draft.type) {\r\n setSelectedType(draft.type);\r\n setStep(2);\r\n }\r\n if (draft.title) setTitle(draft.title);\r\n if (draft.description) setDescription(draft.description);\r\n if (draft.priority) setPriority(draft.priority);\r\n if (draft.screenshot) {\r\n setScreenshot(draft.screenshot);\r\n setAnnotatedScreenshot(draft.screenshot);\r\n }\r\n if (selectedTenant) {\r\n setSelectedTenantForTicket(selectedTenant);\r\n }\r\n }\r\n\r\n // Pre-fill from URL params (e.g. from AccessDenied page) — draft takes priority\r\n if (!draft) {\r\n const validTypes: TicketType[] = ['Bug', 'FeatureRequest', 'Suggestion', 'ApplicationRequest', 'Support', 'Question'];\r\n const prefillType = searchParams.get('type') as TicketType | null;\r\n const prefillSubject = searchParams.get('subject');\r\n const prefillBody = searchParams.get('body');\r\n\r\n if (prefillType && validTypes.includes(prefillType)) {\r\n setSelectedType(prefillType);\r\n setStep(2);\r\n }\r\n if (prefillSubject) setTitle(decodeURIComponent(prefillSubject));\r\n if (prefillBody) setDescription(decodeURIComponent(prefillBody));\r\n }\r\n\r\n // Load captured screenshot from session context (from CreateTicketButton)\r\n const sessionContext = errorContextService.loadContext();\r\n const { screenshot: sessionScreenshot, autoSelectType } = restoreSessionContext(sessionContext);\r\n if (sessionScreenshot && !annotatedScreenshot) {\r\n setScreenshot(sessionScreenshot);\r\n setAnnotatedScreenshot(sessionScreenshot);\r\n\r\n if (autoSelectType && !selectedType) {\r\n setSelectedType(autoSelectType);\r\n setPriority('High');\r\n }\r\n }\r\n errorContextService.clearContext();\r\n\r\n const info = browserInfoService.captureBrowserInfo();\r\n setBrowserInfo(info);\r\n\r\n // Mark initial load complete (prevents auto-save during hydration)\r\n setTimeout(() => { isInitialLoadCompleteRef.current = true; }, 100);\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [draftId]);\r\n\r\n // Process image file for screenshot\r\n const processImageFile = useCallback((file: File) => {\r\n if (!file.type.startsWith('image/')) {\r\n setError(t('tickets.create.invalidImageType', 'Please select a valid image file'));\r\n return;\r\n }\r\n\r\n if (file.size > MAX_FILE_SIZE) {\r\n setError(t('tickets.create.imageTooLarge', 'Image must be less than 10MB'));\r\n return;\r\n }\r\n\r\n const reader = new FileReader();\r\n reader.onload = (e) => {\r\n const dataUrl = e.target?.result as string;\r\n setScreenshot(dataUrl);\r\n setAnnotatedScreenshot(dataUrl);\r\n setError(null);\r\n };\r\n reader.onerror = () => {\r\n setError(t('tickets.create.imageReadError', 'Failed to read image file'));\r\n };\r\n reader.readAsDataURL(file);\r\n }, [t]);\r\n\r\n const handleScreenshotUpload = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = event.target.files?.[0];\r\n if (file) {\r\n processImageFile(file);\r\n }\r\n }, [processImageFile]);\r\n\r\n // Drag & Drop handlers for screenshot\r\n const handleScreenshotDragOver = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingScreenshot(true);\r\n }, []);\r\n\r\n const handleScreenshotDragLeave = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingScreenshot(false);\r\n }, []);\r\n\r\n const handleScreenshotDrop = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingScreenshot(false);\r\n\r\n const files = e.dataTransfer.files;\r\n if (files.length > 0) {\r\n const file = files[0];\r\n if (file.type.startsWith('image/')) {\r\n processImageFile(file);\r\n } else {\r\n setError(t('tickets.create.invalidImageType', 'Please select a valid image file'));\r\n }\r\n }\r\n }, [processImageFile, t]);\r\n\r\n const handleRemoveScreenshot = useCallback(() => {\r\n setScreenshot(null);\r\n setAnnotatedScreenshot(null);\r\n if (screenshotInputRef.current) {\r\n screenshotInputRef.current.value = '';\r\n }\r\n }, []);\r\n\r\n const handleAnnotatedScreenshot = useCallback((dataUrl: string) => {\r\n setAnnotatedScreenshot(dataUrl);\r\n }, []);\r\n\r\n // Attachment handlers\r\n const isAllowedFileType = useCallback((file: File): boolean => {\r\n // Allow all images\r\n if (file.type.startsWith('image/')) {\r\n return true;\r\n }\r\n const extension = '.' + file.name.split('.').pop()?.toLowerCase();\r\n return ALLOWED_EXTENSIONS.includes(extension);\r\n }, []);\r\n\r\n const processAttachmentFiles = useCallback((files: FileList) => {\r\n const newAttachments: AttachmentFile[] = [];\r\n\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i];\r\n\r\n // Skip if already at max attachments\r\n if (attachments.length + newAttachments.length >= MAX_ATTACHMENTS) {\r\n setError(t('tickets.create.maxAttachments', `Maximum ${MAX_ATTACHMENTS} attachments allowed`));\r\n break;\r\n }\r\n\r\n // Check file size\r\n if (file.size > MAX_FILE_SIZE) {\r\n setError(t('tickets.create.fileTooLarge', `File \"${file.name}\" is too large (max 10MB)`));\r\n continue;\r\n }\r\n\r\n // Check file type\r\n if (!isAllowedFileType(file)) {\r\n setError(t('tickets.create.invalidFileType', `File type not allowed: ${file.name}`));\r\n continue;\r\n }\r\n\r\n // Check for duplicates\r\n const isDuplicate = attachments.some(a => a.name === file.name && a.size === file.size);\r\n if (isDuplicate) {\r\n continue;\r\n }\r\n\r\n newAttachments.push({\r\n id: generateUUID(),\r\n file,\r\n name: file.name,\r\n size: file.size,\r\n type: file.type,\r\n });\r\n }\r\n\r\n if (newAttachments.length > 0) {\r\n setAttachments(prev => [...prev, ...newAttachments]);\r\n setError(null);\r\n }\r\n }, [attachments, isAllowedFileType, t]);\r\n\r\n const handleAttachmentUpload = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = event.target.files;\r\n if (files) {\r\n processAttachmentFiles(files);\r\n }\r\n // Reset input\r\n if (attachmentInputRef.current) {\r\n attachmentInputRef.current.value = '';\r\n }\r\n }, [processAttachmentFiles]);\r\n\r\n // Drag & Drop handlers for attachments\r\n const handleAttachmentDragOver = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingAttachment(true);\r\n }, []);\r\n\r\n const handleAttachmentDragLeave = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingAttachment(false);\r\n }, []);\r\n\r\n const handleAttachmentDrop = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDraggingAttachment(false);\r\n\r\n const files = e.dataTransfer.files;\r\n if (files.length > 0) {\r\n processAttachmentFiles(files);\r\n }\r\n }, [processAttachmentFiles]);\r\n\r\n const handleRemoveAttachment = useCallback((id: string) => {\r\n setAttachments(prev => prev.filter(a => a.id !== id));\r\n }, []);\r\n\r\n const handleSubmit = async () => {\r\n if (!selectedType || !title.trim() || !description.trim()) return;\r\n\r\n if (!effectiveTenant) {\r\n setShowTenantPicker(true);\r\n return;\r\n }\r\n\r\n try {\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n // Build description with browser info if enabled\r\n let fullDescription = description.trim();\r\n\r\n if (includeBrowserInfo && browserInfo) {\r\n fullDescription += '\\n\\n---\\n**System Information:**\\n' + browserInfoService.formatForDescription(browserInfo);\r\n }\r\n\r\n // Build structured client context for backend storage\r\n const currentBrowserInfo = browserInfo || browserInfoService.captureBrowserInfo();\r\n const recentErrors = logService.getRecentErrors().slice(0, 5);\r\n const clientContext: ClientContextDto = {\r\n sourceUrl: window.location.href,\r\n browser: {\r\n name: currentBrowserInfo.browser,\r\n version: currentBrowserInfo.browserVersion,\r\n language: currentBrowserInfo.language,\r\n },\r\n os: {\r\n name: currentBrowserInfo.os,\r\n version: currentBrowserInfo.osVersion,\r\n },\r\n device: {\r\n type: currentBrowserInfo.deviceType,\r\n screenResolution: currentBrowserInfo.screenResolution,\r\n },\r\n recentErrors: recentErrors.map((e) => ({\r\n message: e.message,\r\n stack: e.stack,\r\n component: e.component,\r\n timestamp: e.timestamp.toISOString(),\r\n })),\r\n };\r\n\r\n // If using locally selected tenant (global view), override X-Tenant-Slug header\r\n const tenantHeaders = selectedTenantForTicket\r\n ? { 'X-Tenant-Slug': selectedTenantForTicket.slug }\r\n : {};\r\n\r\n const ticket = selectedTenantForTicket\r\n ? await api.post<MyTicketDetailDto>('/api/support/my-tickets', {\r\n title: title.trim(),\r\n description: fullDescription,\r\n type: selectedType,\r\n priority,\r\n clientContext,\r\n }, { headers: tenantHeaders })\r\n : await myTicketsApi.create({\r\n title: title.trim(),\r\n description: fullDescription,\r\n type: selectedType,\r\n priority,\r\n clientContext,\r\n });\r\n\r\n // Upload screenshot as attachment if present\r\n if (annotatedScreenshot) {\r\n await uploadScreenshot(ticket.id, annotatedScreenshot, selectedTenantForTicket);\r\n }\r\n\r\n // Upload other attachments\r\n await uploadAttachments(ticket.id, attachments, selectedTenantForTicket);\r\n\r\n // Clean up draft on successful submit\r\n if (currentDraftId) {\r\n ticketDraftService.deleteDraft(currentDraftId);\r\n }\r\n if (autoSaveTimerRef.current) {\r\n clearTimeout(autoSaveTimerRef.current);\r\n autoSaveTimerRef.current = null;\r\n }\r\n hasUnsavedChangesRef.current = false;\r\n\r\n navigate(`/support/my-tickets/${ticket.id}?tab=submitted`);\r\n } catch (err: unknown) {\r\n const serverMessage = err && typeof err === 'object' && 'message' in err\r\n ? (err as { message: string }).message\r\n : null;\r\n setError(serverMessage || t('tickets.create.submitError', 'Failed to create ticket. Please try again.'));\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n const renderTypeSelection = () => (\r\n <div className=\"space-y-4\">\r\n <h2 className=\"text-lg font-semibold mb-4\">{t('tickets.create.selectType', 'What type of request do you have?')}</h2>\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n {ticketTypes.map((type) => (\r\n <button\r\n key={type.value}\r\n onClick={() => {\r\n setSelectedType(type.value);\r\n setStep(2);\r\n }}\r\n className={`card p-4 text-left hover:shadow-md transition-shadow ${\r\n selectedType === type.value ? 'ring-2 ring-[var(--color-primary-600)]' : ''\r\n }`}\r\n >\r\n <div className=\"flex items-start gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <type.icon className=\"w-6 h-6\" />\r\n </div>\r\n <div>\r\n <h3 className=\"font-medium\">{t(type.labelKey, type.label)}</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">{t(type.descriptionKey, type.description)}</p>\r\n </div>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n\r\n const renderForm = () => (\r\n <div className=\"space-y-6\">\r\n <div className=\"flex items-center gap-4 mb-6\">\r\n <button onClick={() => setStep(1)} className=\"btn btn-ghost p-2\">\r\n <ArrowLeft className=\"w-5 h-5\" />\r\n </button>\r\n <div>\r\n <h2 className=\"text-lg font-semibold\">\r\n {t(ticketTypes.find((tt) => tt.value === selectedType)?.labelKey || '', { defaultValue: ticketTypes.find((tt) => tt.value === selectedType)?.label })}\r\n </h2>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('tickets.create.fillDetails', 'Fill in the details below')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n {t('tickets.form.title', 'Title')} <span className=\"text-[var(--error-text)]\">*</span>\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n placeholder={t('tickets.create.titlePlaceholder', 'Brief summary of your request')}\r\n className=\"input w-full\"\r\n maxLength={200}\r\n />\r\n <p className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n {title.length}/200 {t('common:text.characters', 'characters')}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n {t('tickets.create.description', 'Description')} <span className=\"text-[var(--error-text)]\">*</span>\r\n </label>\r\n <textarea\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n placeholder={\r\n selectedType === 'Bug'\r\n ? t('tickets.create.bugPlaceholder', 'Please describe the issue in detail. Include steps to reproduce, expected behavior, and actual behavior.')\r\n : selectedType === 'FeatureRequest'\r\n ? t('tickets.create.featurePlaceholder', 'Describe the feature you would like to see and why it would be useful.')\r\n : selectedType === 'ApplicationRequest'\r\n ? t('tickets.create.applicationPlaceholder', 'Which application do you need access to and why?')\r\n : t('tickets.create.defaultPlaceholder', 'Please provide as much detail as possible.')\r\n }\r\n className=\"input w-full h-40\"\r\n maxLength={5000}\r\n />\r\n <p className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n {description.length}/5000 {t('common:text.characters', 'characters')}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">{t('tickets.create.priority', 'Priority')}</label>\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2\">\r\n {priorityOptions.map((option) => (\r\n <button\r\n key={option.value}\r\n type=\"button\"\r\n onClick={() => setPriority(option.value)}\r\n className={`p-3 rounded-lg border text-center transition-colors ${\r\n priority === option.value\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <div className=\"font-medium\">{t(option.labelKey, option.label)}</div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">{t(option.descriptionKey, option.description)}</div>\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Screenshot Upload Section */}\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n <ImageIcon className=\"w-4 h-4 inline mr-2\" />\r\n {t('tickets.create.screenshot', 'Screenshot')}\r\n <span className=\"text-[var(--text-secondary)] font-normal ml-2\">({t('common:text.optional', 'optional')})</span>\r\n </label>\r\n\r\n {!screenshot ? (\r\n <div\r\n className={`border-2 border-dashed rounded-lg p-6 text-center cursor-pointer transition-colors ${\r\n isDraggingScreenshot\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-primary-600)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n onClick={() => screenshotInputRef.current?.click()}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); screenshotInputRef.current?.click(); } }}\r\n role=\"button\"\r\n tabIndex={0}\r\n onDragOver={handleScreenshotDragOver}\r\n onDragLeave={handleScreenshotDragLeave}\r\n onDrop={handleScreenshotDrop}\r\n >\r\n <Upload className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-secondary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {isDraggingScreenshot\r\n ? t('tickets.create.dropScreenshotNow', 'Drop image here')\r\n : t('tickets.create.uploadScreenshot', 'Click or drag & drop to upload a screenshot')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)] mt-1\">\r\n {t('tickets.create.uploadScreenshotHint', 'PNG, JPG, or GIF up to 10MB')}\r\n </p>\r\n <input\r\n ref={screenshotInputRef}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n onChange={handleScreenshotUpload}\r\n className=\"hidden\"\r\n />\r\n </div>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('tickets.create.screenshotUploaded', 'Screenshot uploaded - you can annotate it below')}\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={handleRemoveScreenshot}\r\n className=\"btn btn-ghost p-2 text-[var(--error-text)]\"\r\n title={t('tickets.create.removeScreenshot', 'Remove screenshot')}\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <ScreenshotAnnotator\r\n screenshot={screenshot}\r\n onAnnotatedScreenshot={handleAnnotatedScreenshot}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Attachments Section */}\r\n <div>\r\n <label className=\"block text-sm font-medium mb-2\">\r\n <Paperclip className=\"w-4 h-4 inline mr-2\" />\r\n {t('tickets.create.attachments', 'Attachments')}\r\n <span className=\"text-[var(--text-secondary)] font-normal ml-2\">({t('common:text.optional', 'optional')})</span>\r\n </label>\r\n\r\n <div\r\n className={`border-2 border-dashed rounded-lg p-4 text-center cursor-pointer transition-colors ${\r\n isDraggingAttachment\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-primary-600)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n onClick={() => attachmentInputRef.current?.click()}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); attachmentInputRef.current?.click(); } }}\r\n role=\"button\"\r\n tabIndex={0}\r\n onDragOver={handleAttachmentDragOver}\r\n onDragLeave={handleAttachmentDragLeave}\r\n onDrop={handleAttachmentDrop}\r\n >\r\n <Upload className=\"w-6 h-6 mx-auto mb-1 text-[var(--text-secondary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {isDraggingAttachment\r\n ? t('tickets.create.dropFilesNow', 'Drop files here')\r\n : t('tickets.create.uploadAttachments', 'Click or drag & drop to add documents')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)] mt-1\">\r\n {t('tickets.create.attachmentsHint', 'PDF, Word, Excel, TXT, CSV, ZIP (max 10MB each, up to 5 files)')}\r\n </p>\r\n <input\r\n ref={attachmentInputRef}\r\n type=\"file\"\r\n multiple\r\n accept=\".pdf,.doc,.docx,.xls,.xlsx,.txt,.csv,.zip,.rar,.7z,image/*\"\r\n onChange={handleAttachmentUpload}\r\n className=\"hidden\"\r\n />\r\n </div>\r\n\r\n {/* Attachments List */}\r\n {attachments.length > 0 && (\r\n <div className=\"mt-3 space-y-2\">\r\n {attachments.map((attachment) => {\r\n const AttachmentIcon = getFileIcon(attachment.type);\r\n return (\r\n <div\r\n key={attachment.id}\r\n className=\"flex items-center justify-between p-2 rounded-lg bg-[var(--bg-secondary)]\"\r\n >\r\n <div className=\"flex items-center gap-2 min-w-0\">\r\n <AttachmentIcon className=\"w-4 h-4 text-[var(--text-secondary)] flex-shrink-0\" />\r\n <span className=\"text-sm truncate\">{attachment.name}</span>\r\n <span className=\"text-xs text-[var(--text-muted)] flex-shrink-0\">\r\n ({formatFileSize(attachment.size)})\r\n </span>\r\n </div>\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRemoveAttachment(attachment.id)}\r\n className=\"btn btn-ghost p-1 text-[var(--error-text)]\"\r\n title={t('tickets.create.removeAttachment', 'Remove attachment')}\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Browser Info Section */}\r\n {browserInfo && (\r\n <div className=\"border border-[var(--border-color)] rounded-lg p-4\">\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <Monitor className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n <span className=\"text-sm font-medium\">{t('tickets.create.systemInfo', 'System Information')}</span>\r\n </div>\r\n <label className=\"flex items-center gap-2 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={includeBrowserInfo}\r\n onChange={(e) => setIncludeBrowserInfo(e.target.checked)}\r\n className=\"rounded border-[var(--border-color)]\"\r\n />\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {t('tickets.create.includeSystemInfo', 'Include in ticket')}\r\n </span>\r\n </label>\r\n </div>\r\n <div className={`grid grid-cols-2 md:grid-cols-3 gap-3 text-sm ${!includeBrowserInfo ? 'opacity-50' : ''}`}>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.browser', 'Browser')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.browser} {browserInfo.browserVersion}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.os', 'OS')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.os} {browserInfo.osVersion}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.device', 'Device')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.deviceType}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.screen', 'Screen')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.screenResolution}</span>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('tickets.create.language', 'Language')}:</span>\r\n <span className=\"ml-2 font-medium\">{browserInfo.language}</span>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-[var(--error-bg)] text-[var(--error-text)] flex items-center gap-2\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n {error}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex items-center justify-between pt-4 border-t border-[var(--border-color)]\">\r\n <button onClick={() => setStep(1)} className=\"btn btn-secondary\">\r\n {t('common:buttons.back', 'Back')}\r\n </button>\r\n <button\r\n onClick={handleSubmit}\r\n disabled={!title.trim() || !description.trim() || submitting}\r\n className=\"btn btn-primary\"\r\n >\r\n {submitting ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />\r\n ) : (\r\n <Send className=\"w-4 h-4 mr-2\" />\r\n )}\r\n {t('tickets.create.submit', 'Submit Ticket')}\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n\r\n return (\r\n <div className=\"max-w-3xl mx-auto\">\r\n <div className=\"flex items-center gap-4 mb-6\">\r\n <button onClick={() => navigate(-1)} className=\"btn btn-ghost p-2\">\r\n <ArrowLeft className=\"w-5 h-5\" />\r\n </button>\r\n <div className=\"flex-1\">\r\n <h1 className=\"text-2xl font-bold flex items-center gap-2\">\r\n <Headset className=\"w-6 h-6\" />\r\n {t('tickets.create.title', 'Create New Ticket')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('tickets.create.subtitle', 'Submit a support request or report an issue')}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n {/* Draft auto-save indicator */}\r\n <div className={`flex items-center gap-1 text-xs text-[var(--success-text)] transition-opacity duration-300 ${\r\n showDraftSaved ? 'opacity-100' : 'opacity-0'\r\n }`}>\r\n <Check className=\"w-3.5 h-3.5\" />\r\n <span>{t('common:drafts.autoSaved', 'Draft saved')}</span>\r\n </div>\r\n {/* Discard draft button */}\r\n {currentDraftId && (\r\n <button\r\n onClick={() => setShowDiscardConfirm(true)}\r\n className=\"btn btn-ghost p-2 text-[var(--text-secondary)] hover:text-[var(--error-text)]\"\r\n title={t('common:drafts.discard', 'Discard draft')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {isGlpi ? (\r\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <div className=\"flex items-center gap-3 mb-3\">\r\n <Info className=\"w-5 h-5 text-[var(--info-text)] flex-shrink-0\" />\r\n <p className=\"font-medium text-[var(--info-text)]\">\r\n {t('glpi.cannotCreateTicket', 'Tickets are managed by GLPI. Please create tickets directly in GLPI.')}\r\n </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-primary inline-flex items-center gap-2\"\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 <div className=\"flex items-center gap-4 mb-8\">\r\n <div className={`flex items-center gap-2 ${step >= 1 ? 'text-[var(--color-primary-600)]' : 'text-[var(--text-secondary)]'}`}>\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center ${\r\n step >= 1 ? 'bg-[var(--color-primary-600)] text-white' : 'bg-[var(--bg-secondary)]'\r\n }`}>\r\n 1\r\n </div>\r\n <span className=\"font-medium\">{t('tickets.create.stepSelectType', 'Select Type')}</span>\r\n </div>\r\n <div className={`flex-1 h-0.5 ${step >= 2 ? 'bg-[var(--color-primary-600)]' : 'bg-[var(--border-color)]'}`} />\r\n <div className={`flex items-center gap-2 ${step >= 2 ? 'text-[var(--color-primary-600)]' : 'text-[var(--text-secondary)]'}`}>\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center ${\r\n step >= 2 ? 'bg-[var(--color-primary-600)] text-white' : 'bg-[var(--bg-secondary)]'\r\n }`}>\r\n 2\r\n </div>\r\n <span className=\"font-medium\">{t('tickets.create.stepDetails', 'Details')}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Tenant context indicator (shown when using locally selected tenant in global view) */}\r\n {selectedTenantForTicket && !currentTenant && (\r\n <div className=\"mb-4 p-3 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--info-text)]\">\r\n <Building2 className=\"w-4 h-4\" />\r\n <span>{t('support:tickets.tenantPicker.creatingFor', 'Creating ticket for:')}</span>\r\n <span className=\"font-semibold\">{selectedTenantForTicket.name}</span>\r\n </div>\r\n <button\r\n onClick={() => setShowTenantPicker(true)}\r\n className=\"text-xs text-[var(--info-text)] underline hover:no-underline\"\r\n >\r\n {t('common:actions.change', 'Change')}\r\n </button>\r\n </div>\r\n )}\r\n\r\n <div className=\"card p-6\">\r\n {step === 1 && renderTypeSelection()}\r\n {step === 2 && renderForm()}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* Discard confirmation modal */}\r\n {showDiscardConfirm && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4\">\r\n <div className=\"card w-full max-w-md p-6\">\r\n <div className=\"flex items-center gap-3 mb-4\">\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--error-bg)] flex items-center justify-center\">\r\n <Trash2 className=\"w-5 h-5 text-[var(--error-text)]\" />\r\n </div>\r\n <h2 className=\"text-xl font-bold\">{t('common:drafts.discardConfirmTitle', 'Discard draft?')}</h2>\r\n </div>\r\n <p className=\"text-[var(--text-secondary)] mb-6\">{t('common:drafts.discardConfirmMessage', 'This draft will be permanently deleted. This action cannot be undone.')}</p>\r\n <div className=\"flex justify-end gap-3\">\r\n <button onClick={() => setShowDiscardConfirm(false)} className=\"btn btn-secondary\">\r\n {t('common:actions.cancel', 'Cancel')}\r\n </button>\r\n <button onClick={handleDiscardDraft} className=\"btn bg-[var(--error-text)] text-white hover:opacity-90\">\r\n {t('common:drafts.discard', 'Discard')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Tenant picker modal (shown in global view when no tenant selected) */}\r\n {showTenantPicker && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4\">\r\n <div className=\"card w-full max-w-md p-6\">\r\n <div className=\"flex items-center gap-3 mb-4\">\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--info-bg)] flex items-center justify-center\">\r\n <Building2 className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <h2 className=\"text-xl font-bold\">{t('support:tickets.tenantPicker.title', 'Select Workspace')}</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">{t('support:tickets.tenantPicker.description', 'Choose a workspace to create the ticket in')}</p>\r\n </div>\r\n </div>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {userTenants\r\n .filter(tenant => tenant.status === 'Active')\r\n .map(tenant => (\r\n <button\r\n key={tenant.id}\r\n onClick={() => {\r\n setSelectedTenantForTicket(tenant);\r\n setShowTenantPicker(false);\r\n // Immediately persist tenant to draft\r\n const id = currentDraftId || ensureDraft();\r\n if (id) {\r\n ticketDraftService.updateDraft(id, {\r\n tenantId: tenant.id,\r\n tenantSlug: tenant.slug,\r\n tenantName: tenant.name,\r\n });\r\n }\r\n }}\r\n className={`w-full p-3 rounded-lg border text-left transition-colors hover:bg-[var(--bg-hover)] ${\r\n selectedTenantForTicket?.id === tenant.id\r\n ? 'border-[var(--color-primary-600)] bg-[var(--color-primary-600)]/10'\r\n : 'border-[var(--border-color)]'\r\n }`}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n <Building2 className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"font-medium truncate\">{tenant.name}</div>\r\n {tenant.organisationName && (\r\n <div className=\"text-xs text-[var(--text-secondary)] truncate\">{tenant.organisationName}</div>\r\n )}\r\n </div>\r\n <span className={`text-xs px-2 py-0.5 rounded-full ${\r\n tenant.type === 'Personal'\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)]'\r\n : 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n }`}>\r\n {tenant.type === 'Personal' ? t('common:tenant.personal', 'Personal') : t('common:tenant.business', 'Business')}\r\n </span>\r\n </div>\r\n </button>\r\n ))}\r\n </div>\r\n <div className=\"flex justify-end gap-3 mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => {\r\n setShowTenantPicker(false);\r\n if (!effectiveTenant) navigate(-1);\r\n }}\r\n className=\"btn btn-secondary\"\r\n >\r\n {t('common:actions.cancel', 'Cancel')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ticketTypes","Bug","Lightbulb","AppWindow","MessageSquare","HelpCircle","priorityOptions","MAX_FILE_SIZE","MAX_ATTACHMENTS","ALLOWED_EXTENSIONS","formatFileSize","bytes","getFileIcon","type","FileText","ImageIcon","FileIcon","restoreDraft","draftId","userTenants","draft","ticketDraftService","selectedTenant","matchingTenant","t","restoreSessionContext","sessionContext","autoSelectType","uploadScreenshot","ticketId","screenshot","selectedTenantForTicket","blob","file","formData","tenantHeaders","api","myTicketsApi","uploadAttachments","attachments","attachment","UserCreateTicketPage","navigate","useNavigate","searchParams","useSearchParams","useTranslation","isGlpi","glpiBaseUrl","useTicketingProvider","currentTenant","isGlobalView","useTenant","screenshotInputRef","useRef","attachmentInputRef","setSelectedTenantForTicket","useState","showTenantPicker","setShowTenantPicker","effectiveTenant","useEffect","step","setStep","selectedType","setSelectedType","title","setTitle","description","setDescription","priority","setPriority","submitting","setSubmitting","error","setError","browserInfo","setBrowserInfo","includeBrowserInfo","setIncludeBrowserInfo","setScreenshot","annotatedScreenshot","setAnnotatedScreenshot","isDraggingScreenshot","setIsDraggingScreenshot","setAttachments","isDraggingAttachment","setIsDraggingAttachment","currentDraftId","setCurrentDraftId","showDraftSaved","setShowDraftSaved","showDiscardConfirm","setShowDiscardConfirm","autoSaveTimerRef","isInitialLoadCompleteRef","hasUnsavedChangesRef","saveDraftNow","useCallback","result","ensureDraft","newDraft","handleBeforeUnload","handleDiscardDraft","validTypes","prefillType","prefillSubject","prefillBody","errorContextService","sessionScreenshot","info","browserInfoService","processImageFile","reader","e","dataUrl","handleScreenshotUpload","event","handleScreenshotDragOver","handleScreenshotDragLeave","handleScreenshotDrop","files","handleRemoveScreenshot","handleAnnotatedScreenshot","isAllowedFileType","extension","processAttachmentFiles","newAttachments","i","a","generateUUID","prev","handleAttachmentUpload","handleAttachmentDragOver","handleAttachmentDragLeave","handleAttachmentDrop","handleRemoveAttachment","id","handleSubmit","fullDescription","currentBrowserInfo","recentErrors","logService","clientContext","ticket","err","serverMessage","renderTypeSelection","jsxs","jsx","renderForm","ArrowLeft","tt","option","X","ScreenshotAnnotator","Upload","Paperclip","AttachmentIcon","Monitor","AlertTriangle","Loader2","Send","Headset","Check","Trash2","Info","ExternalLink","Fragment","Building2","tenant"],"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"),u=require("react"),W=require("react-router-dom"),h=require("react-i18next"),c=require("lucide-react"),v=require("./index-cAikSVW0.js"),i=require("recharts");function G(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const o in t)if(o!=="default"){const n=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(r,o,n.get?n:{enumerable:!0,get:()=>t[o]})}}return r.default=t,Object.freeze(r)}const H=G(c);function Y({data:t}){const{t:r}=h.useTranslation("navigation");if(!t||t.length===0)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.sessionAnalytics.noData")});const o=t.map(n=>({date:new Date(n.date).toLocaleDateString("fr-FR",{day:"2-digit",month:"2-digit"}),loginCount:n.loginCount,avgDuration:Math.round(n.avgDuration)}));return e.jsx(i.ResponsiveContainer,{width:"100%",height:300,children:e.jsxs(i.LineChart,{data:o,margin:{top:5,right:30,left:20,bottom:5},children:[e.jsx(i.CartesianGrid,{strokeDasharray:"3 3",stroke:"var(--border-color)"}),e.jsx(i.XAxis,{dataKey:"date",stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12}}),e.jsx(i.YAxis,{yAxisId:"left",stroke:"var(--color-accent-500)",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.sessionAnalytics.connections"),angle:-90,position:"insideLeft",fill:"var(--text-secondary)"}}),e.jsx(i.YAxis,{yAxisId:"right",orientation:"right",stroke:"#22c55e",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.sessionAnalytics.avgDuration"),angle:90,position:"insideRight",fill:"var(--text-secondary)"}}),e.jsx(i.Tooltip,{contentStyle:{backgroundColor:"var(--bg-card)",border:"1px solid var(--border-color)",borderRadius:"var(--radius-card)",color:"var(--text-primary)"},formatter:(n,a)=>a==="loginCount"?[n,r("dashboard.sessionAnalytics.connections")]:a==="avgDuration"?[`${n} min`,r("dashboard.sessionAnalytics.avgDuration")]:[n,a||""]}),e.jsx(i.Legend,{wrapperStyle:{color:"var(--text-secondary)"},formatter:n=>n==="loginCount"?r("dashboard.sessionAnalytics.connections"):n==="avgDuration"?r("dashboard.sessionAnalytics.avgDurationMin"):n}),e.jsx(i.Line,{yAxisId:"left",type:"monotone",dataKey:"loginCount",stroke:"var(--color-accent-500)",strokeWidth:2,dot:{fill:"var(--color-accent-500)",r:4},activeDot:{r:6}}),e.jsx(i.Line,{yAxisId:"right",type:"monotone",dataKey:"avgDuration",stroke:"#22c55e",strokeWidth:2,dot:{fill:"#22c55e",r:4},activeDot:{r:6}})]})})}function _({errors:t}){const{t:r}=h.useTranslation("navigation");if(!Array.isArray(t)||t.length===0)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-8 text-[var(--text-secondary)]",children:[e.jsx(c.AlertTriangle,{className:"w-12 h-12 mb-3 text-green-500"}),e.jsx("p",{className:"font-medium",children:r("dashboard.loginErrors.noErrors")}),e.jsx("p",{className:"text-sm mt-1",children:r("dashboard.loginErrors.accountSecure")})]});const o=n=>{const a=new Date(n);return(new Date().getTime()-a.getTime())/(1e3*60*60)<24};return 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 text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.datetime")}),e.jsx("th",{className:"text-left p-3 font-medium text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.reason")}),e.jsx("th",{className:"text-left p-3 font-medium text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.ipAddress")}),e.jsx("th",{className:"text-left p-3 font-medium text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.location")})]})}),e.jsx("tbody",{children:t.map(n=>{const a=o(n.loginAt);return e.jsxs("tr",{className:`border-b border-[var(--border-color)] hover:bg-[var(--bg-secondary)] ${a?"bg-red-50/50 dark:bg-red-900/10":""}`,children:[e.jsx("td",{className:"p-3",children:e.jsxs("div",{className:"flex items-center gap-2",children:[a&&e.jsx("span",{className:"w-2 h-2 rounded-full bg-red-500 animate-pulse",title:r("dashboard.loginErrors.recentLabel")}),e.jsx("span",{className:"text-sm",children:new Date(n.loginAt).toLocaleDateString("fr-FR",{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit"})})]})}),e.jsx("td",{className:"p-3",children:e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400",style:{borderRadius:"var(--radius-badge)"},children:[e.jsx(c.AlertTriangle,{className:"w-3 h-3"}),n.failureReason]})}),e.jsx("td",{className:"p-3",children:e.jsx("span",{className:"text-sm font-mono text-[var(--text-secondary)]",children:n.ipAddress||"N/A"})}),e.jsx("td",{className:"p-3",children:n.city||n.country?e.jsxs("div",{className:"flex items-center gap-1 text-sm text-[var(--text-secondary)]",children:[n.city&&e.jsxs(e.Fragment,{children:[e.jsx(c.MapPin,{className:"w-3 h-3"}),e.jsx("span",{children:n.city})]}),n.country&&e.jsxs(e.Fragment,{children:[e.jsx(c.Globe,{className:"w-3 h-3"}),e.jsx("span",{children:n.country})]})]}):e.jsx("span",{className:"text-sm text-[var(--text-tertiary)]",children:r("dashboard.loginErrors.notAvailable")})})]},n.loginAt)})})]})})}function X({session:t}){const{t:r}=h.useTranslation("navigation");if(!t)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-8 text-[var(--text-secondary)]",children:[e.jsx(c.Monitor,{className:"w-12 h-12 mb-3 opacity-50"}),e.jsx("p",{className:"font-medium",children:r("dashboard.currentSession.noActiveSession")}),e.jsx("p",{className:"text-sm mt-1",children:r("dashboard.currentSession.pleaseReconnect")})]});const o=a=>{if(a<1)return"< 1 minute";if(a<60)return`${Math.round(a)} minutes`;const s=Math.floor(a/60),d=Math.round(a%60);return d===0?`${s}h`:`${s}h ${d}min`},n=a=>a?a.includes("Edg/")?r("dashboard.browsers.edge"):a.includes("Chrome/")?r("dashboard.browsers.chrome"):a.includes("Firefox/")?r("dashboard.browsers.firefox"):a.includes("Safari/")&&!a.includes("Chrome")?r("dashboard.browsers.safari"):a.includes("OPR/")||a.includes("Opera/")?r("dashboard.browsers.opera"):r("dashboard.browsers.other"):r("dashboard.browsers.unknown");return e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"flex items-start gap-3 p-4 bg-[var(--bg-secondary)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"p-2 bg-[var(--accent-bg)] text-[var(--color-accent-500)]",style:{borderRadius:"var(--radius-button)"},children:e.jsx(c.Clock,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] uppercase tracking-wide",children:r("dashboard.currentSession.duration")}),e.jsx("p",{className:"text-lg font-bold text-[var(--text-primary)] mt-1",children:o(t.durationMinutes)}),e.jsxs("p",{className:"text-xs text-[var(--text-secondary)] mt-1",children:[r("dashboard.currentSession.since")," ",new Date(t.loginAt).toLocaleTimeString("fr-FR",{hour:"2-digit",minute:"2-digit"})]})]})]}),e.jsxs("div",{className:"flex items-start gap-3 p-4 bg-[var(--bg-secondary)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"p-2 bg-blue-500/10 text-blue-500",style:{borderRadius:"var(--radius-button)"},children:e.jsx(c.Monitor,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] uppercase tracking-wide",children:r("dashboard.currentSession.device")}),e.jsx("p",{className:"text-lg font-bold text-[var(--text-primary)] mt-1",children:n(t.userAgent)}),e.jsx("p",{className:"text-xs text-[var(--text-secondary)] mt-1 font-mono",children:t.ipAddress||r("dashboard.currentSession.ipNotAvailable")})]})]}),(t.city||t.country)&&e.jsxs("div",{className:"md:col-span-2 flex items-start gap-3 p-4 bg-[var(--bg-secondary)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"p-2 bg-green-500/10 text-green-500",style:{borderRadius:"var(--radius-button)"},children:e.jsx(c.Globe,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] uppercase tracking-wide",children:r("dashboard.currentSession.location")}),e.jsxs("div",{className:"flex items-center gap-3 mt-1",children:[t.city&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(c.MapPin,{className:"w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)]",children:t.city})]}),t.country&&e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:t.country})]})]})]})]})}function J({stats:t}){const{t:r}=h.useTranslation("navigation");if(!t)return e.jsx("div",{className:"flex items-center justify-center py-8 text-[var(--text-secondary)]",children:e.jsx("p",{children:r("dashboard.deviceStats.noData")})});const o=["#3b82f6","#8b5cf6","#22c55e","#f59e0b","#ef4444"],n=["#06b6d4","#ec4899","#10b981","#f97316","#6366f1"];return e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3 flex items-center gap-2",children:[e.jsx(c.Monitor,{className:"w-4 h-4"}),r("dashboard.deviceStats.browsersUsed")]}),t.byBrowser?.length?e.jsx("div",{className:"space-y-3",children:t.byBrowser.map((a,s)=>{const d=Math.max(...t.byBrowser.map(m=>m.count),1),x=a.count/d*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm text-[var(--text-primary)] truncate",title:a.browser,children:a.browser}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${x}%`,backgroundColor:o[s%o.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium text-[var(--text-primary)]",children:a.count})]},a.browser)})}):e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:r("dashboard.deviceStats.noData")})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3 flex items-center gap-2",children:[e.jsx(c.Globe,{className:"w-4 h-4"}),r("dashboard.deviceStats.connectionCountries")]}),t.byCountry?.length?e.jsx("div",{className:"space-y-3",children:t.byCountry.map((a,s)=>{const d=Math.max(...t.byCountry.map(m=>m.count),1),x=a.count/d*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm text-[var(--text-primary)] truncate",title:a.country,children:a.country}),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:`${x}%`,backgroundColor:n[s%n.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium text-[var(--text-primary)]",children:a.count})]},a.country)})}):e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:r("dashboard.deviceStats.locationNotAvailable")})]})]})}function Q({data:t}){const{t:r}=h.useTranslation("navigation");if(!t?.dayStats?.length)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.weeklyUsage.noData")});const o=t.dayStats.map(s=>({day:r(`dashboard.days.${s.dayName.toLowerCase()}`),duration:s.sessionCount>0?Math.round(s.totalDuration/s.sessionCount):0,sessionCount:s.sessionCount})),n=o.filter(s=>s.sessionCount>0).length>0?o.filter(s=>s.sessionCount>0).reduce((s,d)=>s+d.duration,0)/o.filter(s=>s.sessionCount>0).length:0,a=s=>{if(s<60)return`${s} min`;const d=Math.floor(s/60),x=s%60;return x>0?`${d}h ${x}m`:`${d}h`};return e.jsx(i.ResponsiveContainer,{width:"100%",height:300,children:e.jsxs(i.BarChart,{data:o,margin:{top:20,right:30,left:20,bottom:5},children:[e.jsx(i.CartesianGrid,{strokeDasharray:"3 3",stroke:"var(--border-color)"}),e.jsx(i.XAxis,{dataKey:"day",stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12}}),e.jsx(i.YAxis,{stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.weeklyUsage.duration"),angle:-90,position:"insideLeft",fill:"var(--text-secondary)"}}),e.jsx(i.Tooltip,{cursor:{fill:"transparent"},contentStyle:{backgroundColor:"var(--bg-tertiary)",border:"none",borderRadius:"var(--radius-card)",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"8px 12px"},formatter:s=>[a(s),null],labelStyle:{color:"var(--text-primary)",fontWeight:600,marginBottom:4},itemStyle:{color:"var(--text-secondary)",padding:0},separator:""}),e.jsx(i.ReferenceLine,{y:n,stroke:"#f59e0b",strokeDasharray:"5 5",label:{value:`${r("dashboard.weeklyUsage.average")}: ${a(Math.round(n))}`,position:"right",fill:"#f59e0b",fontSize:11}}),e.jsx(i.Bar,{dataKey:"duration",fill:"var(--color-accent-500)",radius:[4,4,0,0]})]})})}function V({data:t}){const{t:r}=h.useTranslation("navigation");if(!t?.hourStats?.length)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.hourlyUsage.noData")});const o=s=>`${s.toString().padStart(2,"0")}:00`,n=s=>{if(s<60)return`${s} min`;const d=Math.floor(s/60),x=s%60;return x>0?`${d}h ${x}m`:`${d}h`},a=t.hourStats.map(s=>({hour:o(s.hour),hourNum:s.hour,duration:s.sessionCount>0?Math.round(s.totalDuration/s.sessionCount):0,sessionCount:s.sessionCount,isPeak:s.hour===t.peakHour}));return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-end mb-2 text-xs text-[var(--text-secondary)]",children:[e.jsx("span",{className:"inline-block w-3 h-3 rounded-sm bg-[var(--color-accent-600)] mr-1"}),r("dashboard.hourlyUsage.peakHour"),": ",o(t.peakHour)]}),e.jsx(i.ResponsiveContainer,{width:"100%",height:300,children:e.jsxs(i.BarChart,{data:a,margin:{top:10,right:30,left:20,bottom:5},children:[e.jsx(i.CartesianGrid,{strokeDasharray:"3 3",stroke:"var(--border-color)"}),e.jsx(i.XAxis,{dataKey:"hour",stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:11},interval:0,angle:-45,textAnchor:"end",height:60}),e.jsx(i.YAxis,{stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.hourlyUsage.duration"),angle:-90,position:"insideLeft",fill:"var(--text-secondary)"}}),e.jsx(i.Tooltip,{cursor:{fill:"transparent"},contentStyle:{backgroundColor:"var(--bg-tertiary)",border:"none",borderRadius:"var(--radius-card)",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"8px 12px"},formatter:s=>[n(s),null],labelStyle:{color:"var(--text-primary)",fontWeight:600,marginBottom:4},itemStyle:{color:"var(--text-secondary)",padding:0},separator:""}),e.jsx(i.Bar,{dataKey:"duration",radius:[4,4,0,0],children:a.map((s,d)=>e.jsx(i.Cell,{fill:s.isPeak?"var(--color-accent-600)":"var(--color-accent-400)"},`${s.hour}-${d}`))})]})})]})}const f=["#3b82f6","#22c55e","#f59e0b","#ef4444","#8b5cf6","#06b6d4","#ec4899","#84cc16","#f97316","#6366f1"];function Z({data:t}){const{t:r}=h.useTranslation("navigation");if(!t?.applications?.length)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.applicationUsage.noData")});const o=t.applications.map(a=>({name:a.applicationName,value:a.accessCount,duration:a.totalDurationSeconds,percentage:a.percentage})),n=a=>a<60?`${a}s`:a<3600?`${Math.round(a/60)}m`:`${Math.round(a/3600)}h`;return e.jsxs("div",{className:"flex flex-col md:flex-row items-center gap-6",children:[e.jsx("div",{className:"w-full md:w-1/2",children:e.jsx(i.ResponsiveContainer,{width:"100%",height:280,children:e.jsxs(i.PieChart,{children:[e.jsx(i.Pie,{data:o,cx:"50%",cy:"50%",innerRadius:60,outerRadius:90,dataKey:"value",label:({name:a,percent:s})=>`${a} (${((s??0)*100).toFixed(0)}%)`,labelLine:!1,children:o.map((a,s)=>e.jsx(i.Cell,{fill:f[s%f.length]},`${a.name}-${s}`))}),e.jsx(i.Tooltip,{contentStyle:{backgroundColor:"var(--bg-tertiary)",border:"none",borderRadius:"var(--radius-card)",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"8px 12px"},formatter:(a,s,d)=>[`${a} ${r("dashboard.applicationUsage.accesses")} (${n(d.payload.duration)})`,null],labelStyle:{color:"var(--text-primary)",fontWeight:600,marginBottom:4},itemStyle:{color:"var(--text-secondary)",padding:0},separator:""})]})})}),e.jsxs("div",{className:"w-full md:w-1/2",children:[e.jsxs("div",{className:"text-sm text-[var(--text-secondary)] mb-3",children:[r("dashboard.applicationUsage.totalAccess"),": ",e.jsx("span",{className:"font-semibold text-[var(--text-primary)]",children:t.totalAccess})]}),e.jsx("div",{className:"space-y-2 max-h-[240px] overflow-y-auto",children:t.applications.map((a,s)=>e.jsxs("div",{className:"flex items-center gap-3 p-2 rounded-[var(--radius-card)] hover:bg-[var(--bg-hover)] transition-colors",children:[e.jsx("div",{className:"w-3 h-3 rounded-sm flex-shrink-0",style:{backgroundColor:f[s%f.length]}}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-sm font-medium text-[var(--text-primary)] truncate",children:a.applicationName}),e.jsxs("div",{className:"text-xs text-[var(--text-secondary)]",children:[a.accessCount," ",r("dashboard.applicationUsage.accesses")," - ",n(a.totalDurationSeconds)]})]}),e.jsxs("div",{className:"text-sm font-semibold text-[var(--text-primary)]",children:[a.percentage,"%"]})]},a.applicationId))})]})]})}function ee({name:t,className:r}){const n=H[t];return n?e.jsx(n,{className:r}):e.jsx(c.Star,{className:r})}function te(){const{t}=h.useTranslation(["navigation","common"]),r=W.useNavigate(),{user:o}=v.useAuth(),{currentTenant:n}=v.useTenant(),{menu:a}=v.useNavigation(),{favorites:s,loading:d,triggerExpand:x}=v.useFavorites(),[m,T]=u.useState(30),[U,N]=u.useState(!0),[y,w]=u.useState(null),[p,S]=u.useState([]),[L,C]=u.useState(null),[E,k]=u.useState(null),[B,D]=u.useState(null),[P,A]=u.useState(null),[O,R]=u.useState(null),F=l=>{if(a)for(const b of a.applications){const M=b.modules.find(g=>g.id===l.id);if(M?.sections?.length){const g=[...M.sections].sort((q,K)=>q.displayOrder-K.displayOrder)[0];if(g.route)return g.route}}return l.route},I=l=>{const b=F(l);b&&(x(),r(b))},z=o?.firstName&&o?.lastName?`${o.firstName} ${o.lastName}`:o?.email||"Utilisateur",$=u.useCallback(async()=>{try{N(!0);const l=await v.userApi.dashboard.getAll(m,10);w(l.sessionAnalytics),S(l.loginErrors??[]),C(l.currentSession),k(l.deviceStats),D(l.weeklyStats),A(l.hourlyStats),R(l.applicationUsage)}catch{w(null),S([]),C(null),k(null),D(null),A(null),R(null)}finally{N(!1)}},[m]);return u.useEffect(()=>{$()},[m,$]),U?e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(c.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-500)]"})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:[t("navigation:dashboard.welcome"),", ",z]}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:t("navigation:breadcrumb.myspace")})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(c.Star,{className:"w-5 h-5 text-[var(--color-accent-500)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("common:favorites.quickAccess")}),n&&e.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-[var(--text-tertiary)] px-2 py-1 bg-[var(--bg-secondary)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-button)"},children:[e.jsx(c.Building2,{className:"w-3.5 h-3.5"}),n.name]})]}),e.jsxs("button",{onClick:()=>r("/myspace/preferences?tab=favorites"),className:"flex items-center gap-1.5 px-3 py-1.5 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors",style:{borderRadius:"var(--radius-button)"},children:[e.jsx(c.Settings,{className:"w-4 h-4"}),t("common:favorites.manage")]})]}),d&&e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(c.Loader2,{className:"w-6 h-6 animate-spin text-[var(--color-accent-500)]"})}),!d&&s.length===0&&e.jsxs("div",{className:"text-center py-8",children:[e.jsx(c.Star,{className:"w-12 h-12 mx-auto text-[var(--text-muted)] mb-3"}),e.jsx("p",{className:"text-[var(--text-secondary)] mb-4",children:t("common:favorites.noFavorites")}),e.jsx("button",{onClick:()=>r("/myspace/preferences?tab=favorites"),className:"px-4 py-2 bg-[var(--color-accent-600)] text-white font-medium hover:bg-[var(--color-accent-700)] transition-colors",style:{borderRadius:"var(--radius-button)"},children:t("common:favorites.configureFavorites")})]}),!d&&s.length>0&&e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3",children:s.map(l=>e.jsxs("button",{onClick:()=>I(l),className:"flex flex-col items-center gap-2 p-4 bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-all group",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"w-12 h-12 flex items-center justify-center bg-[var(--color-accent-100)] text-[var(--color-accent-600)] group-hover:bg-[var(--color-accent-600)] group-hover:text-white transition-colors",style:{borderRadius:"var(--radius-button)"},children:e.jsx(ee,{name:l.icon,className:"w-6 h-6"})}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)] text-center",children:l.label}),e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:l.applicationLabel})]},l.id))})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[e.jsx(j,{title:t("navigation:dashboard.stats.totalSessions"),value:y?.totalSessions??0,icon:e.jsx(c.Activity,{className:"w-5 h-5"}),subtitle:`${m} ${t("navigation:dashboard.stats.lastDays")}`}),e.jsx(j,{title:t("navigation:dashboard.stats.avgDuration"),value:`${Math.round(y?.avgSessionDuration??0)} min`,icon:e.jsx(c.TrendingUp,{className:"w-5 h-5"}),subtitle:t("navigation:dashboard.stats.perSession")}),e.jsx(j,{title:t("navigation:dashboard.stats.connectionErrors"),value:(p??[]).length,icon:e.jsx(c.AlertTriangle,{className:"w-5 h-5"}),subtitle:t("navigation:dashboard.stats.recent"),color:(p??[]).length>0?"red":"green"})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.Calendar,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.weeklyUsage.title")})]}),e.jsx(Q,{data:B})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.Clock,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.hourlyUsage.title")})]}),e.jsx(V,{data:P})]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.AppWindow,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.applicationUsage.title")})]}),e.jsx(Z,{data:O})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(c.BarChart3,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.sessionAnalytics.title")})]}),e.jsx("div",{className:"flex gap-2",children:[7,30,90].map(l=>e.jsx("button",{onClick:()=>T(l),className:`px-3 py-1 text-sm font-medium transition-colors ${m===l?"bg-[var(--color-accent-500)] text-white":"bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)]"}`,style:{borderRadius:"var(--radius-button)"},children:t(`navigation:dashboard.sessionAnalytics.period.${l}days`)},l))})]}),e.jsx(Y,{data:y?.dailyStats??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.Monitor,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.currentSession.title")})]}),e.jsx(X,{session:L})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.AlertTriangle,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.loginErrors.title")})]}),e.jsx(_,{errors:p??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.BarChart3,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.deviceStats.title")})]}),e.jsx(J,{stats:E})]})]})}function j({title:t,value:r,icon:o,subtitle:n,color:a="blue"}){const s={blue:"bg-blue-50 text-blue-600 border-blue-200 dark:bg-blue-900/20 dark:border-blue-800",green:"bg-green-50 text-green-600 border-green-200 dark:bg-green-900/20 dark:border-green-800",red:"bg-red-50 text-red-600 border-red-200 dark:bg-red-900/20 dark:border-red-800"};return e.jsxs("div",{className:`p-4 border ${s[a]}`,style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium opacity-80",children:t}),o]}),e.jsx("div",{className:"text-2xl font-bold",children:r}),n&&e.jsx("div",{className:"text-xs opacity-70 mt-1",children:n})]})}exports.UserDashboardPage=te;
|
|
2
|
-
//# sourceMappingURL=UserDashboardPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),u=require("react"),W=require("react-router-dom"),h=require("react-i18next"),c=require("lucide-react"),v=require("./index-DK5czlkn.js"),i=require("recharts");function G(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const o in t)if(o!=="default"){const n=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(r,o,n.get?n:{enumerable:!0,get:()=>t[o]})}}return r.default=t,Object.freeze(r)}const H=G(c);function Y({data:t}){const{t:r}=h.useTranslation("navigation");if(!t||t.length===0)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.sessionAnalytics.noData")});const o=t.map(n=>({date:new Date(n.date).toLocaleDateString("fr-FR",{day:"2-digit",month:"2-digit"}),loginCount:n.loginCount,avgDuration:Math.round(n.avgDuration)}));return e.jsx(i.ResponsiveContainer,{width:"100%",height:300,children:e.jsxs(i.LineChart,{data:o,margin:{top:5,right:30,left:20,bottom:5},children:[e.jsx(i.CartesianGrid,{strokeDasharray:"3 3",stroke:"var(--border-color)"}),e.jsx(i.XAxis,{dataKey:"date",stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12}}),e.jsx(i.YAxis,{yAxisId:"left",stroke:"var(--color-accent-500)",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.sessionAnalytics.connections"),angle:-90,position:"insideLeft",fill:"var(--text-secondary)"}}),e.jsx(i.YAxis,{yAxisId:"right",orientation:"right",stroke:"#22c55e",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.sessionAnalytics.avgDuration"),angle:90,position:"insideRight",fill:"var(--text-secondary)"}}),e.jsx(i.Tooltip,{contentStyle:{backgroundColor:"var(--bg-card)",border:"1px solid var(--border-color)",borderRadius:"var(--radius-card)",color:"var(--text-primary)"},formatter:(n,a)=>a==="loginCount"?[n,r("dashboard.sessionAnalytics.connections")]:a==="avgDuration"?[`${n} min`,r("dashboard.sessionAnalytics.avgDuration")]:[n,a||""]}),e.jsx(i.Legend,{wrapperStyle:{color:"var(--text-secondary)"},formatter:n=>n==="loginCount"?r("dashboard.sessionAnalytics.connections"):n==="avgDuration"?r("dashboard.sessionAnalytics.avgDurationMin"):n}),e.jsx(i.Line,{yAxisId:"left",type:"monotone",dataKey:"loginCount",stroke:"var(--color-accent-500)",strokeWidth:2,dot:{fill:"var(--color-accent-500)",r:4},activeDot:{r:6}}),e.jsx(i.Line,{yAxisId:"right",type:"monotone",dataKey:"avgDuration",stroke:"#22c55e",strokeWidth:2,dot:{fill:"#22c55e",r:4},activeDot:{r:6}})]})})}function _({errors:t}){const{t:r}=h.useTranslation("navigation");if(!Array.isArray(t)||t.length===0)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-8 text-[var(--text-secondary)]",children:[e.jsx(c.AlertTriangle,{className:"w-12 h-12 mb-3 text-green-500"}),e.jsx("p",{className:"font-medium",children:r("dashboard.loginErrors.noErrors")}),e.jsx("p",{className:"text-sm mt-1",children:r("dashboard.loginErrors.accountSecure")})]});const o=n=>{const a=new Date(n);return(new Date().getTime()-a.getTime())/(1e3*60*60)<24};return 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 text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.datetime")}),e.jsx("th",{className:"text-left p-3 font-medium text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.reason")}),e.jsx("th",{className:"text-left p-3 font-medium text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.ipAddress")}),e.jsx("th",{className:"text-left p-3 font-medium text-[var(--text-secondary)] text-sm",children:r("dashboard.loginErrors.columns.location")})]})}),e.jsx("tbody",{children:t.map(n=>{const a=o(n.loginAt);return e.jsxs("tr",{className:`border-b border-[var(--border-color)] hover:bg-[var(--bg-secondary)] ${a?"bg-red-50/50 dark:bg-red-900/10":""}`,children:[e.jsx("td",{className:"p-3",children:e.jsxs("div",{className:"flex items-center gap-2",children:[a&&e.jsx("span",{className:"w-2 h-2 rounded-full bg-red-500 animate-pulse",title:r("dashboard.loginErrors.recentLabel")}),e.jsx("span",{className:"text-sm",children:new Date(n.loginAt).toLocaleDateString("fr-FR",{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit"})})]})}),e.jsx("td",{className:"p-3",children:e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400",style:{borderRadius:"var(--radius-badge)"},children:[e.jsx(c.AlertTriangle,{className:"w-3 h-3"}),n.failureReason]})}),e.jsx("td",{className:"p-3",children:e.jsx("span",{className:"text-sm font-mono text-[var(--text-secondary)]",children:n.ipAddress||"N/A"})}),e.jsx("td",{className:"p-3",children:n.city||n.country?e.jsxs("div",{className:"flex items-center gap-1 text-sm text-[var(--text-secondary)]",children:[n.city&&e.jsxs(e.Fragment,{children:[e.jsx(c.MapPin,{className:"w-3 h-3"}),e.jsx("span",{children:n.city})]}),n.country&&e.jsxs(e.Fragment,{children:[e.jsx(c.Globe,{className:"w-3 h-3"}),e.jsx("span",{children:n.country})]})]}):e.jsx("span",{className:"text-sm text-[var(--text-tertiary)]",children:r("dashboard.loginErrors.notAvailable")})})]},n.loginAt)})})]})})}function X({session:t}){const{t:r}=h.useTranslation("navigation");if(!t)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-8 text-[var(--text-secondary)]",children:[e.jsx(c.Monitor,{className:"w-12 h-12 mb-3 opacity-50"}),e.jsx("p",{className:"font-medium",children:r("dashboard.currentSession.noActiveSession")}),e.jsx("p",{className:"text-sm mt-1",children:r("dashboard.currentSession.pleaseReconnect")})]});const o=a=>{if(a<1)return"< 1 minute";if(a<60)return`${Math.round(a)} minutes`;const s=Math.floor(a/60),d=Math.round(a%60);return d===0?`${s}h`:`${s}h ${d}min`},n=a=>a?a.includes("Edg/")?r("dashboard.browsers.edge"):a.includes("Chrome/")?r("dashboard.browsers.chrome"):a.includes("Firefox/")?r("dashboard.browsers.firefox"):a.includes("Safari/")&&!a.includes("Chrome")?r("dashboard.browsers.safari"):a.includes("OPR/")||a.includes("Opera/")?r("dashboard.browsers.opera"):r("dashboard.browsers.other"):r("dashboard.browsers.unknown");return e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"flex items-start gap-3 p-4 bg-[var(--bg-secondary)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"p-2 bg-[var(--accent-bg)] text-[var(--color-accent-500)]",style:{borderRadius:"var(--radius-button)"},children:e.jsx(c.Clock,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] uppercase tracking-wide",children:r("dashboard.currentSession.duration")}),e.jsx("p",{className:"text-lg font-bold text-[var(--text-primary)] mt-1",children:o(t.durationMinutes)}),e.jsxs("p",{className:"text-xs text-[var(--text-secondary)] mt-1",children:[r("dashboard.currentSession.since")," ",new Date(t.loginAt).toLocaleTimeString("fr-FR",{hour:"2-digit",minute:"2-digit"})]})]})]}),e.jsxs("div",{className:"flex items-start gap-3 p-4 bg-[var(--bg-secondary)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"p-2 bg-blue-500/10 text-blue-500",style:{borderRadius:"var(--radius-button)"},children:e.jsx(c.Monitor,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] uppercase tracking-wide",children:r("dashboard.currentSession.device")}),e.jsx("p",{className:"text-lg font-bold text-[var(--text-primary)] mt-1",children:n(t.userAgent)}),e.jsx("p",{className:"text-xs text-[var(--text-secondary)] mt-1 font-mono",children:t.ipAddress||r("dashboard.currentSession.ipNotAvailable")})]})]}),(t.city||t.country)&&e.jsxs("div",{className:"md:col-span-2 flex items-start gap-3 p-4 bg-[var(--bg-secondary)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"p-2 bg-green-500/10 text-green-500",style:{borderRadius:"var(--radius-button)"},children:e.jsx(c.Globe,{className:"w-5 h-5"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] uppercase tracking-wide",children:r("dashboard.currentSession.location")}),e.jsxs("div",{className:"flex items-center gap-3 mt-1",children:[t.city&&e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(c.MapPin,{className:"w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)]",children:t.city})]}),t.country&&e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:t.country})]})]})]})]})}function J({stats:t}){const{t:r}=h.useTranslation("navigation");if(!t)return e.jsx("div",{className:"flex items-center justify-center py-8 text-[var(--text-secondary)]",children:e.jsx("p",{children:r("dashboard.deviceStats.noData")})});const o=["#3b82f6","#8b5cf6","#22c55e","#f59e0b","#ef4444"],n=["#06b6d4","#ec4899","#10b981","#f97316","#6366f1"];return e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3 flex items-center gap-2",children:[e.jsx(c.Monitor,{className:"w-4 h-4"}),r("dashboard.deviceStats.browsersUsed")]}),t.byBrowser?.length?e.jsx("div",{className:"space-y-3",children:t.byBrowser.map((a,s)=>{const d=Math.max(...t.byBrowser.map(m=>m.count),1),x=a.count/d*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm text-[var(--text-primary)] truncate",title:a.browser,children:a.browser}),e.jsx("div",{className:"flex-1 h-6 bg-[var(--bg-secondary)] rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${x}%`,backgroundColor:o[s%o.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium text-[var(--text-primary)]",children:a.count})]},a.browser)})}):e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:r("dashboard.deviceStats.noData")})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3 flex items-center gap-2",children:[e.jsx(c.Globe,{className:"w-4 h-4"}),r("dashboard.deviceStats.connectionCountries")]}),t.byCountry?.length?e.jsx("div",{className:"space-y-3",children:t.byCountry.map((a,s)=>{const d=Math.max(...t.byCountry.map(m=>m.count),1),x=a.count/d*100;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-24 text-sm text-[var(--text-primary)] truncate",title:a.country,children:a.country}),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:`${x}%`,backgroundColor:n[s%n.length]}})}),e.jsx("div",{className:"w-12 text-right font-medium text-[var(--text-primary)]",children:a.count})]},a.country)})}):e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:r("dashboard.deviceStats.locationNotAvailable")})]})]})}function Q({data:t}){const{t:r}=h.useTranslation("navigation");if(!t?.dayStats?.length)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.weeklyUsage.noData")});const o=t.dayStats.map(s=>({day:r(`dashboard.days.${s.dayName.toLowerCase()}`),duration:s.sessionCount>0?Math.round(s.totalDuration/s.sessionCount):0,sessionCount:s.sessionCount})),n=o.filter(s=>s.sessionCount>0).length>0?o.filter(s=>s.sessionCount>0).reduce((s,d)=>s+d.duration,0)/o.filter(s=>s.sessionCount>0).length:0,a=s=>{if(s<60)return`${s} min`;const d=Math.floor(s/60),x=s%60;return x>0?`${d}h ${x}m`:`${d}h`};return e.jsx(i.ResponsiveContainer,{width:"100%",height:300,children:e.jsxs(i.BarChart,{data:o,margin:{top:20,right:30,left:20,bottom:5},children:[e.jsx(i.CartesianGrid,{strokeDasharray:"3 3",stroke:"var(--border-color)"}),e.jsx(i.XAxis,{dataKey:"day",stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12}}),e.jsx(i.YAxis,{stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.weeklyUsage.duration"),angle:-90,position:"insideLeft",fill:"var(--text-secondary)"}}),e.jsx(i.Tooltip,{cursor:{fill:"transparent"},contentStyle:{backgroundColor:"var(--bg-tertiary)",border:"none",borderRadius:"var(--radius-card)",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"8px 12px"},formatter:s=>[a(s),null],labelStyle:{color:"var(--text-primary)",fontWeight:600,marginBottom:4},itemStyle:{color:"var(--text-secondary)",padding:0},separator:""}),e.jsx(i.ReferenceLine,{y:n,stroke:"#f59e0b",strokeDasharray:"5 5",label:{value:`${r("dashboard.weeklyUsage.average")}: ${a(Math.round(n))}`,position:"right",fill:"#f59e0b",fontSize:11}}),e.jsx(i.Bar,{dataKey:"duration",fill:"var(--color-accent-500)",radius:[4,4,0,0]})]})})}function V({data:t}){const{t:r}=h.useTranslation("navigation");if(!t?.hourStats?.length)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.hourlyUsage.noData")});const o=s=>`${s.toString().padStart(2,"0")}:00`,n=s=>{if(s<60)return`${s} min`;const d=Math.floor(s/60),x=s%60;return x>0?`${d}h ${x}m`:`${d}h`},a=t.hourStats.map(s=>({hour:o(s.hour),hourNum:s.hour,duration:s.sessionCount>0?Math.round(s.totalDuration/s.sessionCount):0,sessionCount:s.sessionCount,isPeak:s.hour===t.peakHour}));return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-end mb-2 text-xs text-[var(--text-secondary)]",children:[e.jsx("span",{className:"inline-block w-3 h-3 rounded-sm bg-[var(--color-accent-600)] mr-1"}),r("dashboard.hourlyUsage.peakHour"),": ",o(t.peakHour)]}),e.jsx(i.ResponsiveContainer,{width:"100%",height:300,children:e.jsxs(i.BarChart,{data:a,margin:{top:10,right:30,left:20,bottom:5},children:[e.jsx(i.CartesianGrid,{strokeDasharray:"3 3",stroke:"var(--border-color)"}),e.jsx(i.XAxis,{dataKey:"hour",stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:11},interval:0,angle:-45,textAnchor:"end",height:60}),e.jsx(i.YAxis,{stroke:"var(--text-secondary)",tick:{fill:"var(--text-secondary)",fontSize:12},label:{value:r("dashboard.hourlyUsage.duration"),angle:-90,position:"insideLeft",fill:"var(--text-secondary)"}}),e.jsx(i.Tooltip,{cursor:{fill:"transparent"},contentStyle:{backgroundColor:"var(--bg-tertiary)",border:"none",borderRadius:"var(--radius-card)",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"8px 12px"},formatter:s=>[n(s),null],labelStyle:{color:"var(--text-primary)",fontWeight:600,marginBottom:4},itemStyle:{color:"var(--text-secondary)",padding:0},separator:""}),e.jsx(i.Bar,{dataKey:"duration",radius:[4,4,0,0],children:a.map((s,d)=>e.jsx(i.Cell,{fill:s.isPeak?"var(--color-accent-600)":"var(--color-accent-400)"},`${s.hour}-${d}`))})]})})]})}const f=["#3b82f6","#22c55e","#f59e0b","#ef4444","#8b5cf6","#06b6d4","#ec4899","#84cc16","#f97316","#6366f1"];function Z({data:t}){const{t:r}=h.useTranslation("navigation");if(!t?.applications?.length)return e.jsx("div",{className:"flex items-center justify-center h-64 text-[var(--text-secondary)]",children:r("dashboard.applicationUsage.noData")});const o=t.applications.map(a=>({name:a.applicationName,value:a.accessCount,duration:a.totalDurationSeconds,percentage:a.percentage})),n=a=>a<60?`${a}s`:a<3600?`${Math.round(a/60)}m`:`${Math.round(a/3600)}h`;return e.jsxs("div",{className:"flex flex-col md:flex-row items-center gap-6",children:[e.jsx("div",{className:"w-full md:w-1/2",children:e.jsx(i.ResponsiveContainer,{width:"100%",height:280,children:e.jsxs(i.PieChart,{children:[e.jsx(i.Pie,{data:o,cx:"50%",cy:"50%",innerRadius:60,outerRadius:90,dataKey:"value",label:({name:a,percent:s})=>`${a} (${((s??0)*100).toFixed(0)}%)`,labelLine:!1,children:o.map((a,s)=>e.jsx(i.Cell,{fill:f[s%f.length]},`${a.name}-${s}`))}),e.jsx(i.Tooltip,{contentStyle:{backgroundColor:"var(--bg-tertiary)",border:"none",borderRadius:"var(--radius-card)",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"8px 12px"},formatter:(a,s,d)=>[`${a} ${r("dashboard.applicationUsage.accesses")} (${n(d.payload.duration)})`,null],labelStyle:{color:"var(--text-primary)",fontWeight:600,marginBottom:4},itemStyle:{color:"var(--text-secondary)",padding:0},separator:""})]})})}),e.jsxs("div",{className:"w-full md:w-1/2",children:[e.jsxs("div",{className:"text-sm text-[var(--text-secondary)] mb-3",children:[r("dashboard.applicationUsage.totalAccess"),": ",e.jsx("span",{className:"font-semibold text-[var(--text-primary)]",children:t.totalAccess})]}),e.jsx("div",{className:"space-y-2 max-h-[240px] overflow-y-auto",children:t.applications.map((a,s)=>e.jsxs("div",{className:"flex items-center gap-3 p-2 rounded-[var(--radius-card)] hover:bg-[var(--bg-hover)] transition-colors",children:[e.jsx("div",{className:"w-3 h-3 rounded-sm flex-shrink-0",style:{backgroundColor:f[s%f.length]}}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-sm font-medium text-[var(--text-primary)] truncate",children:a.applicationName}),e.jsxs("div",{className:"text-xs text-[var(--text-secondary)]",children:[a.accessCount," ",r("dashboard.applicationUsage.accesses")," - ",n(a.totalDurationSeconds)]})]}),e.jsxs("div",{className:"text-sm font-semibold text-[var(--text-primary)]",children:[a.percentage,"%"]})]},a.applicationId))})]})]})}function ee({name:t,className:r}){const n=H[t];return n?e.jsx(n,{className:r}):e.jsx(c.Star,{className:r})}function te(){const{t}=h.useTranslation(["navigation","common"]),r=W.useNavigate(),{user:o}=v.useAuth(),{currentTenant:n}=v.useTenant(),{menu:a}=v.useNavigation(),{favorites:s,loading:d,triggerExpand:x}=v.useFavorites(),[m,T]=u.useState(30),[U,N]=u.useState(!0),[y,w]=u.useState(null),[p,S]=u.useState([]),[L,C]=u.useState(null),[E,k]=u.useState(null),[B,D]=u.useState(null),[P,A]=u.useState(null),[O,R]=u.useState(null),F=l=>{if(a)for(const b of a.applications){const M=b.modules.find(g=>g.id===l.id);if(M?.sections?.length){const g=[...M.sections].sort((q,K)=>q.displayOrder-K.displayOrder)[0];if(g.route)return g.route}}return l.route},I=l=>{const b=F(l);b&&(x(),r(b))},z=o?.firstName&&o?.lastName?`${o.firstName} ${o.lastName}`:o?.email||"Utilisateur",$=u.useCallback(async()=>{try{N(!0);const l=await v.userApi.dashboard.getAll(m,10);w(l.sessionAnalytics),S(l.loginErrors??[]),C(l.currentSession),k(l.deviceStats),D(l.weeklyStats),A(l.hourlyStats),R(l.applicationUsage)}catch{w(null),S([]),C(null),k(null),D(null),A(null),R(null)}finally{N(!1)}},[m]);return u.useEffect(()=>{$()},[m,$]),U?e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(c.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-500)]"})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:[t("navigation:dashboard.welcome"),", ",z]}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:t("navigation:breadcrumb.myspace")})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(c.Star,{className:"w-5 h-5 text-[var(--color-accent-500)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("common:favorites.quickAccess")}),n&&e.jsxs("span",{className:"flex items-center gap-1.5 text-xs text-[var(--text-tertiary)] px-2 py-1 bg-[var(--bg-secondary)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-button)"},children:[e.jsx(c.Building2,{className:"w-3.5 h-3.5"}),n.name]})]}),e.jsxs("button",{onClick:()=>r("/myspace/preferences?tab=favorites"),className:"flex items-center gap-1.5 px-3 py-1.5 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors",style:{borderRadius:"var(--radius-button)"},children:[e.jsx(c.Settings,{className:"w-4 h-4"}),t("common:favorites.manage")]})]}),d&&e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(c.Loader2,{className:"w-6 h-6 animate-spin text-[var(--color-accent-500)]"})}),!d&&s.length===0&&e.jsxs("div",{className:"text-center py-8",children:[e.jsx(c.Star,{className:"w-12 h-12 mx-auto text-[var(--text-muted)] mb-3"}),e.jsx("p",{className:"text-[var(--text-secondary)] mb-4",children:t("common:favorites.noFavorites")}),e.jsx("button",{onClick:()=>r("/myspace/preferences?tab=favorites"),className:"px-4 py-2 bg-[var(--color-accent-600)] text-white font-medium hover:bg-[var(--color-accent-700)] transition-colors",style:{borderRadius:"var(--radius-button)"},children:t("common:favorites.configureFavorites")})]}),!d&&s.length>0&&e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3",children:s.map(l=>e.jsxs("button",{onClick:()=>I(l),className:"flex flex-col items-center gap-2 p-4 bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-all group",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"w-12 h-12 flex items-center justify-center bg-[var(--color-accent-100)] text-[var(--color-accent-600)] group-hover:bg-[var(--color-accent-600)] group-hover:text-white transition-colors",style:{borderRadius:"var(--radius-button)"},children:e.jsx(ee,{name:l.icon,className:"w-6 h-6"})}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)] text-center",children:l.label}),e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:l.applicationLabel})]},l.id))})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[e.jsx(j,{title:t("navigation:dashboard.stats.totalSessions"),value:y?.totalSessions??0,icon:e.jsx(c.Activity,{className:"w-5 h-5"}),subtitle:`${m} ${t("navigation:dashboard.stats.lastDays")}`}),e.jsx(j,{title:t("navigation:dashboard.stats.avgDuration"),value:`${Math.round(y?.avgSessionDuration??0)} min`,icon:e.jsx(c.TrendingUp,{className:"w-5 h-5"}),subtitle:t("navigation:dashboard.stats.perSession")}),e.jsx(j,{title:t("navigation:dashboard.stats.connectionErrors"),value:(p??[]).length,icon:e.jsx(c.AlertTriangle,{className:"w-5 h-5"}),subtitle:t("navigation:dashboard.stats.recent"),color:(p??[]).length>0?"red":"green"})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.Calendar,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.weeklyUsage.title")})]}),e.jsx(Q,{data:B})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.Clock,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.hourlyUsage.title")})]}),e.jsx(V,{data:P})]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.AppWindow,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.applicationUsage.title")})]}),e.jsx(Z,{data:O})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(c.BarChart3,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.sessionAnalytics.title")})]}),e.jsx("div",{className:"flex gap-2",children:[7,30,90].map(l=>e.jsx("button",{onClick:()=>T(l),className:`px-3 py-1 text-sm font-medium transition-colors ${m===l?"bg-[var(--color-accent-500)] text-white":"bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)]"}`,style:{borderRadius:"var(--radius-button)"},children:t(`navigation:dashboard.sessionAnalytics.period.${l}days`)},l))})]}),e.jsx(Y,{data:y?.dailyStats??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.Monitor,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.currentSession.title")})]}),e.jsx(X,{session:L})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.AlertTriangle,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.loginErrors.title")})]}),e.jsx(_,{errors:p??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx(c.BarChart3,{className:"w-5 h-5 text-[var(--text-secondary)]"}),e.jsx("h2",{className:"font-semibold text-[var(--text-primary)]",children:t("navigation:dashboard.deviceStats.title")})]}),e.jsx(J,{stats:E})]})]})}function j({title:t,value:r,icon:o,subtitle:n,color:a="blue"}){const s={blue:"bg-blue-50 text-blue-600 border-blue-200 dark:bg-blue-900/20 dark:border-blue-800",green:"bg-green-50 text-green-600 border-green-200 dark:bg-green-900/20 dark:border-green-800",red:"bg-red-50 text-red-600 border-red-200 dark:bg-red-900/20 dark:border-red-800"};return e.jsxs("div",{className:`p-4 border ${s[a]}`,style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm font-medium opacity-80",children:t}),o]}),e.jsx("div",{className:"text-2xl font-bold",children:r}),n&&e.jsx("div",{className:"text-xs opacity-70 mt-1",children:n})]})}exports.UserDashboardPage=te;
|
|
2
|
+
//# sourceMappingURL=UserDashboardPage-C_tm7Pld.js.map
|