@atlashub/smartstack 3.21.0 → 3.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js → AgentSkillsPage-BWQSCYl-.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js.map → AgentSkillsPage-BWQSCYl-.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js → AgentSkillsPage-IQcMnBaD.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js.map → AgentSkillsPage-IQcMnBaD.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js → AgentWorkloadPage-DqrjkvWL.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js.map → AgentWorkloadPage-DqrjkvWL.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js → AgentWorkloadPage-w-HiyFYP.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js.map → AgentWorkloadPage-w-HiyFYP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js → ApiCatalogDetailPage-D3L8Yf4G.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js.map → ApiCatalogDetailPage-D3L8Yf4G.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js → ApiCatalogDetailPage-MPT3Kz6H.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js.map → ApiCatalogDetailPage-MPT3Kz6H.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js → ApiCatalogPage-D4Hg3uiS.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js.map → ApiCatalogPage-D4Hg3uiS.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js → ApiCatalogPage-DRg5Cz0r.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js.map → ApiCatalogPage-DRg5Cz0r.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js → ApplicationDetailPage-Caizuyn2.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js.map → ApplicationDetailPage-Caizuyn2.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js → ApplicationDetailPage-CuCW6aMB.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js.map → ApplicationDetailPage-CuCW6aMB.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js → ApplicationsDashboardPage-B2MW8-Kc.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js.map → ApplicationsDashboardPage-B2MW8-Kc.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js → ApplicationsDashboardPage-BDIjFIYZ.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js.map → ApplicationsDashboardPage-BDIjFIYZ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js → ApplicationsGridPage-DV-FihKj.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js.map → ApplicationsGridPage-DV-FihKj.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js → ApplicationsGridPage-DXsTfXPI.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js.map → ApplicationsGridPage-DXsTfXPI.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js → ApplicationsListPage--CGkyBuJ.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js.map → ApplicationsListPage--CGkyBuJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js → ApplicationsListPage-JUX823bh.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js.map → ApplicationsListPage-JUX823bh.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js → ApplicationsPage-6zgFye6w.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js.map → ApplicationsPage-6zgFye6w.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js → ApplicationsPage-CQPuuiO6.js} +4 -4
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js.map → ApplicationsPage-CQPuuiO6.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js → AssignmentRulesPage-CFffeEbo.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js.map → AssignmentRulesPage-CFffeEbo.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js → AssignmentRulesPage-D78UeUId.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js.map → AssignmentRulesPage-D78UeUId.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js → AssignmentsPage-Cww2ifZF.js} +2 -2
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js.map → AssignmentsPage-Cww2ifZF.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js → AssignmentsPage-DE_QS2LO.js} +2 -2
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js.map → AssignmentsPage-DE_QS2LO.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js → AuthCallbackPage-CA2nO6DG.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js.map → AuthCallbackPage-CA2nO6DG.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js → AuthCallbackPage-CDUAoX-N.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js.map → AuthCallbackPage-CDUAoX-N.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js → ConfirmEmailPage-BqsILAYH.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js.map → ConfirmEmailPage-BqsILAYH.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js → ConfirmEmailPage-INeHCuMB.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js.map → ConfirmEmailPage-INeHCuMB.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js → CreateSupportTicketPage-BWeuV2aU.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js.map → CreateSupportTicketPage-BWeuV2aU.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js → CreateSupportTicketPage-OBwF4v7b.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js.map → CreateSupportTicketPage-OBwF4v7b.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZ80NGV.js → DashboardPage-CKHqWrdS.js} +3 -3
- package/dist/chunks/{DashboardPage-CUZ80NGV.js.map → DashboardPage-CKHqWrdS.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CaNOAstg.js → DashboardPage-COmc9b__.js} +3 -3
- package/dist/chunks/{DashboardPage-CaNOAstg.js.map → DashboardPage-COmc9b__.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B48_rQFi.js → DashboardPage-CfKZHiSj.js} +2 -2
- package/dist/chunks/{DashboardPage-B48_rQFi.js.map → DashboardPage-CfKZHiSj.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZV1J9t.js → DashboardPage-CwEZZ3jx.js} +2 -2
- package/dist/chunks/{DashboardPage-CUZV1J9t.js.map → DashboardPage-CwEZZ3jx.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js → EscalationConfigPage--7lgZ0kJ.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js.map → EscalationConfigPage--7lgZ0kJ.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js → EscalationConfigPage-DPyiBcqV.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js.map → EscalationConfigPage-DPyiBcqV.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js → ForceChangePasswordPage-BE-6umub.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js.map → ForceChangePasswordPage-BE-6umub.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js → ForceChangePasswordPage-CnsYoWmV.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js.map → ForceChangePasswordPage-CnsYoWmV.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js → ForgotPasswordPage-CSq4DnFF.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js.map → ForgotPasswordPage-CSq4DnFF.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js → ForgotPasswordPage-DZLVolAC.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js.map → ForgotPasswordPage-DZLVolAC.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js → GroupDetailPage-Bf9Wb_2j.js} +5 -5
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js.map → GroupDetailPage-Bf9Wb_2j.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js → GroupDetailPage-R-hf3rJ7.js} +2 -2
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js.map → GroupDetailPage-R-hf3rJ7.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js → MyAccessRequestsPage-BIisvWM6.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js.map → MyAccessRequestsPage-BIisvWM6.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js → MyAccessRequestsPage-BLSV7Tbx.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js.map → MyAccessRequestsPage-BLSV7Tbx.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js → MyTenantsPage-D-7k9CP1.js} +3 -3
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js.map → MyTenantsPage-D-7k9CP1.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js → MyTenantsPage-DqGW6aDt.js} +2 -2
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js.map → MyTenantsPage-DqGW6aDt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js → MyTicketsPage--DgDsnZA.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js.map → MyTicketsPage--DgDsnZA.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js → MyTicketsPage-CqJ3Aqob.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js.map → MyTicketsPage-CqJ3Aqob.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js → NavigationAppsPage-Bebis_RT.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js.map → NavigationAppsPage-Bebis_RT.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js → NavigationAppsPage-THNPOAjv.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js.map → NavigationAppsPage-THNPOAjv.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-C29Lln5o.js → NotificationsPage-CAbNW_Cn.js} +2 -2
- package/dist/chunks/{NotificationsPage-C29Lln5o.js.map → NotificationsPage-CAbNW_Cn.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js → NotificationsPage-DxwizUhL.js} +2 -2
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js.map → NotificationsPage-DxwizUhL.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js → OnboardingWizardPage-C6HlbJ3K.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js.map → OnboardingWizardPage-C6HlbJ3K.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js → OnboardingWizardPage-CyC2zONO.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js.map → OnboardingWizardPage-CyC2zONO.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js → PermissionDetailPage-BDHiNgky.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js.map → PermissionDetailPage-BDHiNgky.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js → PermissionDetailPage-C5K17ydY.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js.map → PermissionDetailPage-C5K17ydY.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js → PermissionsPage-COI5LJPo.js} +2 -2
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js.map → PermissionsPage-COI5LJPo.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js → PermissionsPage-CkOwH2_d.js} +2 -2
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js.map → PermissionsPage-CkOwH2_d.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js → PortalDashboardPage-CoEC4CmC.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js.map → PortalDashboardPage-CoEC4CmC.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js → PortalDashboardPage-DrYymEf-.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js.map → PortalDashboardPage-DrYymEf-.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js → PreferencesPage-CJRaU3ba.js} +2 -2
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js.map → PreferencesPage-CJRaU3ba.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-B81MsNV1.js → PreferencesPage-Cqr9mAab.js} +2 -2
- package/dist/chunks/{PreferencesPage-B81MsNV1.js.map → PreferencesPage-Cqr9mAab.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DDrl10zj.js → ProfilePage-BZVpg6-l.js} +2 -2
- package/dist/chunks/{ProfilePage-DDrl10zj.js.map → ProfilePage-BZVpg6-l.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DPoXwdnc.js → ProfilePage-Cu_FITeL.js} +2 -2
- package/dist/chunks/{ProfilePage-DPoXwdnc.js.map → ProfilePage-Cu_FITeL.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js → ReferencesManagementPage-DUlVk9Ps.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js.map → ReferencesManagementPage-DUlVk9Ps.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js → ReferencesManagementPage-ZCuYtqd7.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js.map → ReferencesManagementPage-ZCuYtqd7.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CiQib3-6.js → RegisterPage-C4xmVwh9.js} +2 -2
- package/dist/chunks/{RegisterPage-CiQib3-6.js.map → RegisterPage-C4xmVwh9.js.map} +1 -1
- package/dist/chunks/{RegisterPage-bXCcJD88.js → RegisterPage-DGyzoIHT.js} +2 -2
- package/dist/chunks/{RegisterPage-bXCcJD88.js.map → RegisterPage-DGyzoIHT.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js → ResetPasswordPage-DqDD6VPR.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js.map → ResetPasswordPage-DqDD6VPR.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js → ResetPasswordPage-Glu-aeqv.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js.map → ResetPasswordPage-Glu-aeqv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js → ResolutionModal-CxjANAOP.js} +2 -2
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js.map → ResolutionModal-CxjANAOP.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js → ResolutionModal-Duat18qV.js} +2 -2
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js.map → ResolutionModal-Duat18qV.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js → RoleDetailPage-BQffUSnt.js} +3 -3
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js.map → RoleDetailPage-BQffUSnt.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js → RoleDetailPage-JTm5lD1_.js} +2 -2
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js.map → RoleDetailPage-JTm5lD1_.js.map} +1 -1
- package/dist/chunks/{RolesPage-Pm-RN3lP.js → RolesPage-B9rRzciI.js} +2 -2
- package/dist/chunks/{RolesPage-Pm-RN3lP.js.map → RolesPage-B9rRzciI.js.map} +1 -1
- package/dist/chunks/{RolesPage-Cb8joqdJ.js → RolesPage-BN8_zMOC.js} +2 -2
- package/dist/chunks/{RolesPage-Cb8joqdJ.js.map → RolesPage-BN8_zMOC.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-B86McKM6.js → SlaConfigPage-B7kZNig4.js} +2 -2
- package/dist/chunks/{SlaConfigPage-B86McKM6.js.map → SlaConfigPage-B7kZNig4.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js → SlaConfigPage-okvZfA_K.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js.map → SlaConfigPage-okvZfA_K.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js → SupportPermissionsPage-DGAPqJbl.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js.map → SupportPermissionsPage-DGAPqJbl.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js → SupportPermissionsPage-Dg_wLOme.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js.map → SupportPermissionsPage-Dg_wLOme.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-BDguJ401.js → TemplatesPage-DT9fhlAU.js} +2 -2
- package/dist/chunks/{TemplatesPage-BDguJ401.js.map → TemplatesPage-DT9fhlAU.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DdnGgioU.js → TemplatesPage-DiEk538p.js} +2 -2
- package/dist/chunks/{TemplatesPage-DdnGgioU.js.map → TemplatesPage-DiEk538p.js.map} +1 -1
- package/dist/chunks/{TenantCard-ffwWsgFQ.js → TenantCard-BbSYk9_Z.js} +2 -2
- package/dist/chunks/{TenantCard-ffwWsgFQ.js.map → TenantCard-BbSYk9_Z.js.map} +1 -1
- package/dist/chunks/{TenantCard-CUjb6og9.js → TenantCard-CEkiKxcZ.js} +2 -2
- package/dist/chunks/{TenantCard-CUjb6og9.js.map → TenantCard-CEkiKxcZ.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js → TenantScopeSelector-BWfYxvEa.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js.map → TenantScopeSelector-BWfYxvEa.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js → TenantScopeSelector-D-BKgQPV.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js.map → TenantScopeSelector-D-BKgQPV.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js → TicketDetailPage-C1mNS9Up.js} +2 -2
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js.map → TicketDetailPage-C1mNS9Up.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js → TicketDetailPage-ieVDRh42.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js.map → TicketDetailPage-ieVDRh42.js.map} +1 -1
- package/dist/chunks/{TicketsPage-Bqd6moQy.js → TicketsPage-CnuWsnIW.js} +2 -2
- package/dist/chunks/{TicketsPage-Bqd6moQy.js.map → TicketsPage-CnuWsnIW.js.map} +1 -1
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js → TicketsPage-jjyY15_D.js} +2 -2
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js.map → TicketsPage-jjyY15_D.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js → UserCreateTicketPage-B8Tvf-ag.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js.map → UserCreateTicketPage-B8Tvf-ag.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js → UserCreateTicketPage-DnOsDlfO.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js.map → UserCreateTicketPage-DnOsDlfO.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js → UserDashboardPage-BrtkJ-NB.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js.map → UserDashboardPage-BrtkJ-NB.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js → UserDashboardPage-KLB5CQP5.js} +2 -2
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js.map → UserDashboardPage-KLB5CQP5.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-B110bmGX.js → UserDetailPage-U7smBQoF.js} +5 -5
- package/dist/chunks/{UserDetailPage-B110bmGX.js.map → UserDetailPage-U7smBQoF.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-CV2VCE46.js → UserDetailPage-_J6lcKAU.js} +2 -2
- package/dist/chunks/{UserDetailPage-CV2VCE46.js.map → UserDetailPage-_J6lcKAU.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js → UserTicketDetailPage-CWoYQgH-.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js.map → UserTicketDetailPage-CWoYQgH-.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js → UserTicketDetailPage-DkufSlvZ.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js.map → UserTicketDetailPage-DkufSlvZ.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js → UsersGroupsPage-C38s2-Rq.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js.map → UsersGroupsPage-C38s2-Rq.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js → UsersGroupsPage-Dq3rAteo.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js.map → UsersGroupsPage-Dq3rAteo.js.map} +1 -1
- package/dist/chunks/{UsersPage-Bg7033pp.js → UsersPage-B5C5KEUR.js} +2 -2
- package/dist/chunks/{UsersPage-Bg7033pp.js.map → UsersPage-B5C5KEUR.js.map} +1 -1
- package/dist/chunks/{UsersPage-TYAfwPY1.js → UsersPage-CXC9Hvq6.js} +2 -2
- package/dist/chunks/{UsersPage-TYAfwPY1.js.map → UsersPage-CXC9Hvq6.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js → accessRequestsApi-B-4TJ5_U.js} +2 -2
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js.map → accessRequestsApi-B-4TJ5_U.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js → accessRequestsApi-DZSfThpd.js} +2 -2
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js.map → accessRequestsApi-DZSfThpd.js.map} +1 -1
- package/dist/chunks/{aiApi-CsH8DXgs.js → aiApi-B20Teu2v.js} +2 -2
- package/dist/chunks/{aiApi-CsH8DXgs.js.map → aiApi-B20Teu2v.js.map} +1 -1
- package/dist/chunks/{aiApi-CVPzFTXa.js → aiApi-DMGz-RPM.js} +2 -2
- package/dist/chunks/{aiApi-CVPzFTXa.js.map → aiApi-DMGz-RPM.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js → applicationAnalyticsApi-Bwa75Fzd.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js.map → applicationAnalyticsApi-Bwa75Fzd.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js → applicationAnalyticsApi-CLBqRPfN.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js.map → applicationAnalyticsApi-CLBqRPfN.js.map} +1 -1
- package/dist/chunks/{groupsApi-BgCk2fsp.js → groupsApi-QzXI-5xu.js} +2 -2
- package/dist/chunks/{groupsApi-BgCk2fsp.js.map → groupsApi-QzXI-5xu.js.map} +1 -1
- package/dist/chunks/{groupsApi-BIbG665N.js → groupsApi-hB9kSWEd.js} +2 -2
- package/dist/chunks/{groupsApi-BIbG665N.js.map → groupsApi-hB9kSWEd.js.map} +1 -1
- package/dist/chunks/{index-Cb3LotuT.js → index--NGcBYUu.js} +3 -3
- package/dist/chunks/{index-Cb3LotuT.js.map → index--NGcBYUu.js.map} +1 -1
- package/dist/chunks/{index-C33zcyF4.js → index--aPwOFjF.js} +2 -2
- package/dist/chunks/{index-C33zcyF4.js.map → index--aPwOFjF.js.map} +1 -1
- package/dist/chunks/{index-sMr9qND_.js → index-0VrOtwP0.js} +2 -2
- package/dist/chunks/{index-sMr9qND_.js.map → index-0VrOtwP0.js.map} +1 -1
- package/dist/chunks/{index-DDKetfKq.js → index-37U271aw.js} +2 -2
- package/dist/chunks/{index-DDKetfKq.js.map → index-37U271aw.js.map} +1 -1
- package/dist/chunks/{index-B9fS7ir6.js → index-B7qZTuQ-.js} +2 -2
- package/dist/chunks/{index-B9fS7ir6.js.map → index-B7qZTuQ-.js.map} +1 -1
- package/dist/chunks/{index-CdjBY7L8.js → index-Bedzmqr-.js} +2 -2
- package/dist/chunks/{index-CdjBY7L8.js.map → index-Bedzmqr-.js.map} +1 -1
- package/dist/chunks/{index-CHG_O1fS.js → index-Betxo5g5.js} +2 -2
- package/dist/chunks/{index-CHG_O1fS.js.map → index-Betxo5g5.js.map} +1 -1
- package/dist/chunks/{index-jiGu-H8x.js → index-BmaJz475.js} +2 -2
- package/dist/chunks/{index-jiGu-H8x.js.map → index-BmaJz475.js.map} +1 -1
- package/dist/chunks/{index-C53JoVNk.js → index-Buhqag3v.js} +2 -2
- package/dist/chunks/{index-C53JoVNk.js.map → index-Buhqag3v.js.map} +1 -1
- package/dist/chunks/{index-DO0Rw7hX.js → index-C3VxlfKq.js} +2 -2
- package/dist/chunks/{index-DO0Rw7hX.js.map → index-C3VxlfKq.js.map} +1 -1
- package/dist/chunks/{index-CSQ60fpG.js → index-CgpRo8Oe.js} +2 -2
- package/dist/chunks/{index-CSQ60fpG.js.map → index-CgpRo8Oe.js.map} +1 -1
- package/dist/chunks/{index-B-e-ELsf.js → index-DOY0w8Iu.js} +8 -8
- package/dist/chunks/{index-B-e-ELsf.js.map → index-DOY0w8Iu.js.map} +1 -1
- package/dist/chunks/{index-D2REDIRX.js → index-DwuvIOrQ.js} +2 -2
- package/dist/chunks/{index-D2REDIRX.js.map → index-DwuvIOrQ.js.map} +1 -1
- package/dist/chunks/{index-DCcl7Qof.js → index-DzedSLdI.js} +2 -2
- package/dist/chunks/{index-DCcl7Qof.js.map → index-DzedSLdI.js.map} +1 -1
- package/dist/chunks/{index-2wUhd9Lu.js → index-IgLVXPg8.js} +10 -10
- package/dist/chunks/index-IgLVXPg8.js.map +1 -0
- package/dist/chunks/{index-CwSaRXXg.js → index-lpIzhufD.js} +1916 -1900
- package/dist/chunks/index-lpIzhufD.js.map +1 -0
- package/dist/chunks/{index-Cuwn2q-f.js → index-mLUKwbGl.js} +4 -4
- package/dist/chunks/{index-Cuwn2q-f.js.map → index-mLUKwbGl.js.map} +1 -1
- package/dist/chunks/{index-B0mk2tNY.js → index-tO6MMIFB.js} +2 -2
- package/dist/chunks/{index-B0mk2tNY.js.map → index-tO6MMIFB.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js → tenantIconMap-BQD9byc8.js} +2 -2
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js.map → tenantIconMap-BQD9byc8.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js → tenantIconMap-CTMuSt18.js} +2 -2
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js.map → tenantIconMap-CTMuSt18.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js → ticketingApi-BNIdox5t.js} +2 -2
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js.map → ticketingApi-BNIdox5t.js.map} +1 -1
- package/dist/chunks/{ticketingApi-r4Avm9iS.js → ticketingApi-J0vC_t7r.js} +2 -2
- package/dist/chunks/{ticketingApi-r4Avm9iS.js.map → ticketingApi-J0vC_t7r.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-B9bF4swg.js → useAccessRequests-DCNNLnxk.js} +3 -3
- package/dist/chunks/{useAccessRequests-B9bF4swg.js.map → useAccessRequests-DCNNLnxk.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js → useAccessRequests-DT7X4FAK.js} +2 -2
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js.map → useAccessRequests-DT7X4FAK.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js → useUserAccessRequests-BYbmG4c7.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js.map → useUserAccessRequests-BYbmG4c7.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js → useUserAccessRequests-CylKxRN6.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js.map → useUserAccessRequests-CylKxRN6.js.map} +1 -1
- package/dist/hooks/useCollapsibleState.d.ts +5 -2
- package/dist/hooks/useCollapsibleState.d.ts.map +1 -1
- package/dist/i18n/config.d.ts +1 -0
- package/dist/i18n/config.d.ts.map +1 -1
- package/dist/main.d.ts +0 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/dist/utils/permissions.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-2wUhd9Lu.js.map +0 -1
- package/dist/chunks/index-CwSaRXXg.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PermissionsPage-DLy9U3P3.js","sources":["../../src/pages/platform/administration/permissions/PermissionsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Search,\r\n Loader2,\r\n ChevronRight,\r\n ChevronDown,\r\n Shield,\r\n FolderTree,\r\n List,\r\n LayoutGrid,\r\n Layers,\r\n FileCode,\r\n Sparkles,\r\n ExternalLink\r\n} from 'lucide-react';\r\nimport { adminApi, type PermissionListDto, type PermissionTreeDto } from '@/services/api/adminApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\ninterface ApplicationTreeNodeProps {\r\n readonly app: PermissionTreeDto['applications'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ApplicationTreeNode({ app, expandedNodes, toggleNode, t }: Readonly<ApplicationTreeNodeProps>) {\r\n return (\r\n <div key={app.id}>\r\n <button\r\n onClick={() => toggleNode(app.id)}\r\n className=\"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n <div className=\"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors\">\r\n {expandedNodes.has(app.id) ? (\r\n <ChevronDown className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n )}\r\n </div>\r\n <div className=\"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-3.5 h-3.5 text-[var(--info-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] text-sm\">{app.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium\">\r\n {t('permissions.levels.application')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{app.permissionPath}</code>\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {app.modules.length} {t('permissions.stats.modules').toLowerCase()}\r\n </div>\r\n </button>\r\n\r\n {expandedNodes.has(app.id) && (\r\n <div className=\"bg-[var(--bg-tertiary)]/50\">\r\n {app.modules.map(module => (\r\n <ModuleTreeNode\r\n key={module.id}\r\n module={module}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface ModuleTreeNodeProps {\r\n readonly module: PermissionTreeDto['applications'][0]['modules'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ModuleTreeNode({ module, expandedNodes, toggleNode, t }: Readonly<ModuleTreeNodeProps>) {\r\n return (\r\n <div key={module.id}>\r\n <button\r\n onClick={() => toggleNode(module.id)}\r\n className=\"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n {module.sections.length > 0 ? (\r\n <div className=\"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors\">\r\n {expandedNodes.has(module.id) ? (\r\n <ChevronDown className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"w-4 h-4\" />\r\n )}\r\n <div className=\"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-3 h-3 text-[var(--success-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-primary)]\">{module.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium\">\r\n {t('permissions.levels.module')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{module.permissionPath}</code>\r\n </div>\r\n {module.sections.length > 0 && (\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {module.sections.length} {t('permissions.stats.sections').toLowerCase()}\r\n </div>\r\n )}\r\n </button>\r\n\r\n {expandedNodes.has(module.id) && module.sections.length > 0 && (\r\n <div className=\"bg-[var(--bg-primary)]\">\r\n {module.sections.map(section => (\r\n <div\r\n key={section.id}\r\n className=\"flex items-center gap-3 py-2 px-4 pl-36 text-sm\"\r\n >\r\n <div className=\"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-3 h-3 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-[var(--text-primary)]\">{section.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n {t('permissions.levels.section')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{section.permissionPath}</code>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface PermissionListRowProps {\r\n readonly permission: PermissionListDto;\r\n readonly navigate: (path: string) => void;\r\n}\r\n\r\nfunction PermissionListRow({ permission, navigate }: Readonly<PermissionListRowProps>) {\r\n return (\r\n <tr\r\n key={permission.id}\r\n onClick={() => navigate(`/administration/permissions/permissions/${permission.id}`)}\r\n className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <code className=\"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors\">{permission.path}</code>\r\n {permission.isWildcard && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n <Sparkles className=\"w-3 h-3\" />\r\n wildcard\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <span className=\"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium\">\r\n {permission.level}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell\">{permission.description || '-'}</td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]\">\r\n {permission.rolesCount}\r\n </span>\r\n <ExternalLink className=\"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity\" />\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n}\r\n\r\nexport function PermissionsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [tree, setTree] = useState<PermissionTreeDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState('');\r\n const [viewMode, setViewMode] = useState<'list' | 'tree'>('list');\r\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());\r\n\r\n const loadPermissions = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.permissions.getAll({ search: search || undefined });\r\n setPermissions(result);\r\n } catch (err) {\r\n console.error('Failed to load permissions:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [search]);\r\n\r\n const collectAllNodeIds = (tree: PermissionTreeDto): Set<string> => {\r\n const allIds = new Set<string>();\r\n (tree.applications ?? []).forEach(app => {\r\n allIds.add(app.id);\r\n (app.modules ?? []).forEach(mod => {\r\n allIds.add(mod.id);\r\n });\r\n });\r\n return allIds;\r\n };\r\n\r\n const loadTree = async () => {\r\n try {\r\n const result = await adminApi.permissions.getTree();\r\n setTree(result);\r\n const allIds = collectAllNodeIds(result);\r\n setExpandedNodes(allIds);\r\n } catch (err) {\r\n console.error('Failed to load permission tree:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadPermissions();\r\n loadTree();\r\n }, [loadPermissions]);\r\n\r\n const handleSearch = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n loadPermissions();\r\n };\r\n\r\n const toggleNode = (id: string) => {\r\n setExpandedNodes(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const countTreeStats = (tree: PermissionTreeDto) => {\r\n const apps = tree.applications ?? [];\r\n let modules = 0;\r\n let sections = 0;\r\n apps.forEach(app => {\r\n const mods = app.modules ?? [];\r\n modules += mods.length;\r\n mods.forEach(mod => {\r\n sections += (mod.sections ?? []).length;\r\n });\r\n });\r\n return { applications: apps.length, modules, sections };\r\n };\r\n\r\n const getStats = () => {\r\n if (!tree) return { applications: 0, modules: 0, sections: 0 };\r\n return countTreeStats(tree);\r\n };\r\n\r\n const stats = getStats();\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('permissions.title') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center\">\r\n <Shield className=\"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('permissions.title')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-0.5\">{t('permissions.subtitle')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]\">\r\n <button\r\n onClick={() => setViewMode('tree')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'tree'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <FolderTree className=\"w-4 h-4\" />\r\n {t('permissions.treeView')}\r\n </button>\r\n <button\r\n onClick={() => setViewMode('list')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'list'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n {t('permissions.listView')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Cards */}\r\n <div className=\"grid grid-cols-3 gap-4\">\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.applications}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.applications')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.modules}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.modules')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.sections}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.sections')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Search Bar (List View) */}\r\n {viewMode === 'list' && (\r\n <form onSubmit={handleSearch} className=\"flex gap-2\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]\" />\r\n <input\r\n type=\"text\"\r\n value={search}\r\n onChange={e => setSearch(e.target.value)}\r\n placeholder={t('common.search')}\r\n className=\"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all\"\r\n />\r\n </div>\r\n <button\r\n type=\"submit\"\r\n className=\"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors\"\r\n >\r\n {t('common.search')}\r\n </button>\r\n </form>\r\n )}\r\n\r\n {/* Tree View */}\r\n {viewMode === 'tree' ? (\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n {loading && (\r\n <div className=\"flex justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loading && tree?.applications?.length ? (\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {tree.applications.map(app => (\r\n <ApplicationTreeNode\r\n key={app.id}\r\n app={app}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n ) : !loading && (\r\n <div className=\"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noData')}</p>\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n /* List View */\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.path')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('permissions.columns.level')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('permissions.columns.description')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.roles')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <Loader2 className=\"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]\" />\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length === 0 && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noPermissions')}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length > 0 && (\r\n permissions.map(permission => (\r\n <PermissionListRow\r\n key={permission.id}\r\n permission={permission}\r\n navigate={navigate}\r\n />\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ApplicationTreeNode","app","expandedNodes","toggleNode","t","jsxs","jsx","ChevronDown","ChevronRight","LayoutGrid","module","ModuleTreeNode","Layers","section","FileCode","PermissionListRow","permission","navigate","Sparkles","ExternalLink","PermissionsPage","useTranslation","useNavigate","permissions","setPermissions","useState","tree","setTree","loading","setLoading","search","setSearch","viewMode","setViewMode","setExpandedNodes","loadPermissions","useCallback","result","adminApi","err","collectAllNodeIds","allIds","mod","loadTree","useEffect","handleSearch","e","id","prev","next","stats","apps","modules","sections","mods","Breadcrumb","Shield","FolderTree","List","Search","Loader2"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PermissionsPage-CkOwH2_d.js","sources":["../../src/pages/platform/administration/permissions/PermissionsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Search,\r\n Loader2,\r\n ChevronRight,\r\n ChevronDown,\r\n Shield,\r\n FolderTree,\r\n List,\r\n LayoutGrid,\r\n Layers,\r\n FileCode,\r\n Sparkles,\r\n ExternalLink\r\n} from 'lucide-react';\r\nimport { adminApi, type PermissionListDto, type PermissionTreeDto } from '@/services/api/adminApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\ninterface ApplicationTreeNodeProps {\r\n readonly app: PermissionTreeDto['applications'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ApplicationTreeNode({ app, expandedNodes, toggleNode, t }: Readonly<ApplicationTreeNodeProps>) {\r\n return (\r\n <div key={app.id}>\r\n <button\r\n onClick={() => toggleNode(app.id)}\r\n className=\"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n <div className=\"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors\">\r\n {expandedNodes.has(app.id) ? (\r\n <ChevronDown className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n )}\r\n </div>\r\n <div className=\"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-3.5 h-3.5 text-[var(--info-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] text-sm\">{app.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium\">\r\n {t('permissions.levels.application')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{app.permissionPath}</code>\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {app.modules.length} {t('permissions.stats.modules').toLowerCase()}\r\n </div>\r\n </button>\r\n\r\n {expandedNodes.has(app.id) && (\r\n <div className=\"bg-[var(--bg-tertiary)]/50\">\r\n {app.modules.map(module => (\r\n <ModuleTreeNode\r\n key={module.id}\r\n module={module}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface ModuleTreeNodeProps {\r\n readonly module: PermissionTreeDto['applications'][0]['modules'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ModuleTreeNode({ module, expandedNodes, toggleNode, t }: Readonly<ModuleTreeNodeProps>) {\r\n return (\r\n <div key={module.id}>\r\n <button\r\n onClick={() => toggleNode(module.id)}\r\n className=\"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n {module.sections.length > 0 ? (\r\n <div className=\"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors\">\r\n {expandedNodes.has(module.id) ? (\r\n <ChevronDown className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"w-4 h-4\" />\r\n )}\r\n <div className=\"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-3 h-3 text-[var(--success-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-primary)]\">{module.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium\">\r\n {t('permissions.levels.module')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{module.permissionPath}</code>\r\n </div>\r\n {module.sections.length > 0 && (\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {module.sections.length} {t('permissions.stats.sections').toLowerCase()}\r\n </div>\r\n )}\r\n </button>\r\n\r\n {expandedNodes.has(module.id) && module.sections.length > 0 && (\r\n <div className=\"bg-[var(--bg-primary)]\">\r\n {module.sections.map(section => (\r\n <div\r\n key={section.id}\r\n className=\"flex items-center gap-3 py-2 px-4 pl-36 text-sm\"\r\n >\r\n <div className=\"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-3 h-3 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-[var(--text-primary)]\">{section.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n {t('permissions.levels.section')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{section.permissionPath}</code>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface PermissionListRowProps {\r\n readonly permission: PermissionListDto;\r\n readonly navigate: (path: string) => void;\r\n}\r\n\r\nfunction PermissionListRow({ permission, navigate }: Readonly<PermissionListRowProps>) {\r\n return (\r\n <tr\r\n key={permission.id}\r\n onClick={() => navigate(`/administration/permissions/permissions/${permission.id}`)}\r\n className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <code className=\"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors\">{permission.path}</code>\r\n {permission.isWildcard && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n <Sparkles className=\"w-3 h-3\" />\r\n wildcard\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <span className=\"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium\">\r\n {permission.level}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell\">{permission.description || '-'}</td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]\">\r\n {permission.rolesCount}\r\n </span>\r\n <ExternalLink className=\"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity\" />\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n}\r\n\r\nexport function PermissionsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [tree, setTree] = useState<PermissionTreeDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState('');\r\n const [viewMode, setViewMode] = useState<'list' | 'tree'>('list');\r\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());\r\n\r\n const loadPermissions = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.permissions.getAll({ search: search || undefined });\r\n setPermissions(result);\r\n } catch (err) {\r\n console.error('Failed to load permissions:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [search]);\r\n\r\n const collectAllNodeIds = (tree: PermissionTreeDto): Set<string> => {\r\n const allIds = new Set<string>();\r\n (tree.applications ?? []).forEach(app => {\r\n allIds.add(app.id);\r\n (app.modules ?? []).forEach(mod => {\r\n allIds.add(mod.id);\r\n });\r\n });\r\n return allIds;\r\n };\r\n\r\n const loadTree = async () => {\r\n try {\r\n const result = await adminApi.permissions.getTree();\r\n setTree(result);\r\n const allIds = collectAllNodeIds(result);\r\n setExpandedNodes(allIds);\r\n } catch (err) {\r\n console.error('Failed to load permission tree:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadPermissions();\r\n loadTree();\r\n }, [loadPermissions]);\r\n\r\n const handleSearch = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n loadPermissions();\r\n };\r\n\r\n const toggleNode = (id: string) => {\r\n setExpandedNodes(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const countTreeStats = (tree: PermissionTreeDto) => {\r\n const apps = tree.applications ?? [];\r\n let modules = 0;\r\n let sections = 0;\r\n apps.forEach(app => {\r\n const mods = app.modules ?? [];\r\n modules += mods.length;\r\n mods.forEach(mod => {\r\n sections += (mod.sections ?? []).length;\r\n });\r\n });\r\n return { applications: apps.length, modules, sections };\r\n };\r\n\r\n const getStats = () => {\r\n if (!tree) return { applications: 0, modules: 0, sections: 0 };\r\n return countTreeStats(tree);\r\n };\r\n\r\n const stats = getStats();\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('permissions.title') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center\">\r\n <Shield className=\"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('permissions.title')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-0.5\">{t('permissions.subtitle')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]\">\r\n <button\r\n onClick={() => setViewMode('tree')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'tree'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <FolderTree className=\"w-4 h-4\" />\r\n {t('permissions.treeView')}\r\n </button>\r\n <button\r\n onClick={() => setViewMode('list')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'list'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n {t('permissions.listView')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Cards */}\r\n <div className=\"grid grid-cols-3 gap-4\">\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.applications}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.applications')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.modules}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.modules')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.sections}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.sections')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Search Bar (List View) */}\r\n {viewMode === 'list' && (\r\n <form onSubmit={handleSearch} className=\"flex gap-2\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]\" />\r\n <input\r\n type=\"text\"\r\n value={search}\r\n onChange={e => setSearch(e.target.value)}\r\n placeholder={t('common.search')}\r\n className=\"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all\"\r\n />\r\n </div>\r\n <button\r\n type=\"submit\"\r\n className=\"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors\"\r\n >\r\n {t('common.search')}\r\n </button>\r\n </form>\r\n )}\r\n\r\n {/* Tree View */}\r\n {viewMode === 'tree' ? (\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n {loading && (\r\n <div className=\"flex justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loading && tree?.applications?.length ? (\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {tree.applications.map(app => (\r\n <ApplicationTreeNode\r\n key={app.id}\r\n app={app}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n ) : !loading && (\r\n <div className=\"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noData')}</p>\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n /* List View */\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.path')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('permissions.columns.level')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('permissions.columns.description')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.roles')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <Loader2 className=\"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]\" />\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length === 0 && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noPermissions')}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length > 0 && (\r\n permissions.map(permission => (\r\n <PermissionListRow\r\n key={permission.id}\r\n permission={permission}\r\n navigate={navigate}\r\n />\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ApplicationTreeNode","app","expandedNodes","toggleNode","t","jsxs","jsx","ChevronDown","ChevronRight","LayoutGrid","module","ModuleTreeNode","Layers","section","FileCode","PermissionListRow","permission","navigate","Sparkles","ExternalLink","PermissionsPage","useTranslation","useNavigate","permissions","setPermissions","useState","tree","setTree","loading","setLoading","search","setSearch","viewMode","setViewMode","setExpandedNodes","loadPermissions","useCallback","result","adminApi","err","collectAllNodeIds","allIds","mod","loadTree","useEffect","handleSearch","e","id","prev","next","stats","apps","modules","sections","mods","Breadcrumb","Shield","FolderTree","List","Search","Loader2"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),r=require("react-i18next"),a=require("./index-
|
|
2
|
-
//# sourceMappingURL=PortalDashboardPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),r=require("react-i18next"),a=require("./index-IgLVXPg8.js");function o(){const{t:e}=r.useTranslation("navigation");return t.jsx(a.UnderDevelopment,{title:e("portal.title","Client Portal"),description:e("portal.description","View aggregated data from all your linked business workspaces.")})}exports.PortalDashboardPage=o;
|
|
2
|
+
//# sourceMappingURL=PortalDashboardPage-CoEC4CmC.js.map
|
package/dist/chunks/{PortalDashboardPage-DFBx38-x.js.map → PortalDashboardPage-CoEC4CmC.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PortalDashboardPage-
|
|
1
|
+
{"version":3,"file":"PortalDashboardPage-CoEC4CmC.js","sources":["../../src/pages/personal/myspace/PortalDashboardPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { UnderDevelopment } from '@/components/ui/UnderDevelopment';\r\n\r\nexport function PortalDashboardPage(): ReactElement {\r\n const { t } = useTranslation('navigation');\r\n\r\n return (\r\n <UnderDevelopment\r\n title={t('portal.title', 'Client Portal')}\r\n description={t('portal.description', 'View aggregated data from all your linked business workspaces.')}\r\n />\r\n );\r\n}\r\n"],"names":["PortalDashboardPage","t","useTranslation","jsx","UnderDevelopment"],"mappings":"iLAIO,SAASA,GAAoC,CAClD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAAA,eAAe,YAAY,EAEzC,OACEC,EAAAA,IAACC,EAAAA,iBAAA,CACC,MAAOH,EAAE,eAAgB,eAAe,EACxC,YAAaA,EAAE,qBAAsB,gEAAgE,CAAA,CAAA,CAG3G"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as o } from "react/jsx-runtime";
|
|
2
2
|
import { useTranslation as r } from "react-i18next";
|
|
3
|
-
import { F as e } from "./index-
|
|
3
|
+
import { F as e } from "./index-lpIzhufD.js";
|
|
4
4
|
function s() {
|
|
5
5
|
const { t } = r("navigation");
|
|
6
6
|
return /* @__PURE__ */ o(
|
|
@@ -14,4 +14,4 @@ function s() {
|
|
|
14
14
|
export {
|
|
15
15
|
s as PortalDashboardPage
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=PortalDashboardPage-
|
|
17
|
+
//# sourceMappingURL=PortalDashboardPage-DrYymEf-.js.map
|
package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js.map → PortalDashboardPage-DrYymEf-.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PortalDashboardPage-
|
|
1
|
+
{"version":3,"file":"PortalDashboardPage-DrYymEf-.js","sources":["../../src/pages/personal/myspace/PortalDashboardPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { UnderDevelopment } from '@/components/ui/UnderDevelopment';\r\n\r\nexport function PortalDashboardPage(): ReactElement {\r\n const { t } = useTranslation('navigation');\r\n\r\n return (\r\n <UnderDevelopment\r\n title={t('portal.title', 'Client Portal')}\r\n description={t('portal.description', 'View aggregated data from all your linked business workspaces.')}\r\n />\r\n );\r\n}\r\n"],"names":["PortalDashboardPage","useTranslation","jsx","UnderDevelopment"],"mappings":";;;AAIO,SAASA,IAAoC;AAClD,QAAM,EAAE,EAAA,IAAMC,EAAe,YAAY;AAEzC,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAO,EAAE,gBAAgB,eAAe;AAAA,MACxC,aAAa,EAAE,sBAAsB,gEAAgE;AAAA,IAAA;AAAA,EAAA;AAG3G;"}
|
|
@@ -5,7 +5,7 @@ import { u as be } from "./useTabNavigation-Bsbskz0i.js";
|
|
|
5
5
|
import { useTranslation as pe } from "react-i18next";
|
|
6
6
|
import * as ge from "lucide-react";
|
|
7
7
|
import { Palette as xe, Globe as ye, Bell as Ne, Star as V, Loader2 as O, Check as q, GripVertical as we, X as Se, Search as Ce } from "lucide-react";
|
|
8
|
-
import { aa as ke, a as Le, u as Re, a9 as Te, f as U, ab as De, ac as Fe } from "./index-
|
|
8
|
+
import { aa as ke, a as Le, u as Re, a9 as Te, f as U, ab as De, ac as Fe } from "./index-lpIzhufD.js";
|
|
9
9
|
const Ae = ["appearance", "language", "notifications", "favorites"];
|
|
10
10
|
function C({ name: i, className: m }) {
|
|
11
11
|
const l = ge[i];
|
|
@@ -412,4 +412,4 @@ function Be() {
|
|
|
412
412
|
export {
|
|
413
413
|
Be as PreferencesPage
|
|
414
414
|
};
|
|
415
|
-
//# sourceMappingURL=PreferencesPage-
|
|
415
|
+
//# sourceMappingURL=PreferencesPage-CJRaU3ba.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreferencesPage-BBu8yZQB.js","sources":["../../src/pages/personal/myspace/PreferencesPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { useTabNavigation } from '@/hooks/useTabNavigation';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Palette, Globe, Bell, Loader2, Check, Star, X, Search, GripVertical } from 'lucide-react';\r\nimport * as LucideIcons from 'lucide-react';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport { LanguageSwitcher } from '@/components/ui/LanguageSwitcher';\r\nimport { ThemeCustomizer } from '@/components/ui/ThemeCustomizer';\r\nimport { useTheme } from '@/contexts/ThemeContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useNavigation, type ModuleDto, type ApplicationDto } from '@/contexts/NavigationContext';\r\nimport { useFavoriteModules, type FavoriteModule } from '@/hooks/useFavoriteModules';\r\nimport { userApi } from '@/services/api/userApi';\r\n\r\nconst PREFERENCES_TABS = ['appearance', 'language', 'notifications', 'favorites'] as const;\r\ntype PreferencesTab = typeof PREFERENCES_TABS[number];\r\n\r\n// Dynamic icon component\r\nfunction DynamicIcon({ name, className }: { name: string; className?: string }) {\r\n const icons = LucideIcons as unknown as Record<string, LucideIcon>;\r\n const IconComponent = icons[name];\r\n if (!IconComponent) {\r\n return <Star className={className} />;\r\n }\r\n return <IconComponent className={className} />;\r\n}\r\n\r\nfunction getFavoriteButtonClass(isSelected: boolean, isDisabled: boolean): string {\r\n if (isSelected) return 'bg-[var(--accent-bg)] border-2 border-[var(--color-accent-500)]';\r\n if (isDisabled) return 'opacity-50 cursor-not-allowed bg-[var(--bg-tertiary)] border border-[var(--border-color)]';\r\n return 'bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)]';\r\n}\r\n\r\nexport function PreferencesPage(): ReactElement | null {\r\n const { t, i18n } = useTranslation(['navigation', 'common']);\r\n const navigate = useNavigate();\r\n const { activeTab, setActiveTab } = useTabNavigation<PreferencesTab>('appearance', PREFERENCES_TABS);\r\n const { loadFromServer, isSyncing, selectedThemeTenant } = useTheme();\r\n const { currentTenant, isLoading: tenantLoading } = useTenant();\r\n const { menu } = useNavigation();\r\n const { favorites, toggleFavorite, isFavorite, canAddMore, maxFavorites, reorderFavorites, loading: favoritesLoading } = useFavoriteModules();\r\n const [syncSuccess, setSyncSuccess] = useState(false);\r\n const [moduleSearch, setModuleSearch] = useState('');\r\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null);\r\n const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);\r\n const dragNodeRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const [emailNotifications, setEmailNotifications] = useState(true);\r\n const [securityAlerts, setSecurityAlerts] = useState(true);\r\n const [productUpdates, setProductUpdates] = useState(false);\r\n const [notificationsSaving, setNotificationsSaving] = useState(false);\r\n const [notificationsSaved, setNotificationsSaved] = useState(false);\r\n const notificationsSaveTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const isInitialLoadRef = useRef(true);\r\n\r\n // Wait for tenant context to be loaded before fetching preferences\r\n useEffect(() => {\r\n if (!tenantLoading && currentTenant) {\r\n loadPreferences();\r\n }\r\n }, [tenantLoading, currentTenant]);\r\n\r\n const loadPreferences = async () => {\r\n try {\r\n const prefs = await userApi.preferences.get();\r\n setEmailNotifications(prefs.emailNotifications);\r\n setSecurityAlerts(prefs.pushNotifications);\r\n isInitialLoadRef.current = false;\r\n } catch {\r\n isInitialLoadRef.current = false;\r\n }\r\n };\r\n\r\n const saveNotifications = useCallback(async () => {\r\n setNotificationsSaving(true);\r\n setNotificationsSaved(false);\r\n try {\r\n await userApi.preferences.updateNotifications({\r\n emailNotifications,\r\n pushNotifications: securityAlerts,\r\n });\r\n setNotificationsSaved(true);\r\n setTimeout(() => setNotificationsSaved(false), 2000);\r\n } catch {\r\n console.error('[PreferencesPage] Failed to save notifications');\r\n } finally {\r\n setNotificationsSaving(false);\r\n }\r\n }, [emailNotifications, securityAlerts]);\r\n\r\n useEffect(() => {\r\n if (isInitialLoadRef.current) return;\r\n\r\n if (notificationsSaveTimeoutRef.current) {\r\n clearTimeout(notificationsSaveTimeoutRef.current);\r\n }\r\n\r\n notificationsSaveTimeoutRef.current = setTimeout(() => {\r\n saveNotifications();\r\n }, 1000);\r\n\r\n return () => {\r\n if (notificationsSaveTimeoutRef.current) {\r\n clearTimeout(notificationsSaveTimeoutRef.current);\r\n }\r\n };\r\n }, [emailNotifications, securityAlerts, saveNotifications]);\r\n\r\n const handleSync = async () => {\r\n // Determine which scope to sync based on selectedThemeTenant\r\n // null = global scope, string = tenant scope\r\n const scope = selectedThemeTenant === null ? 'global' : 'tenant';\r\n setSyncSuccess(false);\r\n try {\r\n await loadFromServer(scope);\r\n await loadPreferences();\r\n setSyncSuccess(true);\r\n setTimeout(() => setSyncSuccess(false), 3000);\r\n } catch (error) {\r\n console.error('[PreferencesPage] Sync failed:', error);\r\n }\r\n };\r\n\r\n const tabs = [\r\n { id: 'appearance' as const, label: 'Apparence', icon: Palette, description: 'Personnaliser le thème et les couleurs' },\r\n { id: 'language' as const, label: 'Langue', icon: Globe, description: 'Changer la langue de l\\'interface' },\r\n { id: 'notifications' as const, label: 'Notifications', icon: Bell, description: 'Gérer les notifications' },\r\n { id: 'favorites' as const, label: t('common:favorites.quickAccess'), icon: Star, description: 'Gérer vos modules favoris' },\r\n ];\r\n\r\n // Gather all modules grouped by application for favorites\r\n const modulesByApp: { app: ApplicationDto; modules: ModuleDto[] }[] = [];\r\n menu?.applications.forEach(app => {\r\n if ((app.modules?.length ?? 0) > 0) {\r\n modulesByApp.push({\r\n app,\r\n modules: app.modules,\r\n });\r\n }\r\n });\r\n\r\n const handleToggleFavorite = (module: ModuleDto, app: ApplicationDto) => {\r\n const favoriteModule: FavoriteModule = {\r\n id: module.id,\r\n code: module.code,\r\n label: module.label,\r\n icon: module.icon || 'Star',\r\n route: `/${app.code}/${module.code}`,\r\n applicationCode: app.code,\r\n applicationLabel: app.label,\r\n };\r\n toggleFavorite(favoriteModule);\r\n };\r\n\r\n const handleFavoriteClick = (module: FavoriteModule) => {\r\n if (module.route) {\r\n navigate(module.route);\r\n }\r\n };\r\n\r\n // Drag and drop handlers for reordering\r\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>, index: number) => {\r\n setDraggedIndex(index);\r\n dragNodeRef.current = e.currentTarget;\r\n e.dataTransfer.effectAllowed = 'move';\r\n e.dataTransfer.setData('text/plain', index.toString());\r\n // Add a slight delay to allow the drag image to be created before adding opacity\r\n setTimeout(() => {\r\n if (dragNodeRef.current) {\r\n dragNodeRef.current.style.opacity = '0.4';\r\n }\r\n }, 0);\r\n };\r\n\r\n const handleDragEnd = () => {\r\n if (dragNodeRef.current) {\r\n dragNodeRef.current.style.opacity = '1';\r\n }\r\n setDraggedIndex(null);\r\n setDragOverIndex(null);\r\n dragNodeRef.current = null;\r\n };\r\n\r\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>, index: number) => {\r\n e.preventDefault();\r\n e.dataTransfer.dropEffect = 'move';\r\n if (index !== draggedIndex) {\r\n setDragOverIndex(index);\r\n }\r\n };\r\n\r\n const handleDragLeave = () => {\r\n setDragOverIndex(null);\r\n };\r\n\r\n const handleDrop = (e: React.DragEvent<HTMLDivElement>, dropIndex: number) => {\r\n e.preventDefault();\r\n const dragIndex = draggedIndex;\r\n if (dragIndex === null || dragIndex === dropIndex) return;\r\n\r\n const newFavorites = [...favorites];\r\n const [draggedItem] = newFavorites.splice(dragIndex, 1);\r\n newFavorites.splice(dropIndex, 0, draggedItem);\r\n\r\n reorderFavorites(newFavorites);\r\n handleDragEnd();\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('navigation:sidebar.preferences')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-1\">Personnalisez votre expérience SmartStack</p>\r\n </div>\r\n\r\n {/* Tab Navigation */}\r\n <div className=\"border-b border-[var(--item-color-border)]\">\r\n <nav className=\"flex gap-1\" aria-label=\"Tabs\">\r\n {tabs.map((tab) => {\r\n const Icon = tab.icon;\r\n return (\r\n <button\r\n key={tab.id}\r\n onClick={() => setActiveTab(tab.id)}\r\n className={`flex items-center gap-2 px-4 py-3 text-sm font-medium transition-all border-b-2 ${\r\n activeTab === tab.id\r\n ? 'border-[var(--color-accent-500)] text-[var(--color-accent-600)] bg-[var(--accent-bg)]'\r\n : 'border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n style={{ borderRadius: 'var(--radius-button) var(--radius-button) 0 0' }}\r\n >\r\n <Icon className=\"w-5 h-5\" />\r\n <span>{tab.label}</span>\r\n </button>\r\n );\r\n })}\r\n </nav>\r\n </div>\r\n\r\n {/* Tab Content */}\r\n <div\r\n className=\"bg-[var(--bg-card)] border border-[var(--item-color-border)] p-6\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n {activeTab === 'appearance' && (\r\n <div className=\"space-y-4\">\r\n <ThemeCustomizer\r\n onSync={handleSync}\r\n isSyncing={isSyncing}\r\n syncSuccess={syncSuccess}\r\n />\r\n </div>\r\n )}\r\n\r\n {activeTab === 'language' && (\r\n <div className=\"space-y-6\">\r\n <div>\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">Langue</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Sélectionnez la langue de l'interface\r\n </p>\r\n </div>\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">\r\n {i18n.language?.startsWith('fr') ? 'Français' : 'English'}\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Langue actuelle de l'interface\r\n </p>\r\n </div>\r\n <LanguageSwitcher />\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {activeTab === 'notifications' && (\r\n <div className=\"space-y-6\">\r\n <div className=\"flex items-start justify-between\">\r\n <div>\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">Notifications</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Gérez vos préférences de notifications\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs text-[var(--text-muted)]\">\r\n {notificationsSaving && (\r\n <>\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n <span>Sauvegarde...</span>\r\n </>\r\n )}\r\n {notificationsSaved && !notificationsSaving && (\r\n <>\r\n <Check className=\"w-3 h-3 text-green-500\" />\r\n <span className=\"text-green-600\">Sauvegardé</span>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"space-y-4\">\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Notifications par email</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Recevoir des notifications par email\r\n </p>\r\n </div>\r\n <label className=\"relative inline-flex items-center cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n className=\"sr-only peer\"\r\n checked={emailNotifications}\r\n onChange={(e) => setEmailNotifications(e.target.checked)}\r\n />\r\n <div\r\n className=\"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <span className=\"after:rounded-full\" />\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Alertes de sécurité</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Être notifié des événements de sécurité\r\n </p>\r\n </div>\r\n <label className=\"relative inline-flex items-center cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n className=\"sr-only peer\"\r\n checked={securityAlerts}\r\n onChange={(e) => setSecurityAlerts(e.target.checked)}\r\n />\r\n <div\r\n className=\"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <span className=\"after:rounded-full\" />\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Mises à jour produit</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Nouvelles fonctionnalités et améliorations\r\n </p>\r\n </div>\r\n <label className=\"relative inline-flex items-center cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n className=\"sr-only peer\"\r\n checked={productUpdates}\r\n onChange={(e) => setProductUpdates(e.target.checked)}\r\n />\r\n <div\r\n className=\"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <span className=\"after:rounded-full\" />\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {activeTab === 'favorites' && (\r\n <div className=\"space-y-6\">\r\n <div>\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">{t('common:favorites.quickAccess')}</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n {t('common:favorites.selectModules', { count: favorites.length, max: maxFavorites })}\r\n </p>\r\n </div>\r\n\r\n {favoritesLoading && (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"w-6 h-6 animate-spin text-[var(--color-accent-500)]\" />\r\n <span className=\"ml-2 text-[var(--text-secondary)]\">Chargement des favoris...</span>\r\n </div>\r\n )}\r\n\r\n {!favoritesLoading && (\r\n <>\r\n\r\n {/* Current Favorites */}\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Vos favoris actuels</h3>\r\n {favorites.length > 1 && (\r\n <span className=\"text-xs text-[var(--text-muted)]\">Glissez pour réorganiser</span>\r\n )}\r\n </div>\r\n {favorites.length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-secondary)]\">Aucun favori sélectionné</p>\r\n ) : (\r\n <div className=\"flex flex-col gap-2\">\r\n {favorites.map((module, index) => (\r\n <div\r\n key={module.id}\r\n draggable\r\n onDragStart={(e) => handleDragStart(e, index)}\r\n onDragEnd={handleDragEnd}\r\n onDragOver={(e) => handleDragOver(e, index)}\r\n onDragLeave={handleDragLeave}\r\n onDrop={(e) => handleDrop(e, index)}\r\n className={`flex items-center gap-2 px-3 py-2 bg-[var(--accent-bg)] border text-[var(--color-accent-500)] cursor-grab active:cursor-grabbing transition-all ${\r\n dragOverIndex === index\r\n ? 'border-[var(--color-accent-500)] border-2 scale-[1.02]'\r\n : 'border-[var(--color-accent-500)]/50'\r\n }`}\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <GripVertical className=\"w-4 h-4 text-[var(--color-accent-400)] flex-shrink-0\" />\r\n <span className=\"text-xs text-[var(--color-accent-500)] font-mono w-4\">{index + 1}</span>\r\n <button\r\n onClick={() => handleFavoriteClick(module)}\r\n className=\"flex items-center gap-2 hover:underline flex-1\"\r\n >\r\n <DynamicIcon name={module.icon} className=\"w-4 h-4\" />\r\n <span className=\"text-sm font-medium\">{module.label}</span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">({module.applicationLabel})</span>\r\n </button>\r\n <button\r\n onClick={() => toggleFavorite(module)}\r\n className=\"p-1 hover:bg-[var(--bg-tertiary)] rounded flex-shrink-0\"\r\n title=\"Retirer des favoris\"\r\n >\r\n <X className=\"w-3.5 h-3.5\" />\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Available Modules */}\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Modules disponibles</h3>\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder=\"Rechercher un module...\"\r\n value={moduleSearch}\r\n onChange={(e) => setModuleSearch(e.target.value)}\r\n className=\"pl-9 pr-3 py-2 w-64 bg-[var(--bg-primary)] border border-[var(--border-color)] text-sm focus:outline-none focus:border-[var(--color-accent-500)]\"\r\n style={{ borderRadius: 'var(--radius-input)' }}\r\n />\r\n </div>\r\n </div>\r\n {modulesByApp.map(({ app, modules }) => {\r\n // Filter modules based on search\r\n const filteredModules = moduleSearch\r\n ? modules.filter(m =>\r\n m.label.toLowerCase().includes(moduleSearch.toLowerCase()) ||\r\n m.code.toLowerCase().includes(moduleSearch.toLowerCase()) ||\r\n app.label.toLowerCase().includes(moduleSearch.toLowerCase())\r\n )\r\n : modules;\r\n\r\n // Don't render app section if no modules match\r\n if (filteredModules.length === 0) return null;\r\n\r\n return (\r\n <div\r\n key={app.id}\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <DynamicIcon name={app.icon || 'Folder'} className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n <span className=\"font-medium text-[var(--text-primary)]\">{app.label}</span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">({filteredModules.length} module{filteredModules.length > 1 ? 's' : ''})</span>\r\n </div>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2\">\r\n {filteredModules.map((module) => {\r\n const isSelected = isFavorite(module.id);\r\n const isDisabled = !isSelected && !canAddMore;\r\n\r\n return (\r\n <button\r\n key={module.id}\r\n onClick={() => handleToggleFavorite(module, app)}\r\n disabled={isDisabled}\r\n className={`flex items-center gap-3 p-3 transition-all ${\r\n getFavoriteButtonClass(isSelected, isDisabled)\r\n }`}\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <div className={`w-8 h-8 flex items-center justify-center ${\r\n isSelected\r\n ? 'bg-[var(--color-accent-600)] text-white'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)]'\r\n }`} style={{ borderRadius: 'var(--radius-button)' }}>\r\n <DynamicIcon name={module.icon || 'Star'} className=\"w-4 h-4\" />\r\n </div>\r\n <span className={`text-sm ${\r\n isSelected ? 'font-medium text-[var(--color-accent-500)]' : 'text-[var(--text-primary)]'\r\n }`}>\r\n {module.label}\r\n </span>\r\n {isSelected && (\r\n <Check className=\"w-4 h-4 text-[var(--color-accent-500)] ml-auto\" />\r\n )}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n })}\r\n\r\n {(modulesByApp.length === 0 || (moduleSearch && modulesByApp.every(({ modules }) =>\r\n !modules.some(m =>\r\n m.label.toLowerCase().includes(moduleSearch.toLowerCase()) ||\r\n m.code.toLowerCase().includes(moduleSearch.toLowerCase())\r\n )\r\n ))) && (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n {moduleSearch ? `Aucun module trouvé pour \"${moduleSearch}\"` : t('common:favorites.noModules')}\r\n </div>\r\n )}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["PREFERENCES_TABS","DynamicIcon","name","className","IconComponent","LucideIcons","jsx","Star","getFavoriteButtonClass","isSelected","isDisabled","PreferencesPage","t","i18n","useTranslation","navigate","useNavigate","activeTab","setActiveTab","useTabNavigation","loadFromServer","isSyncing","selectedThemeTenant","useTheme","currentTenant","tenantLoading","useTenant","menu","useNavigation","favorites","toggleFavorite","isFavorite","canAddMore","maxFavorites","reorderFavorites","favoritesLoading","useFavoriteModules","syncSuccess","setSyncSuccess","useState","moduleSearch","setModuleSearch","draggedIndex","setDraggedIndex","dragOverIndex","setDragOverIndex","dragNodeRef","useRef","emailNotifications","setEmailNotifications","securityAlerts","setSecurityAlerts","productUpdates","setProductUpdates","notificationsSaving","setNotificationsSaving","notificationsSaved","setNotificationsSaved","notificationsSaveTimeoutRef","isInitialLoadRef","useEffect","loadPreferences","prefs","userApi","saveNotifications","useCallback","handleSync","scope","error","tabs","Palette","Globe","Bell","modulesByApp","app","handleToggleFavorite","module","favoriteModule","handleFavoriteClick","handleDragStart","e","index","handleDragEnd","handleDragOver","handleDragLeave","handleDrop","dropIndex","dragIndex","newFavorites","draggedItem","jsxs","tab","Icon","ThemeCustomizer","LanguageSwitcher","Fragment","Loader2","Check","GripVertical","X","Search","modules","filteredModules","m"],"mappings":";;;;;;;;AAgBA,MAAMA,KAAmB,CAAC,cAAc,YAAY,iBAAiB,WAAW;AAIhF,SAASC,EAAY,EAAE,MAAAC,GAAM,WAAAC,KAAmD;AAE9E,QAAMC,IADQC,GACcH,CAAI;AAChC,SAAKE,IAGE,gBAAAE,EAACF,KAAc,WAAAD,GAAsB,IAFnC,gBAAAG,EAACC,KAAK,WAAAJ,GAAsB;AAGvC;AAEA,SAASK,GAAuBC,GAAqBC,GAA6B;AAChF,SAAID,IAAmB,oEACnBC,IAAmB,8FAChB;AACT;AAEO,SAASC,KAAuC;AACrD,QAAM,EAAE,GAAAC,GAAG,MAAAC,EAAA,IAASC,GAAe,CAAC,cAAc,QAAQ,CAAC,GACrDC,IAAWC,GAAA,GACX,EAAE,WAAAC,GAAW,cAAAC,EAAA,IAAiBC,GAAiC,cAAcnB,EAAgB,GAC7F,EAAE,gBAAAoB,GAAgB,WAAAC,GAAW,qBAAAC,EAAA,IAAwBC,GAAA,GACrD,EAAE,eAAAC,GAAe,WAAWC,EAAA,IAAkBC,GAAA,GAC9C,EAAE,MAAAC,EAAA,IAASC,GAAA,GACX,EAAE,WAAAC,GAAW,gBAAAC,GAAgB,YAAAC,GAAY,YAAAC,GAAY,cAAAC,GAAc,kBAAAC,GAAkB,SAASC,EAAA,IAAqBC,GAAA,GACnH,CAACC,IAAaC,CAAc,IAAIC,EAAS,EAAK,GAC9C,CAACC,GAAcC,EAAe,IAAIF,EAAS,EAAE,GAC7C,CAACG,GAAcC,CAAe,IAAIJ,EAAwB,IAAI,GAC9D,CAACK,IAAeC,CAAgB,IAAIN,EAAwB,IAAI,GAChEO,IAAcC,EAA8B,IAAI,GAEhD,CAACC,GAAoBC,CAAqB,IAAIV,EAAS,EAAI,GAC3D,CAACW,GAAgBC,CAAiB,IAAIZ,EAAS,EAAI,GACnD,CAACa,IAAgBC,EAAiB,IAAId,EAAS,EAAK,GACpD,CAACe,GAAqBC,CAAsB,IAAIhB,EAAS,EAAK,GAC9D,CAACiB,IAAoBC,CAAqB,IAAIlB,EAAS,EAAK,GAC5DmB,IAA8BX,EAA6C,IAAI,GAC/EY,IAAmBZ,EAAO,EAAI;AAGpC,EAAAa,EAAU,MAAM;AACd,IAAI,CAACnC,KAAiBD,KACpBqC,EAAA;AAAA,EAEJ,GAAG,CAACpC,GAAeD,CAAa,CAAC;AAEjC,QAAMqC,IAAkB,YAAY;AAClC,QAAI;AACF,YAAMC,IAAQ,MAAMC,EAAQ,YAAY,IAAA;AACxC,MAAAd,EAAsBa,EAAM,kBAAkB,GAC9CX,EAAkBW,EAAM,iBAAiB,GACzCH,EAAiB,UAAU;AAAA,IAC7B,QAAQ;AACN,MAAAA,EAAiB,UAAU;AAAA,IAC7B;AAAA,EACF,GAEMK,IAAoBC,GAAY,YAAY;AAChD,IAAAV,EAAuB,EAAI,GAC3BE,EAAsB,EAAK;AAC3B,QAAI;AACF,YAAMM,EAAQ,YAAY,oBAAoB;AAAA,QAC5C,oBAAAf;AAAA,QACA,mBAAmBE;AAAA,MAAA,CACpB,GACDO,EAAsB,EAAI,GAC1B,WAAW,MAAMA,EAAsB,EAAK,GAAG,GAAI;AAAA,IACrD,QAAQ;AACN,cAAQ,MAAM,gDAAgD;AAAA,IAChE,UAAA;AACE,MAAAF,EAAuB,EAAK;AAAA,IAC9B;AAAA,EACF,GAAG,CAACP,GAAoBE,CAAc,CAAC;AAEvC,EAAAU,EAAU,MAAM;AACd,QAAI,CAAAD,EAAiB;AAErB,aAAID,EAA4B,WAC9B,aAAaA,EAA4B,OAAO,GAGlDA,EAA4B,UAAU,WAAW,MAAM;AACrD,QAAAM,EAAA;AAAA,MACF,GAAG,GAAI,GAEA,MAAM;AACX,QAAIN,EAA4B,WAC9B,aAAaA,EAA4B,OAAO;AAAA,MAEpD;AAAA,EACF,GAAG,CAACV,GAAoBE,GAAgBc,CAAiB,CAAC;AAE1D,QAAME,KAAa,YAAY;AAG7B,UAAMC,IAAQ7C,MAAwB,OAAO,WAAW;AACxD,IAAAgB,EAAe,EAAK;AACpB,QAAI;AACF,YAAMlB,EAAe+C,CAAK,GAC1B,MAAMN,EAAA,GACNvB,EAAe,EAAI,GACnB,WAAW,MAAMA,EAAe,EAAK,GAAG,GAAI;AAAA,IAC9C,SAAS8B,GAAO;AACd,cAAQ,MAAM,kCAAkCA,CAAK;AAAA,IACvD;AAAA,EACF,GAEMC,KAAO;AAAA,IACX,EAAE,IAAI,cAAuB,OAAO,aAAa,MAAMC,IAAS,aAAa,yCAAA;AAAA,IAC7E,EAAE,IAAI,YAAqB,OAAO,UAAU,MAAMC,IAAO,aAAa,mCAAA;AAAA,IACtE,EAAE,IAAI,iBAA0B,OAAO,iBAAiB,MAAMC,IAAM,aAAa,0BAAA;AAAA,IACjF,EAAE,IAAI,aAAsB,OAAO5D,EAAE,8BAA8B,GAAG,MAAML,GAAM,aAAa,4BAAA;AAAA,EAA4B,GAIvHkE,IAAgE,CAAA;AACtE,EAAA9C,GAAM,aAAa,QAAQ,CAAA+C,MAAO;AAChC,KAAKA,EAAI,SAAS,UAAU,KAAK,KAC/BD,EAAa,KAAK;AAAA,MAChB,KAAAC;AAAA,MACA,SAASA,EAAI;AAAA,IAAA,CACd;AAAA,EAEL,CAAC;AAED,QAAMC,KAAuB,CAACC,GAAmBF,MAAwB;AACvE,UAAMG,IAAiC;AAAA,MACrC,IAAID,EAAO;AAAA,MACX,MAAMA,EAAO;AAAA,MACb,OAAOA,EAAO;AAAA,MACd,MAAMA,EAAO,QAAQ;AAAA,MACrB,OAAO,IAAIF,EAAI,IAAI,IAAIE,EAAO,IAAI;AAAA,MAClC,iBAAiBF,EAAI;AAAA,MACrB,kBAAkBA,EAAI;AAAA,IAAA;AAExB,IAAA5C,EAAe+C,CAAc;AAAA,EAC/B,GAEMC,KAAsB,CAACF,MAA2B;AACtD,IAAIA,EAAO,SACT7D,EAAS6D,EAAO,KAAK;AAAA,EAEzB,GAGMG,KAAkB,CAACC,GAAoCC,MAAkB;AAC7E,IAAAtC,EAAgBsC,CAAK,GACrBnC,EAAY,UAAUkC,EAAE,eACxBA,EAAE,aAAa,gBAAgB,QAC/BA,EAAE,aAAa,QAAQ,cAAcC,EAAM,UAAU,GAErD,WAAW,MAAM;AACf,MAAInC,EAAY,YACdA,EAAY,QAAQ,MAAM,UAAU;AAAA,IAExC,GAAG,CAAC;AAAA,EACN,GAEMoC,IAAgB,MAAM;AAC1B,IAAIpC,EAAY,YACdA,EAAY,QAAQ,MAAM,UAAU,MAEtCH,EAAgB,IAAI,GACpBE,EAAiB,IAAI,GACrBC,EAAY,UAAU;AAAA,EACxB,GAEMqC,KAAiB,CAACH,GAAoCC,MAAkB;AAC5E,IAAAD,EAAE,eAAA,GACFA,EAAE,aAAa,aAAa,QACxBC,MAAUvC,KACZG,EAAiBoC,CAAK;AAAA,EAE1B,GAEMG,KAAkB,MAAM;AAC5B,IAAAvC,EAAiB,IAAI;AAAA,EACvB,GAEMwC,KAAa,CAACL,GAAoCM,MAAsB;AAC5E,IAAAN,EAAE,eAAA;AACF,UAAMO,IAAY7C;AAClB,QAAI6C,MAAc,QAAQA,MAAcD,EAAW;AAEnD,UAAME,IAAe,CAAC,GAAG3D,CAAS,GAC5B,CAAC4D,CAAW,IAAID,EAAa,OAAOD,GAAW,CAAC;AACtD,IAAAC,EAAa,OAAOF,GAAW,GAAGG,CAAW,GAE7CvD,EAAiBsD,CAAY,GAC7BN,EAAA;AAAA,EACF;AAEA,SACE,gBAAAQ,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,MAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,iDAAiD,UAAAM,EAAE,gCAAgC,GAAE;AAAA,MACnG,gBAAAN,EAAC,KAAA,EAAE,WAAU,qCAAoC,UAAA,4CAAA,CAAyC;AAAA,IAAA,GAC5F;AAAA,IAGA,gBAAAA,EAAC,OAAA,EAAI,WAAU,8CACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,cAAa,cAAW,QACpC,UAAA+D,GAAK,IAAI,CAACsB,MAAQ;AACjB,YAAMC,IAAOD,EAAI;AACjB,aACE,gBAAAD;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,SAAS,MAAMxE,EAAayE,EAAI,EAAE;AAAA,UAClC,WAAW,mFACT1E,MAAc0E,EAAI,KACd,0FACA,6GACN;AAAA,UACA,OAAO,EAAE,cAAc,gDAAA;AAAA,UAEvB,UAAA;AAAA,YAAA,gBAAArF,EAACsF,GAAA,EAAK,WAAU,UAAA,CAAU;AAAA,YAC1B,gBAAAtF,EAAC,QAAA,EAAM,UAAAqF,EAAI,MAAA,CAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAVZA,EAAI;AAAA,MAAA;AAAA,IAaf,CAAC,GACH,GACF;AAAA,IAGA,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,cAAc,qBAAA;AAAA,QAEtB,UAAA;AAAA,UAAAzE,MAAc,gBACb,gBAAAX,EAAC,OAAA,EAAI,WAAU,aACb,UAAA,gBAAAA;AAAA,YAACuF;AAAA,YAAA;AAAA,cACC,QAAQ3B;AAAA,cACR,WAAA7C;AAAA,cACA,aAAAgB;AAAA,YAAA;AAAA,UAAA,GAEJ;AAAA,UAGDpB,MAAc,cACb,gBAAAyE,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,cAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,gDAA+C,UAAA,UAAM;AAAA,cACnE,gBAAAA,EAAC,KAAA,EAAE,WAAU,6CAA4C,UAAA,wCAAA,CAEzD;AAAA,YAAA,GACF;AAAA,YACA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,cAAc,qBAAA;AAAA,gBAEvB,UAAA,gBAAAoF,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,kBAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,oBAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,4CACX,UAAAO,EAAK,UAAU,WAAW,IAAI,IAAI,aAAa,UAAA,CAClD;AAAA,oBACA,gBAAAP,EAAC,KAAA,EAAE,WAAU,6CAA4C,UAAA,iCAAA,CAEzD;AAAA,kBAAA,GACF;AAAA,oCACCwF,IAAA,CAAA,CAAiB;AAAA,gBAAA,EAAA,CACpB;AAAA,cAAA;AAAA,YAAA;AAAA,UACF,GACF;AAAA,UAGD7E,MAAc,mBACb,gBAAAyE,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,cAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,gBAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,gDAA+C,UAAA,iBAAa;AAAA,gBAC1E,gBAAAA,EAAC,KAAA,EAAE,WAAU,6CAA4C,UAAA,yCAAA,CAEzD;AAAA,cAAA,GACF;AAAA,cACA,gBAAAoF,EAAC,OAAA,EAAI,WAAU,4DACZ,UAAA;AAAA,gBAAApC,KACC,gBAAAoC,EAAAK,GAAA,EACE,UAAA;AAAA,kBAAA,gBAAAzF,EAAC0F,GAAA,EAAQ,WAAU,uBAAA,CAAuB;AAAA,kBAC1C,gBAAA1F,EAAC,UAAK,UAAA,gBAAA,CAAa;AAAA,gBAAA,GACrB;AAAA,gBAEDkD,MAAsB,CAACF,KACtB,gBAAAoC,EAAAK,GAAA,EACE,UAAA;AAAA,kBAAA,gBAAAzF,EAAC2F,GAAA,EAAM,WAAU,yBAAA,CAAyB;AAAA,kBAC1C,gBAAA3F,EAAC,QAAA,EAAK,WAAU,kBAAiB,UAAA,aAAA,CAAU;AAAA,gBAAA,EAAA,CAC7C;AAAA,cAAA,EAAA,CAEJ;AAAA,YAAA,GACF;AAAA,YACA,gBAAAoF,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,cAAA,gBAAApF;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,cAAc,qBAAA;AAAA,kBAEvB,UAAA,gBAAAoF,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,oBAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,sBAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,4CAA2C,UAAA,2BAAuB;AAAA,sBAChF,gBAAAA,EAAC,KAAA,EAAE,WAAU,6CAA4C,UAAA,uCAAA,CAEzD;AAAA,oBAAA,GACF;AAAA,oBACA,gBAAAoF,EAAC,SAAA,EAAM,WAAU,oDACf,UAAA;AAAA,sBAAA,gBAAApF;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,MAAK;AAAA,0BACL,WAAU;AAAA,0BACV,SAAS0C;AAAA,0BACT,UAAU,CAACgC,MAAM/B,EAAsB+B,EAAE,OAAO,OAAO;AAAA,wBAAA;AAAA,sBAAA;AAAA,sBAEzD,gBAAA1E;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,WAAU;AAAA,0BACV,OAAO,EAAE,cAAc,uBAAA;AAAA,0BAEvB,UAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,qBAAA,CAAqB;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACvC,EAAA,CACF;AAAA,kBAAA,EAAA,CACF;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGF,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,cAAc,qBAAA;AAAA,kBAEvB,UAAA,gBAAAoF,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,oBAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,sBAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,4CAA2C,UAAA,uBAAmB;AAAA,sBAC5E,gBAAAA,EAAC,KAAA,EAAE,WAAU,6CAA4C,UAAA,0CAAA,CAEzD;AAAA,oBAAA,GACF;AAAA,oBACA,gBAAAoF,EAAC,SAAA,EAAM,WAAU,oDACf,UAAA;AAAA,sBAAA,gBAAApF;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,MAAK;AAAA,0BACL,WAAU;AAAA,0BACV,SAAS4C;AAAA,0BACT,UAAU,CAAC8B,MAAM7B,EAAkB6B,EAAE,OAAO,OAAO;AAAA,wBAAA;AAAA,sBAAA;AAAA,sBAErD,gBAAA1E;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,WAAU;AAAA,0BACV,OAAO,EAAE,cAAc,uBAAA;AAAA,0BAEvB,UAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,qBAAA,CAAqB;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACvC,EAAA,CACF;AAAA,kBAAA,EAAA,CACF;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGF,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,cAAc,qBAAA;AAAA,kBAEvB,UAAA,gBAAAoF,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,oBAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,sBAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,4CAA2C,UAAA,wBAAoB;AAAA,sBAC7E,gBAAAA,EAAC,KAAA,EAAE,WAAU,6CAA4C,UAAA,6CAAA,CAEzD;AAAA,oBAAA,GACF;AAAA,oBACA,gBAAAoF,EAAC,SAAA,EAAM,WAAU,oDACf,UAAA;AAAA,sBAAA,gBAAApF;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,MAAK;AAAA,0BACL,WAAU;AAAA,0BACV,SAAS8C;AAAA,0BACT,UAAU,CAAC4B,MAAM3B,GAAkB2B,EAAE,OAAO,OAAO;AAAA,wBAAA;AAAA,sBAAA;AAAA,sBAErD,gBAAA1E;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,WAAU;AAAA,0BACV,OAAO,EAAE,cAAc,uBAAA;AAAA,0BAEvB,UAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,qBAAA,CAAqB;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACvC,EAAA,CACF;AAAA,kBAAA,EAAA,CACF;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF,EAAA,CACF;AAAA,UAAA,GACF;AAAA,UAGDW,MAAc,eACb,gBAAAyE,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,cAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,gDAAgD,UAAAM,EAAE,8BAA8B,GAAE;AAAA,cAChG,gBAAAN,EAAC,KAAA,EAAE,WAAU,6CACV,UAAAM,EAAE,kCAAkC,EAAE,OAAOiB,EAAU,QAAQ,KAAKI,EAAA,CAAc,EAAA,CACrF;AAAA,YAAA,GACF;AAAA,YAECE,KACC,gBAAAuD,EAAC,OAAA,EAAI,WAAU,yCACb,UAAA;AAAA,cAAA,gBAAApF,EAAC0F,GAAA,EAAQ,WAAU,sDAAA,CAAsD;AAAA,cACzE,gBAAA1F,EAAC,QAAA,EAAK,WAAU,qCAAoC,UAAA,4BAAA,CAAyB;AAAA,YAAA,GAC/E;AAAA,YAGD,CAAC6B,KACA,gBAAAuD,EAAAK,GAAA,EAGF,UAAA;AAAA,cAAA,gBAAAL;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO,EAAE,cAAc,qBAAA;AAAA,kBAEvB,UAAA;AAAA,oBAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,sBAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,4CAA2C,UAAA,uBAAmB;AAAA,sBAC3EuB,EAAU,SAAS,uBACjB,QAAA,EAAK,WAAU,oCAAmC,UAAA,2BAAA,CAAwB;AAAA,oBAAA,GAE/E;AAAA,oBACCA,EAAU,WAAW,IACpB,gBAAAvB,EAAC,KAAA,EAAE,WAAU,wCAAuC,UAAA,2BAAA,CAAwB,IAE5E,gBAAAA,EAAC,SAAI,WAAU,uBACZ,YAAU,IAAI,CAACsE,GAAQK,MACtB,gBAAAS;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBAEC,WAAS;AAAA,wBACT,aAAa,CAACV,MAAMD,GAAgBC,GAAGC,CAAK;AAAA,wBAC5C,WAAWC;AAAA,wBACX,YAAY,CAACF,MAAMG,GAAeH,GAAGC,CAAK;AAAA,wBAC1C,aAAaG;AAAA,wBACb,QAAQ,CAACJ,MAAMK,GAAWL,GAAGC,CAAK;AAAA,wBAClC,WAAW,mJACTrC,OAAkBqC,IACd,2DACA,qCACN;AAAA,wBACA,OAAO,EAAE,cAAc,uBAAA;AAAA,wBAEvB,UAAA;AAAA,0BAAA,gBAAA3E,EAAC4F,IAAA,EAAa,WAAU,uDAAA,CAAuD;AAAA,0BAC/E,gBAAA5F,EAAC,QAAA,EAAK,WAAU,wDAAwD,cAAQ,GAAE;AAAA,0BAClF,gBAAAoF;AAAA,4BAAC;AAAA,4BAAA;AAAA,8BACC,SAAS,MAAMZ,GAAoBF,CAAM;AAAA,8BACzC,WAAU;AAAA,8BAEV,UAAA;AAAA,gCAAA,gBAAAtE,EAACL,GAAA,EAAY,MAAM2E,EAAO,MAAM,WAAU,WAAU;AAAA,gCACpD,gBAAAtE,EAAC,QAAA,EAAK,WAAU,uBAAuB,YAAO,OAAM;AAAA,gCACpD,gBAAAoF,EAAC,QAAA,EAAK,WAAU,oCAAmC,UAAA;AAAA,kCAAA;AAAA,kCAAEd,EAAO;AAAA,kCAAiB;AAAA,gCAAA,EAAA,CAAC;AAAA,8BAAA;AAAA,4BAAA;AAAA,0BAAA;AAAA,0BAEhF,gBAAAtE;AAAA,4BAAC;AAAA,4BAAA;AAAA,8BACC,SAAS,MAAMwB,EAAe8C,CAAM;AAAA,8BACpC,WAAU;AAAA,8BACV,OAAM;AAAA,8BAEN,UAAA,gBAAAtE,EAAC6F,IAAA,EAAE,WAAU,cAAA,CAAc;AAAA,4BAAA;AAAA,0BAAA;AAAA,wBAC7B;AAAA,sBAAA;AAAA,sBA9BKvB,EAAO;AAAA,oBAAA,CAgCf,EAAA,CACH;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAKJ,gBAAAc,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,gBAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,kBAAA,gBAAApF,EAAC,MAAA,EAAG,WAAU,4CAA2C,UAAA,uBAAmB;AAAA,kBAC5E,gBAAAoF,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,oBAAA,gBAAApF,EAAC8F,IAAA,EAAO,WAAU,4EAAA,CAA4E;AAAA,oBAC9F,gBAAA9F;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAK;AAAA,wBACL,aAAY;AAAA,wBACZ,OAAOkC;AAAA,wBACP,UAAU,CAACwC,MAAMvC,GAAgBuC,EAAE,OAAO,KAAK;AAAA,wBAC/C,WAAU;AAAA,wBACV,OAAO,EAAE,cAAc,sBAAA;AAAA,sBAAsB;AAAA,oBAAA;AAAA,kBAC/C,EAAA,CACF;AAAA,gBAAA,GACF;AAAA,gBACCP,EAAa,IAAI,CAAC,EAAE,KAAAC,GAAK,SAAA2B,QAAc;AAEtC,wBAAMC,IAAkB9D,IACpB6D,EAAQ;AAAA,oBAAO,CAAAE,MACbA,EAAE,MAAM,YAAA,EAAc,SAAS/D,EAAa,YAAA,CAAa,KACzD+D,EAAE,KAAK,YAAA,EAAc,SAAS/D,EAAa,YAAA,CAAa,KACxDkC,EAAI,MAAM,YAAA,EAAc,SAASlC,EAAa,YAAA,CAAa;AAAA,kBAAA,IAE7D6D;AAGJ,yBAAIC,EAAgB,WAAW,IAAU,OAGvC,gBAAAZ;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBAEC,WAAU;AAAA,sBACV,OAAO,EAAE,cAAc,qBAAA;AAAA,sBAEvB,UAAA;AAAA,wBAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,0BAAA,gBAAApF,EAACL,KAAY,MAAMyE,EAAI,QAAQ,UAAU,WAAU,wCAAuC;AAAA,0BAC1F,gBAAApE,EAAC,QAAA,EAAK,WAAU,0CAA0C,YAAI,OAAM;AAAA,0BACpE,gBAAAoF,EAAC,QAAA,EAAK,WAAU,oCAAmC,UAAA;AAAA,4BAAA;AAAA,4BAAEY,EAAgB;AAAA,4BAAO;AAAA,4BAAQA,EAAgB,SAAS,IAAI,MAAM;AAAA,4BAAG;AAAA,0BAAA,EAAA,CAAC;AAAA,wBAAA,GAC7H;AAAA,0CACC,OAAA,EAAI,WAAU,wDACZ,UAAAA,EAAgB,IAAI,CAAC1B,MAAW;AAC/B,gCAAMnE,IAAasB,EAAW6C,EAAO,EAAE,GACjClE,IAAa,CAACD,KAAc,CAACuB;AAEnC,iCACE,gBAAA0D;AAAA,4BAAC;AAAA,4BAAA;AAAA,8BAEC,SAAS,MAAMf,GAAqBC,GAAQF,CAAG;AAAA,8BAC/C,UAAUhE;AAAA,8BACV,WAAW,8CACTF,GAAuBC,GAAYC,CAAU,CAC/C;AAAA,8BACA,OAAO,EAAE,cAAc,uBAAA;AAAA,8BAEvB,UAAA;AAAA,gCAAA,gBAAAJ,EAAC,OAAA,EAAI,WAAW,4CACdG,IACI,4CACA,sDACN,IAAI,OAAO,EAAE,cAAc,0BACzB,UAAA,gBAAAH,EAACL,KAAY,MAAM2E,EAAO,QAAQ,QAAQ,WAAU,WAAU,EAAA,CAChE;AAAA,gCACA,gBAAAtE,EAAC,UAAK,WAAW,WACfG,IAAa,+CAA+C,4BAC9D,IACG,UAAAmE,EAAO,MAAA,CACV;AAAA,gCACCnE,KACC,gBAAAH,EAAC2F,GAAA,EAAM,WAAU,iDAAA,CAAiD;AAAA,8BAAA;AAAA,4BAAA;AAAA,4BArB/DrB,EAAO;AAAA,0BAAA;AAAA,wBAyBlB,CAAC,EAAA,CACH;AAAA,sBAAA;AAAA,oBAAA;AAAA,oBA1CKF,EAAI;AAAA,kBAAA;AAAA,gBA6Cf,CAAC;AAAA,iBAECD,EAAa,WAAW,KAAMjC,KAAgBiC,EAAa;AAAA,kBAAM,CAAC,EAAE,SAAA4B,EAAA,MACpE,CAACA,EAAQ;AAAA,oBAAK,OACZE,EAAE,MAAM,YAAA,EAAc,SAAS/D,EAAa,YAAA,CAAa,KACzD+D,EAAE,KAAK,YAAA,EAAc,SAAS/D,EAAa,aAAa;AAAA,kBAAA;AAAA,gBAC1D,MAEA,gBAAAlC,EAAC,OAAA,EAAI,WAAU,iDACZ,UAAAkC,IAAe,6BAA6BA,CAAY,MAAM5B,EAAE,4BAA4B,EAAA,CAC/F;AAAA,cAAA,EAAA,CAEJ;AAAA,YAAA,EAAA,CACA;AAAA,UAAA,EAAA,CAEF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ,GACF;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"PreferencesPage-CJRaU3ba.js","sources":["../../src/pages/personal/myspace/PreferencesPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { useTabNavigation } from '@/hooks/useTabNavigation';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Palette, Globe, Bell, Loader2, Check, Star, X, Search, GripVertical } from 'lucide-react';\r\nimport * as LucideIcons from 'lucide-react';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport { LanguageSwitcher } from '@/components/ui/LanguageSwitcher';\r\nimport { ThemeCustomizer } from '@/components/ui/ThemeCustomizer';\r\nimport { useTheme } from '@/contexts/ThemeContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useNavigation, type ModuleDto, type ApplicationDto } from '@/contexts/NavigationContext';\r\nimport { useFavoriteModules, type FavoriteModule } from '@/hooks/useFavoriteModules';\r\nimport { userApi } from '@/services/api/userApi';\r\n\r\nconst PREFERENCES_TABS = ['appearance', 'language', 'notifications', 'favorites'] as const;\r\ntype PreferencesTab = typeof PREFERENCES_TABS[number];\r\n\r\n// Dynamic icon component\r\nfunction DynamicIcon({ name, className }: { name: string; className?: string }) {\r\n const icons = LucideIcons as unknown as Record<string, LucideIcon>;\r\n const IconComponent = icons[name];\r\n if (!IconComponent) {\r\n return <Star className={className} />;\r\n }\r\n return <IconComponent className={className} />;\r\n}\r\n\r\nfunction getFavoriteButtonClass(isSelected: boolean, isDisabled: boolean): string {\r\n if (isSelected) return 'bg-[var(--accent-bg)] border-2 border-[var(--color-accent-500)]';\r\n if (isDisabled) return 'opacity-50 cursor-not-allowed bg-[var(--bg-tertiary)] border border-[var(--border-color)]';\r\n return 'bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)]';\r\n}\r\n\r\nexport function PreferencesPage(): ReactElement | null {\r\n const { t, i18n } = useTranslation(['navigation', 'common']);\r\n const navigate = useNavigate();\r\n const { activeTab, setActiveTab } = useTabNavigation<PreferencesTab>('appearance', PREFERENCES_TABS);\r\n const { loadFromServer, isSyncing, selectedThemeTenant } = useTheme();\r\n const { currentTenant, isLoading: tenantLoading } = useTenant();\r\n const { menu } = useNavigation();\r\n const { favorites, toggleFavorite, isFavorite, canAddMore, maxFavorites, reorderFavorites, loading: favoritesLoading } = useFavoriteModules();\r\n const [syncSuccess, setSyncSuccess] = useState(false);\r\n const [moduleSearch, setModuleSearch] = useState('');\r\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null);\r\n const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);\r\n const dragNodeRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const [emailNotifications, setEmailNotifications] = useState(true);\r\n const [securityAlerts, setSecurityAlerts] = useState(true);\r\n const [productUpdates, setProductUpdates] = useState(false);\r\n const [notificationsSaving, setNotificationsSaving] = useState(false);\r\n const [notificationsSaved, setNotificationsSaved] = useState(false);\r\n const notificationsSaveTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const isInitialLoadRef = useRef(true);\r\n\r\n // Wait for tenant context to be loaded before fetching preferences\r\n useEffect(() => {\r\n if (!tenantLoading && currentTenant) {\r\n loadPreferences();\r\n }\r\n }, [tenantLoading, currentTenant]);\r\n\r\n const loadPreferences = async () => {\r\n try {\r\n const prefs = await userApi.preferences.get();\r\n setEmailNotifications(prefs.emailNotifications);\r\n setSecurityAlerts(prefs.pushNotifications);\r\n isInitialLoadRef.current = false;\r\n } catch {\r\n isInitialLoadRef.current = false;\r\n }\r\n };\r\n\r\n const saveNotifications = useCallback(async () => {\r\n setNotificationsSaving(true);\r\n setNotificationsSaved(false);\r\n try {\r\n await userApi.preferences.updateNotifications({\r\n emailNotifications,\r\n pushNotifications: securityAlerts,\r\n });\r\n setNotificationsSaved(true);\r\n setTimeout(() => setNotificationsSaved(false), 2000);\r\n } catch {\r\n console.error('[PreferencesPage] Failed to save notifications');\r\n } finally {\r\n setNotificationsSaving(false);\r\n }\r\n }, [emailNotifications, securityAlerts]);\r\n\r\n useEffect(() => {\r\n if (isInitialLoadRef.current) return;\r\n\r\n if (notificationsSaveTimeoutRef.current) {\r\n clearTimeout(notificationsSaveTimeoutRef.current);\r\n }\r\n\r\n notificationsSaveTimeoutRef.current = setTimeout(() => {\r\n saveNotifications();\r\n }, 1000);\r\n\r\n return () => {\r\n if (notificationsSaveTimeoutRef.current) {\r\n clearTimeout(notificationsSaveTimeoutRef.current);\r\n }\r\n };\r\n }, [emailNotifications, securityAlerts, saveNotifications]);\r\n\r\n const handleSync = async () => {\r\n // Determine which scope to sync based on selectedThemeTenant\r\n // null = global scope, string = tenant scope\r\n const scope = selectedThemeTenant === null ? 'global' : 'tenant';\r\n setSyncSuccess(false);\r\n try {\r\n await loadFromServer(scope);\r\n await loadPreferences();\r\n setSyncSuccess(true);\r\n setTimeout(() => setSyncSuccess(false), 3000);\r\n } catch (error) {\r\n console.error('[PreferencesPage] Sync failed:', error);\r\n }\r\n };\r\n\r\n const tabs = [\r\n { id: 'appearance' as const, label: 'Apparence', icon: Palette, description: 'Personnaliser le thème et les couleurs' },\r\n { id: 'language' as const, label: 'Langue', icon: Globe, description: 'Changer la langue de l\\'interface' },\r\n { id: 'notifications' as const, label: 'Notifications', icon: Bell, description: 'Gérer les notifications' },\r\n { id: 'favorites' as const, label: t('common:favorites.quickAccess'), icon: Star, description: 'Gérer vos modules favoris' },\r\n ];\r\n\r\n // Gather all modules grouped by application for favorites\r\n const modulesByApp: { app: ApplicationDto; modules: ModuleDto[] }[] = [];\r\n menu?.applications.forEach(app => {\r\n if ((app.modules?.length ?? 0) > 0) {\r\n modulesByApp.push({\r\n app,\r\n modules: app.modules,\r\n });\r\n }\r\n });\r\n\r\n const handleToggleFavorite = (module: ModuleDto, app: ApplicationDto) => {\r\n const favoriteModule: FavoriteModule = {\r\n id: module.id,\r\n code: module.code,\r\n label: module.label,\r\n icon: module.icon || 'Star',\r\n route: `/${app.code}/${module.code}`,\r\n applicationCode: app.code,\r\n applicationLabel: app.label,\r\n };\r\n toggleFavorite(favoriteModule);\r\n };\r\n\r\n const handleFavoriteClick = (module: FavoriteModule) => {\r\n if (module.route) {\r\n navigate(module.route);\r\n }\r\n };\r\n\r\n // Drag and drop handlers for reordering\r\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>, index: number) => {\r\n setDraggedIndex(index);\r\n dragNodeRef.current = e.currentTarget;\r\n e.dataTransfer.effectAllowed = 'move';\r\n e.dataTransfer.setData('text/plain', index.toString());\r\n // Add a slight delay to allow the drag image to be created before adding opacity\r\n setTimeout(() => {\r\n if (dragNodeRef.current) {\r\n dragNodeRef.current.style.opacity = '0.4';\r\n }\r\n }, 0);\r\n };\r\n\r\n const handleDragEnd = () => {\r\n if (dragNodeRef.current) {\r\n dragNodeRef.current.style.opacity = '1';\r\n }\r\n setDraggedIndex(null);\r\n setDragOverIndex(null);\r\n dragNodeRef.current = null;\r\n };\r\n\r\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>, index: number) => {\r\n e.preventDefault();\r\n e.dataTransfer.dropEffect = 'move';\r\n if (index !== draggedIndex) {\r\n setDragOverIndex(index);\r\n }\r\n };\r\n\r\n const handleDragLeave = () => {\r\n setDragOverIndex(null);\r\n };\r\n\r\n const handleDrop = (e: React.DragEvent<HTMLDivElement>, dropIndex: number) => {\r\n e.preventDefault();\r\n const dragIndex = draggedIndex;\r\n if (dragIndex === null || dragIndex === dropIndex) return;\r\n\r\n const newFavorites = [...favorites];\r\n const [draggedItem] = newFavorites.splice(dragIndex, 1);\r\n newFavorites.splice(dropIndex, 0, draggedItem);\r\n\r\n reorderFavorites(newFavorites);\r\n handleDragEnd();\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('navigation:sidebar.preferences')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-1\">Personnalisez votre expérience SmartStack</p>\r\n </div>\r\n\r\n {/* Tab Navigation */}\r\n <div className=\"border-b border-[var(--item-color-border)]\">\r\n <nav className=\"flex gap-1\" aria-label=\"Tabs\">\r\n {tabs.map((tab) => {\r\n const Icon = tab.icon;\r\n return (\r\n <button\r\n key={tab.id}\r\n onClick={() => setActiveTab(tab.id)}\r\n className={`flex items-center gap-2 px-4 py-3 text-sm font-medium transition-all border-b-2 ${\r\n activeTab === tab.id\r\n ? 'border-[var(--color-accent-500)] text-[var(--color-accent-600)] bg-[var(--accent-bg)]'\r\n : 'border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n style={{ borderRadius: 'var(--radius-button) var(--radius-button) 0 0' }}\r\n >\r\n <Icon className=\"w-5 h-5\" />\r\n <span>{tab.label}</span>\r\n </button>\r\n );\r\n })}\r\n </nav>\r\n </div>\r\n\r\n {/* Tab Content */}\r\n <div\r\n className=\"bg-[var(--bg-card)] border border-[var(--item-color-border)] p-6\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n {activeTab === 'appearance' && (\r\n <div className=\"space-y-4\">\r\n <ThemeCustomizer\r\n onSync={handleSync}\r\n isSyncing={isSyncing}\r\n syncSuccess={syncSuccess}\r\n />\r\n </div>\r\n )}\r\n\r\n {activeTab === 'language' && (\r\n <div className=\"space-y-6\">\r\n <div>\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">Langue</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Sélectionnez la langue de l'interface\r\n </p>\r\n </div>\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">\r\n {i18n.language?.startsWith('fr') ? 'Français' : 'English'}\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Langue actuelle de l'interface\r\n </p>\r\n </div>\r\n <LanguageSwitcher />\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {activeTab === 'notifications' && (\r\n <div className=\"space-y-6\">\r\n <div className=\"flex items-start justify-between\">\r\n <div>\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">Notifications</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Gérez vos préférences de notifications\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs text-[var(--text-muted)]\">\r\n {notificationsSaving && (\r\n <>\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n <span>Sauvegarde...</span>\r\n </>\r\n )}\r\n {notificationsSaved && !notificationsSaving && (\r\n <>\r\n <Check className=\"w-3 h-3 text-green-500\" />\r\n <span className=\"text-green-600\">Sauvegardé</span>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"space-y-4\">\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Notifications par email</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Recevoir des notifications par email\r\n </p>\r\n </div>\r\n <label className=\"relative inline-flex items-center cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n className=\"sr-only peer\"\r\n checked={emailNotifications}\r\n onChange={(e) => setEmailNotifications(e.target.checked)}\r\n />\r\n <div\r\n className=\"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <span className=\"after:rounded-full\" />\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Alertes de sécurité</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Être notifié des événements de sécurité\r\n </p>\r\n </div>\r\n <label className=\"relative inline-flex items-center cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n className=\"sr-only peer\"\r\n checked={securityAlerts}\r\n onChange={(e) => setSecurityAlerts(e.target.checked)}\r\n />\r\n <div\r\n className=\"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <span className=\"after:rounded-full\" />\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Mises à jour produit</h3>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n Nouvelles fonctionnalités et améliorations\r\n </p>\r\n </div>\r\n <label className=\"relative inline-flex items-center cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n className=\"sr-only peer\"\r\n checked={productUpdates}\r\n onChange={(e) => setProductUpdates(e.target.checked)}\r\n />\r\n <div\r\n className=\"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <span className=\"after:rounded-full\" />\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {activeTab === 'favorites' && (\r\n <div className=\"space-y-6\">\r\n <div>\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">{t('common:favorites.quickAccess')}</h2>\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1\">\r\n {t('common:favorites.selectModules', { count: favorites.length, max: maxFavorites })}\r\n </p>\r\n </div>\r\n\r\n {favoritesLoading && (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"w-6 h-6 animate-spin text-[var(--color-accent-500)]\" />\r\n <span className=\"ml-2 text-[var(--text-secondary)]\">Chargement des favoris...</span>\r\n </div>\r\n )}\r\n\r\n {!favoritesLoading && (\r\n <>\r\n\r\n {/* Current Favorites */}\r\n <div\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Vos favoris actuels</h3>\r\n {favorites.length > 1 && (\r\n <span className=\"text-xs text-[var(--text-muted)]\">Glissez pour réorganiser</span>\r\n )}\r\n </div>\r\n {favorites.length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-secondary)]\">Aucun favori sélectionné</p>\r\n ) : (\r\n <div className=\"flex flex-col gap-2\">\r\n {favorites.map((module, index) => (\r\n <div\r\n key={module.id}\r\n draggable\r\n onDragStart={(e) => handleDragStart(e, index)}\r\n onDragEnd={handleDragEnd}\r\n onDragOver={(e) => handleDragOver(e, index)}\r\n onDragLeave={handleDragLeave}\r\n onDrop={(e) => handleDrop(e, index)}\r\n className={`flex items-center gap-2 px-3 py-2 bg-[var(--accent-bg)] border text-[var(--color-accent-500)] cursor-grab active:cursor-grabbing transition-all ${\r\n dragOverIndex === index\r\n ? 'border-[var(--color-accent-500)] border-2 scale-[1.02]'\r\n : 'border-[var(--color-accent-500)]/50'\r\n }`}\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <GripVertical className=\"w-4 h-4 text-[var(--color-accent-400)] flex-shrink-0\" />\r\n <span className=\"text-xs text-[var(--color-accent-500)] font-mono w-4\">{index + 1}</span>\r\n <button\r\n onClick={() => handleFavoriteClick(module)}\r\n className=\"flex items-center gap-2 hover:underline flex-1\"\r\n >\r\n <DynamicIcon name={module.icon} className=\"w-4 h-4\" />\r\n <span className=\"text-sm font-medium\">{module.label}</span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">({module.applicationLabel})</span>\r\n </button>\r\n <button\r\n onClick={() => toggleFavorite(module)}\r\n className=\"p-1 hover:bg-[var(--bg-tertiary)] rounded flex-shrink-0\"\r\n title=\"Retirer des favoris\"\r\n >\r\n <X className=\"w-3.5 h-3.5\" />\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Available Modules */}\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">Modules disponibles</h3>\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder=\"Rechercher un module...\"\r\n value={moduleSearch}\r\n onChange={(e) => setModuleSearch(e.target.value)}\r\n className=\"pl-9 pr-3 py-2 w-64 bg-[var(--bg-primary)] border border-[var(--border-color)] text-sm focus:outline-none focus:border-[var(--color-accent-500)]\"\r\n style={{ borderRadius: 'var(--radius-input)' }}\r\n />\r\n </div>\r\n </div>\r\n {modulesByApp.map(({ app, modules }) => {\r\n // Filter modules based on search\r\n const filteredModules = moduleSearch\r\n ? modules.filter(m =>\r\n m.label.toLowerCase().includes(moduleSearch.toLowerCase()) ||\r\n m.code.toLowerCase().includes(moduleSearch.toLowerCase()) ||\r\n app.label.toLowerCase().includes(moduleSearch.toLowerCase())\r\n )\r\n : modules;\r\n\r\n // Don't render app section if no modules match\r\n if (filteredModules.length === 0) return null;\r\n\r\n return (\r\n <div\r\n key={app.id}\r\n className=\"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <DynamicIcon name={app.icon || 'Folder'} className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n <span className=\"font-medium text-[var(--text-primary)]\">{app.label}</span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">({filteredModules.length} module{filteredModules.length > 1 ? 's' : ''})</span>\r\n </div>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2\">\r\n {filteredModules.map((module) => {\r\n const isSelected = isFavorite(module.id);\r\n const isDisabled = !isSelected && !canAddMore;\r\n\r\n return (\r\n <button\r\n key={module.id}\r\n onClick={() => handleToggleFavorite(module, app)}\r\n disabled={isDisabled}\r\n className={`flex items-center gap-3 p-3 transition-all ${\r\n getFavoriteButtonClass(isSelected, isDisabled)\r\n }`}\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <div className={`w-8 h-8 flex items-center justify-center ${\r\n isSelected\r\n ? 'bg-[var(--color-accent-600)] text-white'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)]'\r\n }`} style={{ borderRadius: 'var(--radius-button)' }}>\r\n <DynamicIcon name={module.icon || 'Star'} className=\"w-4 h-4\" />\r\n </div>\r\n <span className={`text-sm ${\r\n isSelected ? 'font-medium text-[var(--color-accent-500)]' : 'text-[var(--text-primary)]'\r\n }`}>\r\n {module.label}\r\n </span>\r\n {isSelected && (\r\n <Check className=\"w-4 h-4 text-[var(--color-accent-500)] ml-auto\" />\r\n )}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n })}\r\n\r\n {(modulesByApp.length === 0 || (moduleSearch && modulesByApp.every(({ modules }) =>\r\n !modules.some(m =>\r\n m.label.toLowerCase().includes(moduleSearch.toLowerCase()) ||\r\n m.code.toLowerCase().includes(moduleSearch.toLowerCase())\r\n )\r\n ))) && (\r\n <div className=\"text-center py-8 text-[var(--text-secondary)]\">\r\n {moduleSearch ? `Aucun module trouvé pour \"${moduleSearch}\"` : t('common:favorites.noModules')}\r\n </div>\r\n )}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["PREFERENCES_TABS","DynamicIcon","name","className","IconComponent","LucideIcons","jsx","Star","getFavoriteButtonClass","isSelected","isDisabled","PreferencesPage","t","i18n","useTranslation","navigate","useNavigate","activeTab","setActiveTab","useTabNavigation","loadFromServer","isSyncing","selectedThemeTenant","useTheme","currentTenant","tenantLoading","useTenant","menu","useNavigation","favorites","toggleFavorite","isFavorite","canAddMore","maxFavorites","reorderFavorites","favoritesLoading","useFavoriteModules","syncSuccess","setSyncSuccess","useState","moduleSearch","setModuleSearch","draggedIndex","setDraggedIndex","dragOverIndex","setDragOverIndex","dragNodeRef","useRef","emailNotifications","setEmailNotifications","securityAlerts","setSecurityAlerts","productUpdates","setProductUpdates","notificationsSaving","setNotificationsSaving","notificationsSaved","setNotificationsSaved","notificationsSaveTimeoutRef","isInitialLoadRef","useEffect","loadPreferences","prefs","userApi","saveNotifications","useCallback","handleSync","scope","error","tabs","Palette","Globe","Bell","modulesByApp","app","handleToggleFavorite","module","favoriteModule","handleFavoriteClick","handleDragStart","e","index","handleDragEnd","handleDragOver","handleDragLeave","handleDrop","dropIndex","dragIndex","newFavorites","draggedItem","jsxs","tab","Icon","ThemeCustomizer","LanguageSwitcher","Fragment","Loader2","Check","GripVertical","X","Search","modules","filteredModules","m"],"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"),c=require("react"),oe=require("react-router-dom"),le=require("./useTabNavigation-BVtbCTd5.js"),de=require("react-i18next"),n=require("lucide-react"),u=require("./index-2wUhd9Lu.js");function ue(s){const l=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const x in s)if(x!=="default"){const o=Object.getOwnPropertyDescriptor(s,x);Object.defineProperty(l,x,o.get?o:{enumerable:!0,get:()=>s[x]})}}return l.default=s,Object.freeze(l)}const xe=ue(n),me=["appearance","language","notifications","favorites"];function S({name:s,className:l}){const o=xe[s];return o?e.jsx(o,{className:l}):e.jsx(n.Star,{className:l})}function ve(s,l){return s?"bg-[var(--accent-bg)] border-2 border-[var(--color-accent-500)]":l?"opacity-50 cursor-not-allowed bg-[var(--bg-tertiary)] border border-[var(--border-color)]":"bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)]"}function fe(){const{t:s,i18n:l}=de.useTranslation(["navigation","common"]),x=oe.useNavigate(),{activeTab:o,setActiveTab:$}=le.useTabNavigation("appearance",me),{loadFromServer:z,isSyncing:G,selectedThemeTenant:B}=u.useTheme(),{currentTenant:k,isLoading:C}=u.useTenant(),{menu:_}=u.useNavigation(),{favorites:f,toggleFavorite:R,isFavorite:U,canAddMore:V,maxFavorites:W,reorderFavorites:X,loading:T}=u.useFavorites(),[H,j]=c.useState(!1),[d,J]=c.useState(""),[L,D]=c.useState(null),[K,y]=c.useState(null),v=c.useRef(null),[h,F]=c.useState(!0),[p,P]=c.useState(!0),[Q,Y]=c.useState(!1),[A,E]=c.useState(!1),[Z,N]=c.useState(!1),b=c.useRef(null),w=c.useRef(!0);c.useEffect(()=>{!C&&k&&I()},[C,k]);const I=async()=>{try{const t=await u.userApi.preferences.get();F(t.emailNotifications),P(t.pushNotifications),w.current=!1}catch{w.current=!1}},M=c.useCallback(async()=>{E(!0),N(!1);try{await u.userApi.preferences.updateNotifications({emailNotifications:h,pushNotifications:p}),N(!0),setTimeout(()=>N(!1),2e3)}catch{console.error("[PreferencesPage] Failed to save notifications")}finally{E(!1)}},[h,p]);c.useEffect(()=>{if(!w.current)return b.current&&clearTimeout(b.current),b.current=setTimeout(()=>{M()},1e3),()=>{b.current&&clearTimeout(b.current)}},[h,p,M]);const ee=async()=>{const t=B===null?"global":"tenant";j(!1);try{await z(t),await I(),j(!0),setTimeout(()=>j(!1),3e3)}catch(r){console.error("[PreferencesPage] Sync failed:",r)}},te=[{id:"appearance",label:"Apparence",icon:n.Palette,description:"Personnaliser le thème et les couleurs"},{id:"language",label:"Langue",icon:n.Globe,description:"Changer la langue de l'interface"},{id:"notifications",label:"Notifications",icon:n.Bell,description:"Gérer les notifications"},{id:"favorites",label:s("common:favorites.quickAccess"),icon:n.Star,description:"Gérer vos modules favoris"}],g=[];_?.applications.forEach(t=>{(t.modules?.length??0)>0&&g.push({app:t,modules:t.modules})});const re=(t,r)=>{const a={id:t.id,code:t.code,label:t.label,icon:t.icon||"Star",route:`/${r.code}/${t.code}`,applicationCode:r.code,applicationLabel:r.label};R(a)},ae=t=>{t.route&&x(t.route)},se=(t,r)=>{D(r),v.current=t.currentTarget,t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",r.toString()),setTimeout(()=>{v.current&&(v.current.style.opacity="0.4")},0)},O=()=>{v.current&&(v.current.style.opacity="1"),D(null),y(null),v.current=null},ce=(t,r)=>{t.preventDefault(),t.dataTransfer.dropEffect="move",r!==L&&y(r)},ne=()=>{y(null)},ie=(t,r)=>{t.preventDefault();const a=L;if(a===null||a===r)return;const i=[...f],[m]=i.splice(a,1);i.splice(r,0,m),X(i),O()};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("navigation:sidebar.preferences")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:"Personnalisez votre expérience SmartStack"})]}),e.jsx("div",{className:"border-b border-[var(--item-color-border)]",children:e.jsx("nav",{className:"flex gap-1","aria-label":"Tabs",children:te.map(t=>{const r=t.icon;return e.jsxs("button",{onClick:()=>$(t.id),className:`flex items-center gap-2 px-4 py-3 text-sm font-medium transition-all border-b-2 ${o===t.id?"border-[var(--color-accent-500)] text-[var(--color-accent-600)] bg-[var(--accent-bg)]":"border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,style:{borderRadius:"var(--radius-button) var(--radius-button) 0 0"},children:[e.jsx(r,{className:"w-5 h-5"}),e.jsx("span",{children:t.label})]},t.id)})})}),e.jsxs("div",{className:"bg-[var(--bg-card)] border border-[var(--item-color-border)] p-6",style:{borderRadius:"var(--radius-card)"},children:[o==="appearance"&&e.jsx("div",{className:"space-y-4",children:e.jsx(u.ThemeCustomizer,{onSync:ee,isSyncing:G,syncSuccess:H})}),o==="language"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Langue"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Sélectionnez la langue de l'interface"})]}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:l.language?.startsWith("fr")?"Français":"English"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Langue actuelle de l'interface"})]}),e.jsx(u.LanguageSwitcher,{})]})})]}),o==="notifications"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Notifications"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Gérez vos préférences de notifications"})]}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-[var(--text-muted)]",children:[A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Loader2,{className:"w-3 h-3 animate-spin"}),e.jsx("span",{children:"Sauvegarde..."})]}),Z&&!A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Check,{className:"w-3 h-3 text-green-500"}),e.jsx("span",{className:"text-green-600",children:"Sauvegardé"})]})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Notifications par email"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Recevoir des notifications par email"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:h,onChange:t=>F(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Alertes de sécurité"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Être notifié des événements de sécurité"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:p,onChange:t=>P(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Mises à jour produit"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Nouvelles fonctionnalités et améliorations"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:Q,onChange:t=>Y(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})})]})]}),o==="favorites"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:s("common:favorites.quickAccess")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:s("common:favorites.selectModules",{count:f.length,max:W})})]}),T&&e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx(n.Loader2,{className:"w-6 h-6 animate-spin text-[var(--color-accent-500)]"}),e.jsx("span",{className:"ml-2 text-[var(--text-secondary)]",children:"Chargement des favoris..."})]}),!T&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Vos favoris actuels"}),f.length>1&&e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"Glissez pour réorganiser"})]}),f.length===0?e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:"Aucun favori sélectionné"}):e.jsx("div",{className:"flex flex-col gap-2",children:f.map((t,r)=>e.jsxs("div",{draggable:!0,onDragStart:a=>se(a,r),onDragEnd:O,onDragOver:a=>ce(a,r),onDragLeave:ne,onDrop:a=>ie(a,r),className:`flex items-center gap-2 px-3 py-2 bg-[var(--accent-bg)] border text-[var(--color-accent-500)] cursor-grab active:cursor-grabbing transition-all ${K===r?"border-[var(--color-accent-500)] border-2 scale-[1.02]":"border-[var(--color-accent-500)]/50"}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx(n.GripVertical,{className:"w-4 h-4 text-[var(--color-accent-400)] flex-shrink-0"}),e.jsx("span",{className:"text-xs text-[var(--color-accent-500)] font-mono w-4",children:r+1}),e.jsxs("button",{onClick:()=>ae(t),className:"flex items-center gap-2 hover:underline flex-1",children:[e.jsx(S,{name:t.icon,className:"w-4 h-4"}),e.jsx("span",{className:"text-sm font-medium",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",t.applicationLabel,")"]})]}),e.jsx("button",{onClick:()=>R(t),className:"p-1 hover:bg-[var(--bg-tertiary)] rounded flex-shrink-0",title:"Retirer des favoris",children:e.jsx(n.X,{className:"w-3.5 h-3.5"})})]},t.id))})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Modules disponibles"}),e.jsxs("div",{className:"relative",children:[e.jsx(n.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]"}),e.jsx("input",{type:"text",placeholder:"Rechercher un module...",value:d,onChange:t=>J(t.target.value),className:"pl-9 pr-3 py-2 w-64 bg-[var(--bg-primary)] border border-[var(--border-color)] text-sm focus:outline-none focus:border-[var(--color-accent-500)]",style:{borderRadius:"var(--radius-input)"}})]})]}),g.map(({app:t,modules:r})=>{const a=d?r.filter(i=>i.label.toLowerCase().includes(d.toLowerCase())||i.code.toLowerCase().includes(d.toLowerCase())||t.label.toLowerCase().includes(d.toLowerCase())):r;return a.length===0?null:e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(S,{name:t.icon||"Folder",className:"w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",a.length," module",a.length>1?"s":"",")"]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2",children:a.map(i=>{const m=U(i.id),q=!m&&!V;return e.jsxs("button",{onClick:()=>re(i,t),disabled:q,className:`flex items-center gap-3 p-3 transition-all ${ve(m,q)}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx("div",{className:`w-8 h-8 flex items-center justify-center ${m?"bg-[var(--color-accent-600)] text-white":"bg-[var(--bg-tertiary)] text-[var(--text-secondary)]"}`,style:{borderRadius:"var(--radius-button)"},children:e.jsx(S,{name:i.icon||"Star",className:"w-4 h-4"})}),e.jsx("span",{className:`text-sm ${m?"font-medium text-[var(--color-accent-500)]":"text-[var(--text-primary)]"}`,children:i.label}),m&&e.jsx(n.Check,{className:"w-4 h-4 text-[var(--color-accent-500)] ml-auto"})]},i.id)})})]},t.id)}),(g.length===0||d&&g.every(({modules:t})=>!t.some(r=>r.label.toLowerCase().includes(d.toLowerCase())||r.code.toLowerCase().includes(d.toLowerCase()))))&&e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:d?`Aucun module trouvé pour "${d}"`:s("common:favorites.noModules")})]})]})]})]})]})}exports.PreferencesPage=fe;
|
|
2
|
-
//# sourceMappingURL=PreferencesPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),c=require("react"),oe=require("react-router-dom"),le=require("./useTabNavigation-BVtbCTd5.js"),de=require("react-i18next"),n=require("lucide-react"),u=require("./index-IgLVXPg8.js");function ue(s){const l=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const x in s)if(x!=="default"){const o=Object.getOwnPropertyDescriptor(s,x);Object.defineProperty(l,x,o.get?o:{enumerable:!0,get:()=>s[x]})}}return l.default=s,Object.freeze(l)}const xe=ue(n),me=["appearance","language","notifications","favorites"];function S({name:s,className:l}){const o=xe[s];return o?e.jsx(o,{className:l}):e.jsx(n.Star,{className:l})}function ve(s,l){return s?"bg-[var(--accent-bg)] border-2 border-[var(--color-accent-500)]":l?"opacity-50 cursor-not-allowed bg-[var(--bg-tertiary)] border border-[var(--border-color)]":"bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)]"}function fe(){const{t:s,i18n:l}=de.useTranslation(["navigation","common"]),x=oe.useNavigate(),{activeTab:o,setActiveTab:$}=le.useTabNavigation("appearance",me),{loadFromServer:z,isSyncing:G,selectedThemeTenant:B}=u.useTheme(),{currentTenant:k,isLoading:C}=u.useTenant(),{menu:_}=u.useNavigation(),{favorites:f,toggleFavorite:R,isFavorite:U,canAddMore:V,maxFavorites:W,reorderFavorites:X,loading:T}=u.useFavorites(),[H,j]=c.useState(!1),[d,J]=c.useState(""),[L,D]=c.useState(null),[K,y]=c.useState(null),v=c.useRef(null),[h,F]=c.useState(!0),[p,P]=c.useState(!0),[Q,Y]=c.useState(!1),[A,E]=c.useState(!1),[Z,N]=c.useState(!1),b=c.useRef(null),w=c.useRef(!0);c.useEffect(()=>{!C&&k&&I()},[C,k]);const I=async()=>{try{const t=await u.userApi.preferences.get();F(t.emailNotifications),P(t.pushNotifications),w.current=!1}catch{w.current=!1}},M=c.useCallback(async()=>{E(!0),N(!1);try{await u.userApi.preferences.updateNotifications({emailNotifications:h,pushNotifications:p}),N(!0),setTimeout(()=>N(!1),2e3)}catch{console.error("[PreferencesPage] Failed to save notifications")}finally{E(!1)}},[h,p]);c.useEffect(()=>{if(!w.current)return b.current&&clearTimeout(b.current),b.current=setTimeout(()=>{M()},1e3),()=>{b.current&&clearTimeout(b.current)}},[h,p,M]);const ee=async()=>{const t=B===null?"global":"tenant";j(!1);try{await z(t),await I(),j(!0),setTimeout(()=>j(!1),3e3)}catch(r){console.error("[PreferencesPage] Sync failed:",r)}},te=[{id:"appearance",label:"Apparence",icon:n.Palette,description:"Personnaliser le thème et les couleurs"},{id:"language",label:"Langue",icon:n.Globe,description:"Changer la langue de l'interface"},{id:"notifications",label:"Notifications",icon:n.Bell,description:"Gérer les notifications"},{id:"favorites",label:s("common:favorites.quickAccess"),icon:n.Star,description:"Gérer vos modules favoris"}],g=[];_?.applications.forEach(t=>{(t.modules?.length??0)>0&&g.push({app:t,modules:t.modules})});const re=(t,r)=>{const a={id:t.id,code:t.code,label:t.label,icon:t.icon||"Star",route:`/${r.code}/${t.code}`,applicationCode:r.code,applicationLabel:r.label};R(a)},ae=t=>{t.route&&x(t.route)},se=(t,r)=>{D(r),v.current=t.currentTarget,t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",r.toString()),setTimeout(()=>{v.current&&(v.current.style.opacity="0.4")},0)},O=()=>{v.current&&(v.current.style.opacity="1"),D(null),y(null),v.current=null},ce=(t,r)=>{t.preventDefault(),t.dataTransfer.dropEffect="move",r!==L&&y(r)},ne=()=>{y(null)},ie=(t,r)=>{t.preventDefault();const a=L;if(a===null||a===r)return;const i=[...f],[m]=i.splice(a,1);i.splice(r,0,m),X(i),O()};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("navigation:sidebar.preferences")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:"Personnalisez votre expérience SmartStack"})]}),e.jsx("div",{className:"border-b border-[var(--item-color-border)]",children:e.jsx("nav",{className:"flex gap-1","aria-label":"Tabs",children:te.map(t=>{const r=t.icon;return e.jsxs("button",{onClick:()=>$(t.id),className:`flex items-center gap-2 px-4 py-3 text-sm font-medium transition-all border-b-2 ${o===t.id?"border-[var(--color-accent-500)] text-[var(--color-accent-600)] bg-[var(--accent-bg)]":"border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,style:{borderRadius:"var(--radius-button) var(--radius-button) 0 0"},children:[e.jsx(r,{className:"w-5 h-5"}),e.jsx("span",{children:t.label})]},t.id)})})}),e.jsxs("div",{className:"bg-[var(--bg-card)] border border-[var(--item-color-border)] p-6",style:{borderRadius:"var(--radius-card)"},children:[o==="appearance"&&e.jsx("div",{className:"space-y-4",children:e.jsx(u.ThemeCustomizer,{onSync:ee,isSyncing:G,syncSuccess:H})}),o==="language"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Langue"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Sélectionnez la langue de l'interface"})]}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:l.language?.startsWith("fr")?"Français":"English"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Langue actuelle de l'interface"})]}),e.jsx(u.LanguageSwitcher,{})]})})]}),o==="notifications"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Notifications"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Gérez vos préférences de notifications"})]}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-[var(--text-muted)]",children:[A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Loader2,{className:"w-3 h-3 animate-spin"}),e.jsx("span",{children:"Sauvegarde..."})]}),Z&&!A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Check,{className:"w-3 h-3 text-green-500"}),e.jsx("span",{className:"text-green-600",children:"Sauvegardé"})]})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Notifications par email"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Recevoir des notifications par email"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:h,onChange:t=>F(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Alertes de sécurité"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Être notifié des événements de sécurité"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:p,onChange:t=>P(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Mises à jour produit"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Nouvelles fonctionnalités et améliorations"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:Q,onChange:t=>Y(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})})]})]}),o==="favorites"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:s("common:favorites.quickAccess")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:s("common:favorites.selectModules",{count:f.length,max:W})})]}),T&&e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx(n.Loader2,{className:"w-6 h-6 animate-spin text-[var(--color-accent-500)]"}),e.jsx("span",{className:"ml-2 text-[var(--text-secondary)]",children:"Chargement des favoris..."})]}),!T&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Vos favoris actuels"}),f.length>1&&e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"Glissez pour réorganiser"})]}),f.length===0?e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:"Aucun favori sélectionné"}):e.jsx("div",{className:"flex flex-col gap-2",children:f.map((t,r)=>e.jsxs("div",{draggable:!0,onDragStart:a=>se(a,r),onDragEnd:O,onDragOver:a=>ce(a,r),onDragLeave:ne,onDrop:a=>ie(a,r),className:`flex items-center gap-2 px-3 py-2 bg-[var(--accent-bg)] border text-[var(--color-accent-500)] cursor-grab active:cursor-grabbing transition-all ${K===r?"border-[var(--color-accent-500)] border-2 scale-[1.02]":"border-[var(--color-accent-500)]/50"}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx(n.GripVertical,{className:"w-4 h-4 text-[var(--color-accent-400)] flex-shrink-0"}),e.jsx("span",{className:"text-xs text-[var(--color-accent-500)] font-mono w-4",children:r+1}),e.jsxs("button",{onClick:()=>ae(t),className:"flex items-center gap-2 hover:underline flex-1",children:[e.jsx(S,{name:t.icon,className:"w-4 h-4"}),e.jsx("span",{className:"text-sm font-medium",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",t.applicationLabel,")"]})]}),e.jsx("button",{onClick:()=>R(t),className:"p-1 hover:bg-[var(--bg-tertiary)] rounded flex-shrink-0",title:"Retirer des favoris",children:e.jsx(n.X,{className:"w-3.5 h-3.5"})})]},t.id))})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Modules disponibles"}),e.jsxs("div",{className:"relative",children:[e.jsx(n.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]"}),e.jsx("input",{type:"text",placeholder:"Rechercher un module...",value:d,onChange:t=>J(t.target.value),className:"pl-9 pr-3 py-2 w-64 bg-[var(--bg-primary)] border border-[var(--border-color)] text-sm focus:outline-none focus:border-[var(--color-accent-500)]",style:{borderRadius:"var(--radius-input)"}})]})]}),g.map(({app:t,modules:r})=>{const a=d?r.filter(i=>i.label.toLowerCase().includes(d.toLowerCase())||i.code.toLowerCase().includes(d.toLowerCase())||t.label.toLowerCase().includes(d.toLowerCase())):r;return a.length===0?null:e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(S,{name:t.icon||"Folder",className:"w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",a.length," module",a.length>1?"s":"",")"]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2",children:a.map(i=>{const m=U(i.id),q=!m&&!V;return e.jsxs("button",{onClick:()=>re(i,t),disabled:q,className:`flex items-center gap-3 p-3 transition-all ${ve(m,q)}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx("div",{className:`w-8 h-8 flex items-center justify-center ${m?"bg-[var(--color-accent-600)] text-white":"bg-[var(--bg-tertiary)] text-[var(--text-secondary)]"}`,style:{borderRadius:"var(--radius-button)"},children:e.jsx(S,{name:i.icon||"Star",className:"w-4 h-4"})}),e.jsx("span",{className:`text-sm ${m?"font-medium text-[var(--color-accent-500)]":"text-[var(--text-primary)]"}`,children:i.label}),m&&e.jsx(n.Check,{className:"w-4 h-4 text-[var(--color-accent-500)] ml-auto"})]},i.id)})})]},t.id)}),(g.length===0||d&&g.every(({modules:t})=>!t.some(r=>r.label.toLowerCase().includes(d.toLowerCase())||r.code.toLowerCase().includes(d.toLowerCase()))))&&e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:d?`Aucun module trouvé pour "${d}"`:s("common:favorites.noModules")})]})]})]})]})]})}exports.PreferencesPage=fe;
|
|
2
|
+
//# sourceMappingURL=PreferencesPage-Cqr9mAab.js.map
|