@atlashub/smartstack 3.39.0-preview.1049 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{AgentSkillsPage-DgqyaZwI.js → AgentSkillsPage-BS_W2KTh.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-DgqyaZwI.js.map → AgentSkillsPage-BS_W2KTh.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js → AgentSkillsPage-CmDFLnp7.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js.map → AgentSkillsPage-CmDFLnp7.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js → AgentWorkloadPage-C8IvYfhT.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js.map → AgentWorkloadPage-C8IvYfhT.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js → AgentWorkloadPage-JXsQbwuM.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js.map → AgentWorkloadPage-JXsQbwuM.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js → ApiCatalogDetailPage-CYOt34Vy.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js.map → ApiCatalogDetailPage-CYOt34Vy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js → ApiCatalogDetailPage-wFZDsTGy.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js.map → ApiCatalogDetailPage-wFZDsTGy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js → ApiCatalogPage-Bdm3HNGP.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js.map → ApiCatalogPage-Bdm3HNGP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js → ApiCatalogPage-m_TWQyGv.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js.map → ApiCatalogPage-m_TWQyGv.js.map} +1 -1
- package/dist/chunks/ApplicationDetailPage-C2BSpEoW.js +2 -0
- package/dist/chunks/{ApplicationDetailPage-CWdz0TS4.js.map → ApplicationDetailPage-C2BSpEoW.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js → ApplicationDetailPage-CcgDAP-J.js} +503 -501
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js.map → ApplicationDetailPage-CcgDAP-J.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js → ApplicationsDashboardPage-CDIjziL3.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js.map → ApplicationsDashboardPage-CDIjziL3.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js → ApplicationsDashboardPage-DslDyNzJ.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js.map → ApplicationsDashboardPage-DslDyNzJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js → ApplicationsGridPage-BCjsQGU0.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js.map → ApplicationsGridPage-BCjsQGU0.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js → ApplicationsGridPage-CIfKiCND.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js.map → ApplicationsGridPage-CIfKiCND.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js → ApplicationsListPage-CT75kNcH.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js.map → ApplicationsListPage-CT75kNcH.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js → ApplicationsListPage-D2B4PZ5n.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js.map → ApplicationsListPage-D2B4PZ5n.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js → ApplicationsPage-CaTBtduL.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js.map → ApplicationsPage-CaTBtduL.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js → ApplicationsPage-DW1LhL0U.js} +4 -4
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js.map → ApplicationsPage-DW1LhL0U.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js → AssignmentRulesPage-Bt9M0ki7.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js.map → AssignmentRulesPage-Bt9M0ki7.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js → AssignmentRulesPage-Y7xv60NY.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js.map → AssignmentRulesPage-Y7xv60NY.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js → AssignmentsPage-1eQGTjTi.js} +2 -2
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js.map → AssignmentsPage-1eQGTjTi.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js → AssignmentsPage-RURdPvfZ.js} +2 -2
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js.map → AssignmentsPage-RURdPvfZ.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js → AuthCallbackPage-8hF0jYlK.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js.map → AuthCallbackPage-8hF0jYlK.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js → AuthCallbackPage-DPL68Asu.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js.map → AuthCallbackPage-DPL68Asu.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js → ConfirmEmailPage-BKlpZkVk.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js.map → ConfirmEmailPage-BKlpZkVk.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js → ConfirmEmailPage-CawSZypI.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js.map → ConfirmEmailPage-CawSZypI.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js → CreateSupportTicketPage-AwbMbBIH.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js.map → CreateSupportTicketPage-AwbMbBIH.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js → CreateSupportTicketPage-Dg1YW1eA.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js.map → CreateSupportTicketPage-Dg1YW1eA.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js → DashboardPage-B4YxOF-9.js} +3 -3
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js.map → DashboardPage-B4YxOF-9.js.map} +1 -1
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js → DashboardPage-BZxjinar.js} +2 -2
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js.map → DashboardPage-BZxjinar.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BAqpoxCW.js → DashboardPage-Bo09y8r7.js} +3 -3
- package/dist/chunks/{DashboardPage-BAqpoxCW.js.map → DashboardPage-Bo09y8r7.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BT5kFaQA.js → DashboardPage-Cq5adDjP.js} +2 -2
- package/dist/chunks/{DashboardPage-BT5kFaQA.js.map → DashboardPage-Cq5adDjP.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js → EscalationConfigPage-C8Hv5naz.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js.map → EscalationConfigPage-C8Hv5naz.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js → EscalationConfigPage-DNAqMRxA.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js.map → EscalationConfigPage-DNAqMRxA.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js → ForceChangePasswordPage-BURE_vNg.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js.map → ForceChangePasswordPage-BURE_vNg.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js → ForceChangePasswordPage-C6jDZshk.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js.map → ForceChangePasswordPage-C6jDZshk.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js → ForgotPasswordPage-C5HLYbz4.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js.map → ForgotPasswordPage-C5HLYbz4.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js → ForgotPasswordPage-D3ZQBtjd.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js.map → ForgotPasswordPage-D3ZQBtjd.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js → GroupDetailPage-CTuzp9Vp.js} +5 -5
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js.map → GroupDetailPage-CTuzp9Vp.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js → GroupDetailPage-NJc2zCxC.js} +2 -2
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js.map → GroupDetailPage-NJc2zCxC.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js → MyAccessRequestsPage-Cvr29Pnq.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js.map → MyAccessRequestsPage-Cvr29Pnq.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js → MyAccessRequestsPage-t6I24rHN.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js.map → MyAccessRequestsPage-t6I24rHN.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js → MyTenantsPage-Dy2RZ_Ei.js} +2 -2
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js.map → MyTenantsPage-Dy2RZ_Ei.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js → MyTenantsPage-SvDCQ4Wt.js} +3 -3
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js.map → MyTenantsPage-SvDCQ4Wt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js → MyTicketsPage-C3lEBFD9.js} +2 -2
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js.map → MyTicketsPage-C3lEBFD9.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js → MyTicketsPage-DydDgFyz.js} +2 -2
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js.map → MyTicketsPage-DydDgFyz.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js → NavigationAppsPage-Dyv767w8.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js.map → NavigationAppsPage-Dyv767w8.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js → NavigationAppsPage-WqSspaVo.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js.map → NavigationAppsPage-WqSspaVo.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-_62-bmuk.js → NotificationsPage-Di4I95PM.js} +2 -2
- package/dist/chunks/{NotificationsPage-_62-bmuk.js.map → NotificationsPage-Di4I95PM.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js → NotificationsPage-elSovpBw.js} +2 -2
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js.map → NotificationsPage-elSovpBw.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js → OnboardingWizardPage-fdWdkwiT.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js.map → OnboardingWizardPage-fdWdkwiT.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js → OnboardingWizardPage-nPLe2buQ.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js.map → OnboardingWizardPage-nPLe2buQ.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js → PermissionDetailPage-B8C7tWFP.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js.map → PermissionDetailPage-B8C7tWFP.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js → PermissionDetailPage-IUgUaTkE.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js.map → PermissionDetailPage-IUgUaTkE.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js → PermissionsPage-CmX5sQf2.js} +2 -2
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js.map → PermissionsPage-CmX5sQf2.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js → PermissionsPage-Kg0rduOM.js} +2 -2
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js.map → PermissionsPage-Kg0rduOM.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js → PortalDashboardPage-CCAYuhtI.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js.map → PortalDashboardPage-CCAYuhtI.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js → PortalDashboardPage-Dme1XmzN.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js.map → PortalDashboardPage-Dme1XmzN.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js → PreferencesPage-Ct6xWAFp.js} +2 -2
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js.map → PreferencesPage-Ct6xWAFp.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js → PreferencesPage-Db2RjMpm.js} +2 -2
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js.map → PreferencesPage-Db2RjMpm.js.map} +1 -1
- package/dist/chunks/{ProfilePage-6Gf7igUI.js → ProfilePage-D6Xb1ALH.js} +2 -2
- package/dist/chunks/{ProfilePage-6Gf7igUI.js.map → ProfilePage-D6Xb1ALH.js.map} +1 -1
- package/dist/chunks/{ProfilePage-BzBWkztf.js → ProfilePage-DN2s-lfp.js} +2 -2
- package/dist/chunks/{ProfilePage-BzBWkztf.js.map → ProfilePage-DN2s-lfp.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js → ReferencesManagementPage-B5mcshG1.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js.map → ReferencesManagementPage-B5mcshG1.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js → ReferencesManagementPage-DB975ktX.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js.map → ReferencesManagementPage-DB975ktX.js.map} +1 -1
- package/dist/chunks/{RegisterPage-asdx33fV.js → RegisterPage-ZskZrLZH.js} +2 -2
- package/dist/chunks/{RegisterPage-asdx33fV.js.map → RegisterPage-ZskZrLZH.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CIPHRYkl.js → RegisterPage-b8yIPVgh.js} +2 -2
- package/dist/chunks/{RegisterPage-CIPHRYkl.js.map → RegisterPage-b8yIPVgh.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js → ResetPasswordPage-CeAvfsE-.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js.map → ResetPasswordPage-CeAvfsE-.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js → ResetPasswordPage-Dzp5dCp8.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js.map → ResetPasswordPage-Dzp5dCp8.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Cs6T441o.js → ResolutionModal-CRVN7gHv.js} +2 -2
- package/dist/chunks/{ResolutionModal-Cs6T441o.js.map → ResolutionModal-CRVN7gHv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js → ResolutionModal-DJOw1sLT.js} +2 -2
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js.map → ResolutionModal-DJOw1sLT.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js → RoleDetailPage-CLVoFVF8.js} +2 -2
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js.map → RoleDetailPage-CLVoFVF8.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js → RoleDetailPage-XGnPD_8C.js} +3 -3
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js.map → RoleDetailPage-XGnPD_8C.js.map} +1 -1
- package/dist/chunks/{RolesPage-BHEkMR2O.js → RolesPage-BnAMpR2b.js} +2 -2
- package/dist/chunks/{RolesPage-BHEkMR2O.js.map → RolesPage-BnAMpR2b.js.map} +1 -1
- package/dist/chunks/{RolesPage-D35jwDJU.js → RolesPage-Czj9LMkL.js} +2 -2
- package/dist/chunks/{RolesPage-D35jwDJU.js.map → RolesPage-Czj9LMkL.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-DtonDehw.js → SlaConfigPage-HM0MpIlg.js} +2 -2
- package/dist/chunks/{SlaConfigPage-DtonDehw.js.map → SlaConfigPage-HM0MpIlg.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js → SlaConfigPage-ZRyAs8aY.js} +2 -2
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js.map → SlaConfigPage-ZRyAs8aY.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js → SupportPermissionsPage-CxJuGgcQ.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js.map → SupportPermissionsPage-CxJuGgcQ.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js → SupportPermissionsPage-DNd323OK.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js.map → SupportPermissionsPage-DNd323OK.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js → TemplatesPage-CdwPLsHj.js} +2 -2
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js.map → TemplatesPage-CdwPLsHj.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DlY91VO_.js → TemplatesPage-Co3ygZvF.js} +2 -2
- package/dist/chunks/{TemplatesPage-DlY91VO_.js.map → TemplatesPage-Co3ygZvF.js.map} +1 -1
- package/dist/chunks/{TenantCard-BHLcv2gD.js → TenantCard-CmCfIK2F.js} +2 -2
- package/dist/chunks/{TenantCard-BHLcv2gD.js.map → TenantCard-CmCfIK2F.js.map} +1 -1
- package/dist/chunks/{TenantCard-DGCKVvKI.js → TenantCard-DI66acce.js} +2 -2
- package/dist/chunks/{TenantCard-DGCKVvKI.js.map → TenantCard-DI66acce.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js → TenantScopeSelector-5NOwmFX2.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js.map → TenantScopeSelector-5NOwmFX2.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js → TenantScopeSelector-CEFgxiWt.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js.map → TenantScopeSelector-CEFgxiWt.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js → TicketDetailPage-BhZ-mpv7.js} +2 -2
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js.map → TicketDetailPage-BhZ-mpv7.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js → TicketDetailPage-BxOiOG22.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js.map → TicketDetailPage-BxOiOG22.js.map} +1 -1
- package/dist/chunks/{TicketsPage-CufUJctx.js → TicketsPage-BiTvIcM8.js} +2 -2
- package/dist/chunks/{TicketsPage-CufUJctx.js.map → TicketsPage-BiTvIcM8.js.map} +1 -1
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js → TicketsPage-CSiinHME.js} +2 -2
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js.map → TicketsPage-CSiinHME.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js → UserCreateTicketPage-B3TW1oV7.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js.map → UserCreateTicketPage-B3TW1oV7.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js → UserCreateTicketPage-BszUd_WZ.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js.map → UserCreateTicketPage-BszUd_WZ.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js → UserDashboardPage-C6MvatAb.js} +2 -2
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js.map → UserDashboardPage-C6MvatAb.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js → UserDashboardPage-Dtt9VzG_.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js.map → UserDashboardPage-Dtt9VzG_.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-C97e-Dax.js → UserDetailPage-BEEV2vlJ.js} +5 -5
- package/dist/chunks/{UserDetailPage-C97e-Dax.js.map → UserDetailPage-BEEV2vlJ.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js → UserDetailPage-Dw5OHheZ.js} +2 -2
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js.map → UserDetailPage-Dw5OHheZ.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js → UserTicketDetailPage-B4YkzzbR.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js.map → UserTicketDetailPage-B4YkzzbR.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js → UserTicketDetailPage-DCFV-0ny.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js.map → UserTicketDetailPage-DCFV-0ny.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js → UsersGroupsPage-CY-l9fTp.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js.map → UsersGroupsPage-CY-l9fTp.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js → UsersGroupsPage-c28vYHN9.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js.map → UsersGroupsPage-c28vYHN9.js.map} +1 -1
- package/dist/chunks/{UsersPage-BIXWHFmG.js → UsersPage-1sLlq9QD.js} +2 -2
- package/dist/chunks/{UsersPage-BIXWHFmG.js.map → UsersPage-1sLlq9QD.js.map} +1 -1
- package/dist/chunks/{UsersPage-DS8aWUKj.js → UsersPage-Bm-uNxh0.js} +2 -2
- package/dist/chunks/{UsersPage-DS8aWUKj.js.map → UsersPage-Bm-uNxh0.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js → accessRequestsApi-CJPjyEkH.js} +2 -2
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js.map → accessRequestsApi-CJPjyEkH.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js → accessRequestsApi-D_pj1wl6.js} +2 -2
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js.map → accessRequestsApi-D_pj1wl6.js.map} +1 -1
- package/dist/chunks/{aiApi-B-H-76wM.js → aiApi-ByF-oo1J.js} +2 -2
- package/dist/chunks/{aiApi-B-H-76wM.js.map → aiApi-ByF-oo1J.js.map} +1 -1
- package/dist/chunks/{aiApi-CcdrBILv.js → aiApi-Dt3fj0dU.js} +2 -2
- package/dist/chunks/{aiApi-CcdrBILv.js.map → aiApi-Dt3fj0dU.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js → applicationAnalyticsApi-BgG3SGJm.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js.map → applicationAnalyticsApi-BgG3SGJm.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js → applicationAnalyticsApi-ktD65iLO.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js.map → applicationAnalyticsApi-ktD65iLO.js.map} +1 -1
- package/dist/chunks/{groupsApi-DExOJZPF.js → groupsApi-C-FLWPCO.js} +2 -2
- package/dist/chunks/{groupsApi-DExOJZPF.js.map → groupsApi-C-FLWPCO.js.map} +1 -1
- package/dist/chunks/{groupsApi-CyqyYsmi.js → groupsApi-CBI5vMLa.js} +2 -2
- package/dist/chunks/{groupsApi-CyqyYsmi.js.map → groupsApi-CBI5vMLa.js.map} +1 -1
- package/dist/chunks/{index-DtAReZI6.js → index-B727-QSU.js} +2 -2
- package/dist/chunks/{index-DtAReZI6.js.map → index-B727-QSU.js.map} +1 -1
- package/dist/chunks/{index-BlOgmQzc.js → index-B9q3vx13.js} +2 -2
- package/dist/chunks/{index-BlOgmQzc.js.map → index-B9q3vx13.js.map} +1 -1
- package/dist/chunks/{index-VSQ2prtJ.js → index-BD-REzV9.js} +2 -2
- package/dist/chunks/{index-VSQ2prtJ.js.map → index-BD-REzV9.js.map} +1 -1
- package/dist/chunks/{index-XOOiD_zY.js → index-BDRogQH_.js} +3 -3
- package/dist/chunks/{index-XOOiD_zY.js.map → index-BDRogQH_.js.map} +1 -1
- package/dist/chunks/{index-DOQyf5yZ.js → index-C-DYxdvd.js} +8 -8
- package/dist/chunks/{index-DOQyf5yZ.js.map → index-C-DYxdvd.js.map} +1 -1
- package/dist/chunks/{index-Cq80YBne.js → index-CBtjGPod.js} +105 -105
- package/dist/chunks/{index-Cq80YBne.js.map → index-CBtjGPod.js.map} +1 -1
- package/dist/chunks/{index-dlXYTPWH.js → index-CF1cvNUL.js} +4 -4
- package/dist/chunks/{index-dlXYTPWH.js.map → index-CF1cvNUL.js.map} +1 -1
- package/dist/chunks/{index-COA_xJVJ.js → index-CH0pTHy1.js} +2 -2
- package/dist/chunks/{index-COA_xJVJ.js.map → index-CH0pTHy1.js.map} +1 -1
- package/dist/chunks/{index-DjZQ6ZG_.js → index-Ca88RIuT.js} +2 -2
- package/dist/chunks/{index-DjZQ6ZG_.js.map → index-Ca88RIuT.js.map} +1 -1
- package/dist/chunks/{index-Cj-9tGpd.js → index-CkWvsvKW.js} +2 -2
- package/dist/chunks/{index-Cj-9tGpd.js.map → index-CkWvsvKW.js.map} +1 -1
- package/dist/chunks/{index-EL_ZNnMH.js → index-CzYKE5fL.js} +2 -2
- package/dist/chunks/{index-EL_ZNnMH.js.map → index-CzYKE5fL.js.map} +1 -1
- package/dist/chunks/{index-qXfYaEmV.js → index-D32ol7lq.js} +2 -2
- package/dist/chunks/{index-qXfYaEmV.js.map → index-D32ol7lq.js.map} +1 -1
- package/dist/chunks/{index-DMQQ0KyA.js → index-D7hmx9IX.js} +2 -2
- package/dist/chunks/{index-DMQQ0KyA.js.map → index-D7hmx9IX.js.map} +1 -1
- package/dist/chunks/{index-BetDcNZm.js → index-DThcQmwZ.js} +2 -2
- package/dist/chunks/{index-BetDcNZm.js.map → index-DThcQmwZ.js.map} +1 -1
- package/dist/chunks/{index-C7h5yvcP.js → index-D_3J6ziZ.js} +2 -2
- package/dist/chunks/{index-C7h5yvcP.js.map → index-D_3J6ziZ.js.map} +1 -1
- package/dist/chunks/{index-C_nDTEP5.js → index-JSjfMShT.js} +2 -2
- package/dist/chunks/{index-C_nDTEP5.js.map → index-JSjfMShT.js.map} +1 -1
- package/dist/chunks/{index-COXxU0FH.js → index-gzXJw_ow.js} +3 -3
- package/dist/chunks/{index-COXxU0FH.js.map → index-gzXJw_ow.js.map} +1 -1
- package/dist/chunks/{index-jJxtz2bs.js → index-rRAbl04H.js} +2 -2
- package/dist/chunks/{index-jJxtz2bs.js.map → index-rRAbl04H.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js → tenantIconMap-Cw-hQ9n4.js} +2 -2
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js.map → tenantIconMap-Cw-hQ9n4.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js → tenantIconMap-DinwojNW.js} +2 -2
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js.map → tenantIconMap-DinwojNW.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js → ticketingApi-CcWdebXv.js} +2 -2
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js.map → ticketingApi-CcWdebXv.js.map} +1 -1
- package/dist/chunks/{ticketingApi-D6s75rOB.js → ticketingApi-x0BwZ1NH.js} +2 -2
- package/dist/chunks/{ticketingApi-D6s75rOB.js.map → ticketingApi-x0BwZ1NH.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js → useAccessRequests-BBTIYht3.js} +2 -2
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js.map → useAccessRequests-BBTIYht3.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CanI2ypo.js → useAccessRequests-BBUj9XY9.js} +71 -71
- package/dist/chunks/{useAccessRequests-CanI2ypo.js.map → useAccessRequests-BBUj9XY9.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js → useUserAccessRequests-BKQxcOXH.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js.map → useUserAccessRequests-BKQxcOXH.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js → useUserAccessRequests-BPUPiP55.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js.map → useUserAccessRequests-BPUPiP55.js.map} +1 -1
- package/dist/pages/platform/administration/applications/ApplicationDetailPage.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/ApplicationDetailPage-CWdz0TS4.js +0 -2
package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js.map → UserCreateTicketPage-BszUd_WZ.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserCreateTicketPage-XxjNlR9K.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-BszUd_WZ.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-XOOiD_zY.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 rounded-[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)] rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"p-2 bg-[var(--accent-bg)] text-[var(--color-accent-500)] rounded-[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)] rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"p-2 bg-blue-500/10 text-blue-500 rounded-[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)] rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"p-2 bg-green-500/10 text-green-500 rounded-[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,R]=u.useState(30),[U,N]=u.useState(!0),[p,w]=u.useState(null),[y,S]=u.useState([]),[L,C]=u.useState(null),[E,k]=u.useState(null),[B,D]=u.useState(null),[P,A]=u.useState(null),[O,$]=u.useState(null),F=l=>{if(a)for(const b of a.applications){const T=b.modules.find(g=>g.id===l.id);if(T?.sections?.length){const g=[...T.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",M=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),$(l.applicationUsage)}catch{w(null),S([]),C(null),k(null),D(null),A(null),$(null)}finally{N(!1)}},[m]);return u.useEffect(()=>{M()},[m,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)] rounded-[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)] rounded-[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 rounded-[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 rounded-[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 rounded-[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 rounded-[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:p?.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(p?.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:(y??[]).length,icon:e.jsx(c.AlertTriangle,{className:"w-5 h-5"}),subtitle:t("navigation:dashboard.stats.recent"),color:(y??[]).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)] rounded-[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)] rounded-[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)] rounded-[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)] rounded-[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:()=>R(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)]"} rounded-[var(--radius-button)]`,children:t(`navigation:dashboard.sessionAnalytics.period.${l}days`)},l))})]}),e.jsx(Y,{data:p?.dailyStats??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)] rounded-[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)] rounded-[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:y??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)] rounded-[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]} rounded-[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-BDRogQH_.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 rounded-[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)] rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"p-2 bg-[var(--accent-bg)] text-[var(--color-accent-500)] rounded-[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)] rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"p-2 bg-blue-500/10 text-blue-500 rounded-[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)] rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"p-2 bg-green-500/10 text-green-500 rounded-[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,R]=u.useState(30),[U,N]=u.useState(!0),[p,w]=u.useState(null),[y,S]=u.useState([]),[L,C]=u.useState(null),[E,k]=u.useState(null),[B,D]=u.useState(null),[P,A]=u.useState(null),[O,$]=u.useState(null),F=l=>{if(a)for(const b of a.applications){const T=b.modules.find(g=>g.id===l.id);if(T?.sections?.length){const g=[...T.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",M=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),$(l.applicationUsage)}catch{w(null),S([]),C(null),k(null),D(null),A(null),$(null)}finally{N(!1)}},[m]);return u.useEffect(()=>{M()},[m,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)] rounded-[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)] rounded-[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 rounded-[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 rounded-[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 rounded-[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 rounded-[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:p?.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(p?.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:(y??[]).length,icon:e.jsx(c.AlertTriangle,{className:"w-5 h-5"}),subtitle:t("navigation:dashboard.stats.recent"),color:(y??[]).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)] rounded-[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)] rounded-[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)] rounded-[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)] rounded-[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:()=>R(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)]"} rounded-[var(--radius-button)]`,children:t(`navigation:dashboard.sessionAnalytics.period.${l}days`)},l))})]}),e.jsx(Y,{data:p?.dailyStats??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)] rounded-[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)] rounded-[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:y??[]})]}),e.jsxs("div",{className:"p-6 bg-[var(--bg-card)] border border-[var(--border-color)] rounded-[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]} rounded-[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-C6MvatAb.js.map
|