@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":"RoleDetailPage-CiRVxxIP.js","sources":["../../src/components/platform/administration/permissions/RolePermissionMatrix.tsx","../../src/pages/platform/administration/permissions/RoleDetailPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\r\nimport React, { useState, useMemo, useCallback, createRef } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Loader2, AlertCircle, ChevronDown, ChevronRight, FolderOpen, Box, FileText, Database, Check, Star, Eye, Ban, Save, X, Plus, Edit, Trash2, UserPlus, Play, Shield } from 'lucide-react';\r\nimport { usePermissionMatrix } from '@/hooks/usePermissionMatrix';\r\nimport { useCollapsibleState } from '@/hooks/useCollapsibleState';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { hasFullAccess } from '@/utils/permissions';\r\nimport { groupByApplicationWithSections, calculatePermissionStatus, calculateModuleWithSectionsStatus, getPermissionCellBackground } from '@/utils/permissionUtils';\r\nimport { PermissionStatusIndicator } from './PermissionStatusIndicator';\r\nimport { PermissionPopover } from '../PermissionPopover';\r\nimport type { ResourceNode, PermissionStatus, ModuleWithSections } from './types';\r\n\r\ninterface RolePermissionMatrixProps {\r\n readonly roleId: string;\r\n}\r\n\r\n// Action icons and colors (same as PermissionCellPopover)\r\nconst ACTION_ICONS: Record<string, React.ReactNode> = {\r\n '*': <Shield className=\"h-3 w-3\" />,\r\n read: <Eye className=\"h-3 w-3\" />,\r\n create: <Plus className=\"h-3 w-3\" />,\r\n update: <Edit className=\"h-3 w-3\" />,\r\n delete: <Trash2 className=\"h-3 w-3\" />,\r\n assign: <UserPlus className=\"h-3 w-3\" />,\r\n execute: <Play className=\"h-3 w-3\" />,\r\n};\r\n\r\nconst ACTION_COLORS: Record<string, string> = {\r\n '*': 'bg-[var(--accent-bg)] text-[var(--accent-text)] border-[var(--accent-border)]',\r\n read: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n create: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n update: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n delete: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\r\n assign: 'bg-[var(--accent-bg)] text-[var(--accent-text)] border-[var(--accent-border)]',\r\n execute: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n};\r\n\r\n// Pure function to apply application/module filter\r\nfunction applyApplicationModuleFilterHelper(\r\n grouped: ReturnType<typeof groupByApplicationWithSections>,\r\n applicationFilter: string,\r\n moduleFilter: string\r\n) {\r\n return grouped\r\n .filter(app => applicationFilter === 'all' || app.application === applicationFilter)\r\n .map(app => ({\r\n ...app,\r\n modules: app.modules.filter(m => moduleFilter === 'all' || m.module.moduleLabel === moduleFilter)\r\n }))\r\n .filter(app => app.modules.length > 0);\r\n}\r\n\r\n// Pure function to apply status filter\r\nfunction applyStatusFilterHelper(\r\n grouped: ReturnType<typeof groupByApplicationWithSections>,\r\n statusFilters: Set<PermissionStatus>,\r\n getModuleStatus: (m: ModuleWithSections) => { status: PermissionStatus; grantedCount: number; totalCount: number }\r\n) {\r\n return grouped.map(app => ({\r\n ...app,\r\n modules: app.modules.filter(m => {\r\n const { status } = getModuleStatus(m);\r\n return statusFilters.has(status);\r\n })\r\n })).filter(app => app.modules.length > 0);\r\n}\r\n\r\n// Sub-component for rendering section and resource rows\r\ninterface SectionResourceRowsProps {\r\n readonly section: ResourceNode;\r\n readonly resources: ResourceNode[];\r\n readonly moduleIndex: number;\r\n readonly sectionIndex: number;\r\n readonly collapsedSections: Set<string>;\r\n readonly renderResourceRow: (resource: ResourceNode, rowIndex: number, level: 'module' | 'section' | 'resource', hasChildren: boolean, isCollapsed: boolean) => React.ReactNode;\r\n}\r\n\r\nfunction SectionResourceRows({\r\n section,\r\n resources,\r\n moduleIndex,\r\n sectionIndex,\r\n collapsedSections,\r\n renderResourceRow,\r\n}: SectionResourceRowsProps) {\r\n const hasResources = resources.length > 0;\r\n const isSectionCollapsed = collapsedSections.has(section.id);\r\n\r\n return (\r\n <React.Fragment key={section.id}>\r\n {/* Section Row */}\r\n {renderResourceRow(section, moduleIndex + sectionIndex + 1, 'section', hasResources, isSectionCollapsed)}\r\n\r\n {/* Resource Rows (if section has resources and is not collapsed) */}\r\n {hasResources && !isSectionCollapsed && resources.map((resource, resourceIndex) =>\r\n renderResourceRow(resource, moduleIndex + sectionIndex + resourceIndex + 2, 'resource', false, false)\r\n )}\r\n </React.Fragment>\r\n );\r\n}\r\n\r\nexport function RolePermissionMatrix({ roleId }: RolePermissionMatrixProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const { user } = useAuth();\r\n\r\n const { collapsedApps, toggleApp } = useCollapsibleState();\r\n const [collapsedModules, setCollapsedModules] = useState<Set<string>>(new Set());\r\n const [collapsedSections, setCollapsedSections] = useState<Set<string>>(new Set());\r\n const [statusFilters, setStatusFilters] = useState<Set<PermissionStatus>>(new Set());\r\n const [openPopover, setOpenPopover] = useState<string | null>(null);\r\n\r\n // Filter states\r\n const [applicationFilter, setApplicationFilter] = useState<string>('all');\r\n const [moduleFilter, setModuleFilter] = useState<string>('all');\r\n\r\n // Super Admin can edit system roles\r\n const canEditSystemRoles = useMemo(() => {\r\n if (!user) return false;\r\n return hasFullAccess(user.permissions);\r\n }, [user]);\r\n\r\n const {\r\n loading,\r\n error,\r\n roles,\r\n filteredResources,\r\n hasChanges,\r\n saving,\r\n saveSuccess,\r\n saveError,\r\n togglePermission,\r\n saveChanges,\r\n resetChanges,\r\n getPermissionInheritance,\r\n } = usePermissionMatrix({ canEditSystemRoles });\r\n\r\n // Find the specific role\r\n const role = useMemo(() => {\r\n return roles.find(r => r.id === roleId);\r\n }, [roles, roleId]);\r\n\r\n // Check if role is editable\r\n const isRoleEditable = useMemo(() => {\r\n if (!role) return false;\r\n if (role.isSystem && !canEditSystemRoles) return false;\r\n return true;\r\n }, [role, canEditSystemRoles]);\r\n\r\n const toggleStatusFilter = (status: PermissionStatus) => {\r\n setStatusFilters(prev => {\r\n const next = new Set(prev);\r\n if (next.has(status)) {\r\n next.delete(status);\r\n } else {\r\n next.add(status);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const toggleModule = (moduleId: string) => {\r\n setCollapsedModules(prev => {\r\n const next = new Set(prev);\r\n if (next.has(moduleId)) {\r\n next.delete(moduleId);\r\n } else {\r\n next.add(moduleId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const toggleSection = (sectionId: string) => {\r\n setCollapsedSections(prev => {\r\n const next = new Set(prev);\r\n if (next.has(sectionId)) {\r\n next.delete(sectionId);\r\n } else {\r\n next.add(sectionId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n // Build filter options from resources\r\n const filterOptions = useMemo(() => {\r\n const applications: { app: string; label: string }[] = [];\r\n const modules: { app: string; module: string; label: string }[] = [];\r\n\r\n filteredResources.forEach(resource => {\r\n if (resource.level === 'module') {\r\n const appKey = resource.applicationLabel;\r\n if (!applications.find(a => a.app === appKey)) {\r\n applications.push({\r\n app: resource.applicationLabel,\r\n label: resource.applicationLabel\r\n });\r\n }\r\n\r\n modules.push({\r\n app: resource.applicationLabel,\r\n module: resource.moduleLabel,\r\n label: resource.moduleLabel\r\n });\r\n }\r\n });\r\n\r\n return {\r\n applications: applications.sort((a, b) => a.label.localeCompare(b.label)),\r\n modules: modules.sort((a, b) => a.label.localeCompare(b.label))\r\n };\r\n }, [filteredResources]);\r\n\r\n // Handle permission toggle\r\n const handleTogglePermission = useCallback((permissionId: string) => {\r\n if (!role || !isRoleEditable) return;\r\n togglePermission(role.id, permissionId);\r\n }, [role, isRoleEditable, togglePermission]);\r\n\r\n // Check if a permission is granted\r\n const isPermissionGrantedFn = useCallback((permissionId: string): boolean => {\r\n if (!role) return false;\r\n const info = getPermissionInheritance(role.id, permissionId);\r\n return info.isDirect || info.isInherited;\r\n }, [role, getPermissionInheritance]);\r\n\r\n // Calculate permission status for this role on a module (including sections)\r\n const getModuleStatus = useCallback((moduleWithSections: ModuleWithSections): { status: PermissionStatus; grantedCount: number; totalCount: number } => {\r\n return calculateModuleWithSectionsStatus(\r\n moduleWithSections.module,\r\n moduleWithSections.sections,\r\n isPermissionGrantedFn\r\n );\r\n }, [isPermissionGrantedFn]);\r\n\r\n // Calculate permission status for a single resource\r\n const getResourceStatus = useCallback((resource: ResourceNode): { status: PermissionStatus; grantedCount: number } => {\r\n return calculatePermissionStatus(resource, isPermissionGrantedFn);\r\n }, [isPermissionGrantedFn]);\r\n\r\n // Get granted permissions for a resource\r\n const getGrantedPermissions = useCallback((resource: ResourceNode): string[] => {\r\n if (!role) return [];\r\n\r\n return resource.permissions\r\n .filter(p => {\r\n const info = getPermissionInheritance(role.id, p.id);\r\n return info.isDirect || info.isInherited;\r\n })\r\n .map(p => p.action);\r\n }, [role, getPermissionInheritance]);\r\n\r\n\r\n const applyApplicationModuleFilter = useCallback((grouped: ReturnType<typeof groupByApplicationWithSections>) => {\r\n return applyApplicationModuleFilterHelper(grouped, applicationFilter, moduleFilter);\r\n }, [applicationFilter, moduleFilter]);\r\n\r\n const applyStatusFilter = useCallback((grouped: ReturnType<typeof groupByApplicationWithSections>) => {\r\n if (statusFilters.size === 0) return grouped;\r\n return applyStatusFilterHelper(grouped, statusFilters, getModuleStatus);\r\n }, [statusFilters, getModuleStatus]);\r\n\r\n const groupedResources = useMemo(() => {\r\n let grouped = groupByApplicationWithSections(filteredResources);\r\n grouped = applyApplicationModuleFilter(grouped);\r\n grouped = applyStatusFilter(grouped);\r\n return grouped;\r\n }, [filteredResources, applyApplicationModuleFilter, applyStatusFilter]);\r\n\r\n // Get total module count for stats\r\n const totalModuleCount = useMemo(() => {\r\n return groupedResources.reduce((sum, app) =>\r\n sum + app.modules.length, 0);\r\n }, [groupedResources]);\r\n\r\n const handleToggleCollapse = useCallback((resourceId: string, level: 'module' | 'section' | 'resource') => {\r\n if (level === 'module') {\r\n toggleModule(resourceId);\r\n } else if (level === 'section') {\r\n toggleSection(resourceId);\r\n }\r\n }, [toggleModule, toggleSection]);\r\n\r\n const handleCellClick = (resourceId: string) => {\r\n if (openPopover === resourceId) {\r\n setOpenPopover(null);\r\n } else {\r\n setOpenPopover(resourceId);\r\n }\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <div className=\"text-center\">\r\n <Loader2 className=\"h-8 w-8 animate-spin text-[var(--color-accent-500)] mx-auto mb-4\" />\r\n <p className=\"text-[var(--text-secondary)]\">{t('userPermissions.loading')}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <p className=\"text-[var(--error-text)]\">{error}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!role) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.notFound')}\r\n </div>\r\n );\r\n }\r\n\r\n const getRoleResourceIcon = (level: 'module' | 'section' | 'resource') => {\r\n if (level === 'resource') return <Database className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n if (level === 'section') return <FileText className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n return <Box className=\"h-3.5 w-3.5 text-[var(--text-secondary)]\" />;\r\n };\r\n\r\n const getRoleResourceLabelClass = (level: 'module' | 'section' | 'resource'): string => {\r\n if (level === 'resource') return 'text-[var(--text-muted)] italic';\r\n if (level === 'section') return 'text-[var(--text-secondary)]';\r\n return 'font-medium text-[var(--text-primary)]';\r\n };\r\n\r\n const getRolePaddingClass = (level: 'module' | 'section' | 'resource'): string => {\r\n if (level === 'resource') return 'pl-28';\r\n if (level === 'section') return 'pl-22';\r\n return 'pl-16';\r\n };\r\n\r\n const renderToggleButton = (hasChildren: boolean, resourceId: string, level: 'module' | 'section' | 'resource', isCollapsed: boolean) => {\r\n if (!hasChildren) return null;\r\n return (\r\n <button\r\n onClick={() => handleToggleCollapse(resourceId, level)}\r\n className=\"p-0.5 hover:bg-[var(--bg-hover)] rounded\"\r\n >\r\n {isCollapsed ? (\r\n <ChevronRight className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n );\r\n };\r\n\r\n const renderPermissionBadges = (grantedPermissions: string[]) => {\r\n if (grantedPermissions.length === 0) {\r\n return (\r\n <span className=\"text-xs text-[var(--text-muted)] italic\">\r\n {t('assignments.noPermissions')}\r\n </span>\r\n );\r\n }\r\n return grantedPermissions.map((action) => {\r\n const actionColor = ACTION_COLORS[action] || 'bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)]';\r\n const icon = ACTION_ICONS[action] || <Eye className=\"h-3 w-3\" />;\r\n return (\r\n <div\r\n key={action}\r\n className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-[var(--radius-badge)] border text-xs font-medium ${actionColor}`}\r\n title={t(`assignments.actions.${action === '*' ? 'all' : action}.description`)}\r\n >\r\n {icon}\r\n <span className=\"capitalize\">\r\n {t(`assignments.actions.${action === '*' ? 'all' : action}.label`)}\r\n </span>\r\n </div>\r\n );\r\n });\r\n };\r\n\r\n const renderResourceRow = (\r\n resource: ResourceNode,\r\n rowIndex: number,\r\n level: 'module' | 'section' | 'resource',\r\n hasChildren: boolean = false,\r\n isCollapsed: boolean = false\r\n ) => {\r\n const { status, grantedCount } = getResourceStatus(resource);\r\n const isPopoverOpen = openPopover === resource.id;\r\n const buttonRef = createRef<HTMLButtonElement>();\r\n const cellBg = getPermissionCellBackground(status);\r\n const grantedPermissions = getGrantedPermissions(resource);\r\n const paddingLeft = getRolePaddingClass(level);\r\n const rowBgClass = rowIndex % 2 === 0 ? 'item-light' : 'item-medium';\r\n\r\n return (\r\n <tr\r\n key={resource.id}\r\n className={`hover:bg-[var(--bg-hover)] ${rowBgClass}`}\r\n >\r\n <td\r\n className={`sticky left-0 z-10 ${rowBgClass} px-3 py-2 ${paddingLeft}`}\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n {renderToggleButton(hasChildren, resource.id, level, isCollapsed)}\r\n {getRoleResourceIcon(level)}\r\n <span className={`text-sm ${getRoleResourceLabelClass(level)}`}>\r\n {resource.moduleLabel}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n ({resource.permissions.length})\r\n </span>\r\n </div>\r\n </td>\r\n\r\n <td\r\n className={`px-0 py-1 text-center relative ${cellBg}`}\r\n style={{ width: '60px', minWidth: '60px', maxWidth: '60px' }}\r\n >\r\n <button\r\n ref={buttonRef}\r\n type=\"button\"\r\n onClick={() => isRoleEditable && handleCellClick(resource.id)}\r\n disabled={!isRoleEditable}\r\n className={`w-full h-full min-h-[36px] flex items-center justify-center rounded transition-colors ${\r\n !isRoleEditable\r\n ? 'cursor-not-allowed opacity-50'\r\n : 'hover:opacity-80'\r\n } ${\r\n isPopoverOpen ? 'ring-2 ring-[var(--color-accent-500)]' : ''\r\n }`}\r\n title={\r\n !isRoleEditable\r\n ? `${role.name} - ${t('assignments.systemRoleReadOnly')}`\r\n : `${role.name} - ${resource.moduleLabel}: ${grantedCount}/${resource.permissions.length}`\r\n }\r\n >\r\n <PermissionStatusIndicator\r\n status={status}\r\n grantedCount={grantedCount}\r\n totalCount={resource.permissions.length}\r\n />\r\n </button>\r\n {isPopoverOpen && isRoleEditable && (\r\n <PermissionPopover\r\n mode=\"editable\"\r\n role={role}\r\n resource={resource}\r\n onTogglePermission={handleTogglePermission}\r\n onClose={() => setOpenPopover(null)}\r\n getPermissionInheritance={(_, permId) => getPermissionInheritance(role.id, permId)}\r\n />\r\n )}\r\n </td>\r\n\r\n <td className=\"px-3 py-2\">\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {renderPermissionBadges(grantedPermissions)}\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Fixed height container for save banner to prevent layout shift */}\r\n <div className=\"min-h-[52px]\">\r\n {saveSuccess && (\r\n <div className=\"flex items-center justify-between p-3 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <Check className=\"h-4 w-4 text-[var(--success-text)]\" />\r\n <p className=\"text-sm text-[var(--success-text)] font-medium\">\r\n {t('common.savedSuccessfully', 'Sauvegardé avec succès !')}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n {!saveSuccess && saving && (\r\n <div className=\"flex items-center justify-between p-3 rounded-[var(--radius-card)] bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <Loader2 className=\"h-4 w-4 animate-spin text-[var(--info-text)]\" />\r\n <p className=\"text-sm text-[var(--info-text)] font-medium\">\r\n {t('common.saving', 'Sauvegarde en cours...')}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n {!saveSuccess && !saving && hasChanges && (\r\n <div className=\"flex items-center justify-between p-3 rounded-[var(--radius-card)] bg-[var(--warning-bg)] border border-[var(--warning-border)]\">\r\n <p className=\"text-sm text-[var(--warning-text)]\">\r\n {t('assignments.unsavedChanges', 'You have unsaved changes')}\r\n </p>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={resetChanges}\r\n disabled={saving}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-50\"\r\n >\r\n <X className=\"h-4 w-4\" />\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={saveChanges}\r\n disabled={saving}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50\"\r\n >\r\n {saving ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Save className=\"h-4 w-4\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n {!saveSuccess && !saving && !hasChanges && (\r\n <div className=\"h-[52px]\" />\r\n )}\r\n </div>\r\n\r\n {/* Save error */}\r\n {saveError && (\r\n <div className=\"p-3 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <AlertCircle className=\"h-4 w-4 text-[var(--error-text)]\" />\r\n <p className=\"text-sm text-[var(--error-text)]\">{saveError}</p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n\r\n {/* Filter Dropdowns */}\r\n <div className=\"flex flex-wrap items-center gap-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <label className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('userPermissions.filters.application')}:\r\n </label>\r\n <select\r\n value={applicationFilter}\r\n onChange={(e) => {\r\n setApplicationFilter(e.target.value);\r\n setModuleFilter('all');\r\n }}\r\n className=\"px-3 py-1.5 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('userPermissions.filters.allApplications')}</option>\r\n {filterOptions.applications\r\n .map(app => (\r\n <option key={app.app} value={app.app}>{app.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <label className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('userPermissions.filters.module')}:\r\n </label>\r\n <select\r\n value={moduleFilter}\r\n onChange={(e) => setModuleFilter(e.target.value)}\r\n className=\"px-3 py-1.5 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('userPermissions.filters.allModules')}</option>\r\n {filterOptions.modules\r\n .filter(mod =>\r\n (applicationFilter === 'all' || mod.app === applicationFilter)\r\n )\r\n .map(mod => (\r\n <option key={`${mod.app}:${mod.module}`} value={mod.module}>{mod.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n\r\n {/* Status Filter Buttons - Using CSS variables for colors */}\r\n <div className=\"flex flex-wrap items-center gap-3\">\r\n <span className=\"text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('userPermissions.filterByStatus')}:\r\n </span>\r\n <div className=\"flex flex-wrap gap-2\">\r\n <button\r\n onClick={() => toggleStatusFilter('all')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('all')\r\n ? 'bg-[var(--success-bg)] border-[var(--success-border)] text-[var(--success-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--success-border)]'\r\n }`}\r\n >\r\n <Check className={`h-3.5 w-3.5 ${statusFilters.has('all') ? '' : 'text-[var(--success-dot)]'}`} />\r\n {t('assignments.complete')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('some')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('some')\r\n ? 'bg-[var(--warning-bg)] border-[var(--warning-border)] text-[var(--warning-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--warning-border)]'\r\n }`}\r\n >\r\n <Star className={`h-3.5 w-3.5 ${statusFilters.has('some') ? '' : 'text-[var(--warning-dot)]'}`} />\r\n {t('assignments.partial')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('read-only')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('read-only')\r\n ? 'bg-[var(--info-bg)] border-[var(--info-border)] text-[var(--info-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--info-border)]'\r\n }`}\r\n >\r\n <Eye className={`h-3.5 w-3.5 ${statusFilters.has('read-only') ? '' : 'text-[var(--info-dot)]'}`} />\r\n {t('assignments.readOnly')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('none')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('none')\r\n ? 'bg-[var(--error-bg)] border-[var(--error-border)] text-[var(--error-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--error-border)]'\r\n }`}\r\n >\r\n <Ban className={`h-3.5 w-3.5 ${statusFilters.has('none') ? '' : 'text-[var(--text-muted)]'}`} />\r\n {t('assignments.none')}\r\n </button>\r\n </div>\r\n {statusFilters.size > 0 && (\r\n <button\r\n onClick={() => setStatusFilters(new Set())}\r\n className=\"text-xs text-[var(--color-accent-500)] hover:text-[var(--color-accent-600)] underline\"\r\n >\r\n {t('assignments.clearFilters')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Stats */}\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--bg-tertiary)] text-[var(--text-secondary)]\">\r\n {totalModuleCount} {t('assignments.modules')}\r\n </span>\r\n </div>\r\n\r\n {/* Permission Matrix Table - Same style as PermissionMatrixTable */}\r\n <div className=\"overflow-x-auto overflow-y-visible\">\r\n <table className=\"border-collapse\" style={{ width: 'auto' }}>\r\n <thead className=\"item-medium border-b border-[var(--item-color-border)]\">\r\n <tr>\r\n <th\r\n scope=\"col\"\r\n className=\"sticky left-0 z-20 item-medium px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('assignments.resource')}\r\n </th>\r\n <th\r\n scope=\"col\"\r\n className=\"px-2 text-center text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ width: '60px', minWidth: '60px', maxWidth: '60px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('userPermissions.status')}\r\n </th>\r\n <th\r\n scope=\"col\"\r\n className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('assignments.permissions')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--item-color-border)]\">\r\n {groupedResources.map((appGroup) => {\r\n const appKey = appGroup.application;\r\n const isAppCollapsed = collapsedApps.has(appKey);\r\n\r\n return (\r\n <React.Fragment key={appKey}>\r\n {/* Application Header Row */}\r\n <tr className=\"bg-[var(--bg-tertiary)]\">\r\n <td\r\n className=\"sticky left-0 z-10 px-3 py-2 bg-[var(--bg-tertiary)]\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <button\r\n onClick={() => toggleApp(appKey)}\r\n className=\"flex items-center gap-3 w-full text-left hover:opacity-80\"\r\n >\r\n {isAppCollapsed ? (\r\n <ChevronRight className=\"h-4 w-4 text-[var(--text-secondary)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-4 w-4 text-[var(--text-secondary)]\" />\r\n )}\r\n <FolderOpen className=\"h-4 w-4 text-[var(--text-secondary)]\" />\r\n <span className=\"text-sm font-semibold text-[var(--text-primary)]\">\r\n {appGroup.application}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)] ml-auto\">\r\n {appGroup.modules.length} module{appGroup.modules.length > 1 ? 's' : ''}\r\n </span>\r\n </button>\r\n </td>\r\n <td className=\"px-0 py-2\" />\r\n <td className=\"px-0 py-2\" />\r\n </tr>\r\n\r\n {/* Module, Section and Resource Rows */}\r\n {!isAppCollapsed && appGroup.modules.map((moduleWithSections, moduleIndex) => {\r\n const { module, sections } = moduleWithSections;\r\n const hasSections = sections.length > 0;\r\n const isModuleCollapsed = collapsedModules.has(module.id);\r\n\r\n return (\r\n <React.Fragment key={module.id}>\r\n {/* Module Row */}\r\n {renderResourceRow(module, moduleIndex, 'module', hasSections, isModuleCollapsed)}\r\n\r\n {/* Section and Resource Rows (if module has sections and is not collapsed) */}\r\n {hasSections && !isModuleCollapsed && sections.map((sectionWithResources, sectionIndex) => {\r\n const { section, resources } = sectionWithResources;\r\n\r\n return (\r\n <SectionResourceRows\r\n key={section.id}\r\n section={section}\r\n resources={resources}\r\n moduleIndex={moduleIndex}\r\n sectionIndex={sectionIndex}\r\n collapsedSections={collapsedSections}\r\n renderResourceRow={renderResourceRow}\r\n />\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n {totalModuleCount === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('assignments.noResources')}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useParams, useNavigate, Link } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n ArrowLeft,\r\n Shield,\r\n Users,\r\n Settings,\r\n Loader2,\r\n Save,\r\n Lock,\r\n AlertTriangle,\r\n CheckCircle,\r\n Languages,\r\n Plus,\r\n Trash2,\r\n Edit2,\r\n X,\r\n UsersRound,\r\n Search\r\n} from 'lucide-react';\r\nimport {\r\n adminApi,\r\n type RoleDetailDto,\r\n type RoleListDto,\r\n type UpdateRoleRequest,\r\n type RoleTranslationDto,\r\n type UpdateRoleTranslationRequest,\r\n type RoleCategory,\r\n type UserListDto\r\n} from '@/services/api/adminApi';\r\nimport { groupsApi, type GroupListDto } from '@/services/api/groupsApi';\r\nimport { RolePermissionMatrix } from '@/components/platform/administration/permissions/RolePermissionMatrix';\r\n\r\ntype TabId = 'info' | 'permissions' | 'users' | 'groups' | 'translations';\r\n\r\nconst SUPPORTED_LANGUAGES = [\r\n { code: 'fr', label: 'Français' },\r\n { code: 'en', label: 'English' },\r\n { code: 'it', label: 'Italiano' },\r\n { code: 'de', label: 'Deutsch' }\r\n];\r\n\r\nexport function RoleDetailPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const { id: roleId } = useParams<{ id: string }>();\r\n const navigate = useNavigate();\r\n\r\n const [role, setRole] = useState<RoleDetailDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [activeTab, setActiveTab] = useState<TabId>('info');\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n\r\n const [formData, setFormData] = useState({\r\n name: '',\r\n shortName: '',\r\n category: 'Custom' as RoleCategory,\r\n description: '',\r\n parentRoleId: null as string | null\r\n });\r\n const [availableRoles, setAvailableRoles] = useState<RoleListDto[]>([]);\r\n\r\n const ROLE_CATEGORIES: RoleCategory[] = ['Global', 'Admin', 'Manager', 'Contributor', 'Viewer', 'Custom'];\r\n\r\n // Translation state\r\n const [translations, setTranslations] = useState<RoleTranslationDto[]>([]);\r\n const [loadingTranslations, setLoadingTranslations] = useState(false);\r\n const [editingTranslation, setEditingTranslation] = useState<string | null>(null);\r\n const [translationForm, setTranslationForm] = useState<UpdateRoleTranslationRequest>({\r\n name: '',\r\n shortName: '',\r\n description: ''\r\n });\r\n const [savingTranslation, setSavingTranslation] = useState(false);\r\n const [showAddTranslation, setShowAddTranslation] = useState(false);\r\n const [newTranslationLang, setNewTranslationLang] = useState('');\r\n\r\n // User assignment state\r\n const [addingUser, setAddingUser] = useState(false);\r\n const [availableUsers, setAvailableUsers] = useState<UserListDto[]>([]);\r\n const [loadingUsers, setLoadingUsers] = useState(false);\r\n const [userSearchTerm, setUserSearchTerm] = useState('');\r\n const [selectedUserId, setSelectedUserId] = useState<string | null>(null);\r\n const [assigningUser, setAssigningUser] = useState(false);\r\n const [removingUserId, setRemovingUserId] = useState<string | null>(null);\r\n\r\n // Group assignment state\r\n const [addingGroup, setAddingGroup] = useState(false);\r\n const [availableGroups, setAvailableGroups] = useState<GroupListDto[]>([]);\r\n const [loadingGroups, setLoadingGroups] = useState(false);\r\n const [groupSearchTerm, setGroupSearchTerm] = useState('');\r\n const [selectedGroupId, setSelectedGroupId] = useState<string | null>(null);\r\n const [assigningGroup, setAssigningGroup] = useState(false);\r\n const [removingGroupId, setRemovingGroupId] = useState<string | null>(null);\r\n\r\n const loadRole = useCallback(async () => {\r\n if (!roleId) return;\r\n try {\r\n setLoading(true);\r\n const [roleData, rolesData] = await Promise.all([\r\n adminApi.roles.getById(roleId),\r\n adminApi.roles.getAll()\r\n ]);\r\n setRole(roleData);\r\n // Filter out current role from available parent roles\r\n setAvailableRoles(rolesData.filter(r => r.id !== roleId));\r\n setFormData({\r\n name: roleData.name,\r\n shortName: roleData.shortName,\r\n category: roleData.category,\r\n description: roleData.description || '',\r\n parentRoleId: roleData.parentRoleId\r\n });\r\n } catch (err) {\r\n console.error('Failed to load role:', err);\r\n setError(t('roleDetail.errors.loadFailed'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [roleId, t]);\r\n\r\n useEffect(() => {\r\n loadRole();\r\n }, [loadRole]);\r\n\r\n const handleSaveInfo = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!roleId || !role) return;\r\n\r\n setSaving(true);\r\n setError(null);\r\n setSuccess(null);\r\n\r\n try {\r\n const updateData: UpdateRoleRequest = {\r\n name: formData.name,\r\n shortName: formData.shortName,\r\n category: formData.category,\r\n description: formData.description || undefined,\r\n parentRoleId: formData.parentRoleId || undefined\r\n };\r\n await adminApi.roles.update(roleId, updateData);\r\n setSuccess(t('roleDetail.success.saved'));\r\n loadRole();\r\n } catch (err: unknown) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.saveFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n // Translation functions\r\n const loadTranslations = useCallback(async () => {\r\n if (!roleId) return;\r\n setLoadingTranslations(true);\r\n try {\r\n const data = await adminApi.roles.getTranslations(roleId);\r\n setTranslations(data);\r\n } catch (err) {\r\n console.error('Failed to load translations:', err);\r\n } finally {\r\n setLoadingTranslations(false);\r\n }\r\n }, [roleId]);\r\n\r\n useEffect(() => {\r\n if (activeTab === 'translations' && translations.length === 0) {\r\n loadTranslations();\r\n }\r\n }, [activeTab, translations.length, loadTranslations]);\r\n\r\n const startEditTranslation = (trans: RoleTranslationDto) => {\r\n setEditingTranslation(trans.languageCode);\r\n setTranslationForm({\r\n name: trans.name,\r\n shortName: trans.shortName,\r\n description: trans.description || ''\r\n });\r\n };\r\n\r\n const cancelEditTranslation = () => {\r\n setEditingTranslation(null);\r\n setShowAddTranslation(false);\r\n setTranslationForm({ name: '', shortName: '', description: '' });\r\n setNewTranslationLang('');\r\n };\r\n\r\n const handleSaveTranslation = async (languageCode: string) => {\r\n if (!roleId) return;\r\n setSavingTranslation(true);\r\n setError(null);\r\n try {\r\n await adminApi.roles.upsertTranslation(roleId, languageCode, translationForm);\r\n setSuccess(t('roleDetail.translations.saved'));\r\n setEditingTranslation(null);\r\n setShowAddTranslation(false);\r\n setNewTranslationLang('');\r\n loadTranslations();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.saveFailed'));\r\n } finally {\r\n setSavingTranslation(false);\r\n }\r\n };\r\n\r\n const handleDeleteTranslation = async (languageCode: string) => {\r\n if (!roleId) return;\r\n if (!confirm(t('roleDetail.translations.confirmDelete'))) return;\r\n try {\r\n await adminApi.roles.deleteTranslation(roleId, languageCode);\r\n setSuccess(t('roleDetail.translations.deleted'));\r\n loadTranslations();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.saveFailed'));\r\n }\r\n };\r\n\r\n const availableLanguages = SUPPORTED_LANGUAGES.filter(\r\n lang => !translations.some(t => t.languageCode === lang.code)\r\n );\r\n\r\n // User assignment functions\r\n const openAddUser = async () => {\r\n setAddingUser(true);\r\n setSelectedUserId(null);\r\n setUserSearchTerm('');\r\n setLoadingUsers(true);\r\n try {\r\n const data = await adminApi.users.getAll({ globalScope: true });\r\n setAvailableUsers(data.items);\r\n } catch (err) {\r\n console.error('Failed to load users:', err);\r\n } finally {\r\n setLoadingUsers(false);\r\n }\r\n };\r\n\r\n const handleAssignUser = async () => {\r\n if (!roleId || !selectedUserId) return;\r\n setAssigningUser(true);\r\n try {\r\n await adminApi.roles.assignUser(roleId, selectedUserId);\r\n setAddingUser(false);\r\n setSelectedUserId(null);\r\n setSuccess(t('roleDetail.users.assigned'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.assignFailed'));\r\n } finally {\r\n setAssigningUser(false);\r\n }\r\n };\r\n\r\n const handleRemoveUser = async (userId: string) => {\r\n if (!roleId) return;\r\n if (!confirm(t('roleDetail.users.confirmRemove'))) return;\r\n setRemovingUserId(userId);\r\n try {\r\n await adminApi.roles.removeUser(roleId, userId);\r\n setSuccess(t('roleDetail.users.removed'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.removeFailed'));\r\n } finally {\r\n setRemovingUserId(null);\r\n }\r\n };\r\n\r\n // Group assignment functions\r\n const openAddGroup = async () => {\r\n setAddingGroup(true);\r\n setSelectedGroupId(null);\r\n setGroupSearchTerm('');\r\n setLoadingGroups(true);\r\n try {\r\n const data = await groupsApi.getAll();\r\n setAvailableGroups(data);\r\n } catch (err) {\r\n console.error('Failed to load groups:', err);\r\n } finally {\r\n setLoadingGroups(false);\r\n }\r\n };\r\n\r\n const handleAssignGroup = async () => {\r\n if (!roleId || !selectedGroupId) return;\r\n setAssigningGroup(true);\r\n try {\r\n await adminApi.roles.assignGroup(roleId, selectedGroupId);\r\n setAddingGroup(false);\r\n setSelectedGroupId(null);\r\n setSuccess(t('roleDetail.groups.assigned'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.assignFailed'));\r\n } finally {\r\n setAssigningGroup(false);\r\n }\r\n };\r\n\r\n const handleRemoveGroup = async (groupId: string) => {\r\n if (!roleId) return;\r\n if (!confirm(t('roleDetail.groups.confirmRemove'))) return;\r\n setRemovingGroupId(groupId);\r\n try {\r\n await adminApi.roles.removeGroup(roleId, groupId);\r\n setSuccess(t('roleDetail.groups.removed'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.removeFailed'));\r\n } finally {\r\n setRemovingGroupId(null);\r\n }\r\n };\r\n\r\n const tabs: { id: TabId; label: string; icon: React.ReactNode }[] = [\r\n { id: 'info', label: t('roleDetail.tabs.info'), icon: <Settings className=\"w-4 h-4\" /> },\r\n { id: 'permissions', label: t('roleDetail.tabs.permissions'), icon: <Shield className=\"w-4 h-4\" /> },\r\n { id: 'users', label: t('roleDetail.tabs.users'), icon: <Users className=\"w-4 h-4\" /> },\r\n { id: 'groups', label: t('roleDetail.tabs.groups'), icon: <UsersRound className=\"w-4 h-4\" /> },\r\n { id: 'translations', label: t('roleDetail.tabs.translations'), icon: <Languages className=\"w-4 h-4\" /> }\r\n ];\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center h-64\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (!role) {\r\n return (\r\n <div className=\"text-center py-12\">\r\n <p className=\"text-[var(--text-secondary)]\">{t('roleDetail.notFound')}</p>\r\n <button\r\n onClick={() => navigate('/administration/permissions/roles')}\r\n className=\"mt-4 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white\"\r\n >\r\n {t('roleDetail.backToList')}\r\n </button>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('roles.title', 'Roles'), href: '/administration/permissions/roles' },\r\n { label: role?.name || 'Detail' }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center gap-4\">\r\n <button\r\n onClick={() => navigate('/administration/permissions/roles')}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <ArrowLeft className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-3\">\r\n <h1 className=\"text-xl sm:text-2xl font-bold text-[var(--text-primary)]\">{role.name}</h1>\r\n {role.isSystem && (\r\n <span className=\"flex items-center gap-1 px-2 py-1 rounded-[var(--radius-badge)] text-xs bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n <Lock className=\"w-3 h-3\" />\r\n {t('roles.system')}\r\n </span>\r\n )}\r\n </div>\r\n {role.description && (\r\n <p className=\"text-sm sm:text-base text-[var(--text-secondary)] mt-1\">{role.description}</p>\r\n )}\r\n </div>\r\n <div className=\"flex items-center gap-4 text-sm text-[var(--text-secondary)]\">\r\n <div className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n <span>{role.users.length} {t('roleDetail.usersCount')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n <UsersRound className=\"w-4 h-4\" />\r\n <span>{role.groups?.length || 0} {t('roleDetail.groupsCount')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n <Shield className=\"w-4 h-4\" />\r\n <span>{role.permissions.length} {t('roles.permissions')}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Alerts */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] text-[var(--error-text)] flex items-center gap-2\">\r\n <AlertTriangle className=\"w-5 h-5 flex-shrink-0\" />\r\n {error}\r\n </div>\r\n )}\r\n {success && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)] text-[var(--success-text)] flex items-center gap-2\">\r\n <CheckCircle className=\"w-5 h-5 flex-shrink-0\" />\r\n {success}\r\n </div>\r\n )}\r\n\r\n\r\n {/* Tabs */}\r\n <div className=\"flex gap-1 p-1 bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)]\">\r\n {tabs.map(tab => (\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-2 rounded-[var(--radius-button)] font-medium transition-colors ${\r\n activeTab === tab.id\r\n ? 'bg-[var(--color-accent-600)] text-white'\r\n : 'text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n {tab.icon}\r\n <span className=\"hidden sm:inline\">{tab.label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Tab Content */}\r\n <div className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4 sm:p-6\">\r\n {/* Info Tab */}\r\n {activeTab === 'info' && (\r\n <form onSubmit={handleSaveInfo} className=\"space-y-6 max-w-2xl\">\r\n {/* ID (read-only) */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.id')}\r\n </label>\r\n <div className=\"px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-tertiary)] text-[var(--text-secondary)] font-mono text-sm\">\r\n {role.id}\r\n </div>\r\n </div>\r\n\r\n {/* Name */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roles.form.name')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.name}\r\n onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Short Name */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.shortName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.shortName}\r\n onChange={e => setFormData(prev => ({ ...prev, shortName: e.target.value }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n <p className=\"mt-1 text-xs text-[var(--text-tertiary)]\">\r\n {t('roleDetail.info.shortNameHelp')}\r\n </p>\r\n </div>\r\n\r\n {/* Category */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.category')} *\r\n </label>\r\n <select\r\n value={formData.category}\r\n onChange={e => setFormData(prev => ({ ...prev, category: e.target.value as RoleCategory }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n {ROLE_CATEGORIES.map(cat => (\r\n <option key={cat} value={cat}>\r\n {t(`roleDetail.categories.${cat.toLowerCase()}`)}\r\n </option>\r\n ))}\r\n </select>\r\n <p className=\"mt-1 text-xs text-[var(--text-tertiary)]\">\r\n {t('roleDetail.info.categoryHelp')}\r\n </p>\r\n </div>\r\n\r\n {/* Parent Role */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.parentRole')}\r\n </label>\r\n <select\r\n value={formData.parentRoleId || ''}\r\n onChange={e => setFormData(prev => ({ ...prev, parentRoleId: e.target.value || null }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"\">{t('roleDetail.info.noParent')}</option>\r\n {availableRoles.map(r => (\r\n <option key={r.id} value={r.id}>\r\n {r.name} ({t(`roleDetail.categories.${r.category.toLowerCase()}`)})\r\n </option>\r\n ))}\r\n </select>\r\n <p className=\"mt-1 text-xs text-[var(--text-tertiary)]\">\r\n {t('roleDetail.info.parentRoleHelp')}\r\n </p>\r\n </div>\r\n\r\n {/* Description */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roles.form.description')}\r\n </label>\r\n <textarea\r\n value={formData.description}\r\n onChange={e => setFormData(prev => ({ ...prev, description: e.target.value }))}\r\n rows={3}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] resize-none\"\r\n />\r\n </div>\r\n\r\n {/* System Role Badge */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.systemRole')}\r\n </label>\r\n <div className=\"flex items-center gap-2\">\r\n {role.isSystem ? (\r\n <span className=\"flex items-center gap-1.5 px-3 py-1.5 rounded-[var(--radius-badge)] text-sm bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n <Lock className=\"w-4 h-4\" />\r\n {t('roleDetail.info.isSystemRole')}\r\n </span>\r\n ) : (\r\n <span className=\"flex items-center gap-1.5 px-3 py-1.5 rounded-[var(--radius-badge)] text-sm bg-[var(--bg-tertiary)] text-[var(--text-secondary)]\">\r\n {t('roleDetail.info.isCustomRole')}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Metadata */}\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4 pt-4 border-t border-[var(--border-color)]\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.createdAt')}\r\n </label>\r\n <div className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(role.createdAt).toLocaleString()}\r\n </div>\r\n </div>\r\n {role.updatedAt && (\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.updatedAt')}\r\n </label>\r\n <div className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(role.updatedAt).toLocaleString()}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex justify-end pt-4\">\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white font-medium transition-colors disabled:opacity-50\"\r\n >\r\n {saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </form>\r\n )}\r\n\r\n {/* Permissions Tab - Matrix View */}\r\n {activeTab === 'permissions' && roleId && (\r\n <RolePermissionMatrix roleId={roleId} />\r\n )}\r\n\r\n {/* Groups Tab */}\r\n {activeTab === 'groups' && (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('roleDetail.groups.title')} ({role.groups?.length || 0})\r\n </h3>\r\n <button\r\n onClick={openAddGroup}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('roleDetail.groups.add')}\r\n </button>\r\n </div>\r\n\r\n {(!role.groups || role.groups.length === 0) ? (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.groups.noGroups')}\r\n </div>\r\n ) : (\r\n <div className=\"grid gap-3\">\r\n {role.groups.map(group => (\r\n <div\r\n key={group.id}\r\n className=\"flex items-center gap-4 p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Link\r\n to={`/administration/users/groups/${group.id}`}\r\n className=\"flex items-center gap-4 flex-1 min-w-0 hover:opacity-80 transition-opacity\"\r\n >\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-100)] flex items-center justify-center\">\r\n <UsersRound className=\"w-5 h-5 text-[var(--color-accent-700)]\" />\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"font-medium text-[var(--text-primary)] truncate\">{group.name}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)] truncate\">\r\n {group.membersCount} {t('roleDetail.groups.members')}\r\n {group.description && ` · ${group.description}`}\r\n </div>\r\n </div>\r\n </Link>\r\n <button\r\n onClick={() => handleRemoveGroup(group.id)}\r\n disabled={removingGroupId === group.id}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--error-text)] transition-colors disabled:opacity-50\"\r\n title={t('roleDetail.groups.remove')}\r\n >\r\n {removingGroupId === group.id ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Add Group Modal */}\r\n {addingGroup && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\r\n <div className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] w-full max-w-md p-6 m-4 max-h-[90vh] overflow-y-auto\">\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">\r\n {t('roleDetail.groups.addTitle')}\r\n </h2>\r\n <button\r\n onClick={() => setAddingGroup(false)}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-tertiary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"mb-4\">\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-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n value={groupSearchTerm}\r\n onChange={(e) => setGroupSearchTerm(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n placeholder={t('roleDetail.groups.searchPlaceholder')}\r\n />\r\n </div>\r\n </div>\r\n\r\n {loadingGroups ? (\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 </div>\r\n ) : (\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {availableGroups\r\n .filter(g =>\r\n !role.groups?.some(rg => rg.id === g.id) &&\r\n (groupSearchTerm === '' ||\r\n g.name.toLowerCase().includes(groupSearchTerm.toLowerCase()) ||\r\n (g.description || '').toLowerCase().includes(groupSearchTerm.toLowerCase()))\r\n )\r\n .map(group => (\r\n <label\r\n key={group.id}\r\n className={`flex items-center gap-3 cursor-pointer p-3 rounded-[var(--radius-button)] transition-colors ${\r\n selectedGroupId === group.id\r\n ? 'bg-[var(--color-accent-500)]/10 border border-[var(--color-accent-500)]'\r\n : 'hover:bg-[var(--bg-hover)] border border-transparent'\r\n }`}\r\n htmlFor={`group-${group.id}`}\r\n >\r\n <input\r\n id={`group-${group.id}`}\r\n type=\"radio\"\r\n name=\"selectedGroup\"\r\n checked={selectedGroupId === group.id}\r\n onChange={() => setSelectedGroupId(group.id)}\r\n className=\"w-4 h-4 text-[var(--color-accent-600)] focus:ring-[var(--color-accent-500)]\"\r\n />\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"text-[var(--text-primary)] font-medium\">{group.name}</span>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {group.memberCount} {t('roleDetail.groups.members')}\r\n {group.description && ` · ${group.description}`}\r\n </p>\r\n </div>\r\n </label>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex justify-end gap-3 mt-6\">\r\n <button\r\n onClick={() => setAddingGroup(false)}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] font-medium transition-colors\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={handleAssignGroup}\r\n disabled={!selectedGroupId || assigningGroup}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white font-medium transition-colors disabled:opacity-50\"\r\n >\r\n {assigningGroup && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.add')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Users Tab */}\r\n {activeTab === 'users' && (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('roleDetail.users.title')} ({role.users.length})\r\n </h3>\r\n <button\r\n onClick={openAddUser}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('roleDetail.users.add')}\r\n </button>\r\n </div>\r\n\r\n {role.users.length === 0 ? (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.users.noUsers')}\r\n </div>\r\n ) : (\r\n <div className=\"grid gap-3\">\r\n {role.users.map(user => (\r\n <div\r\n key={user.id}\r\n className=\"flex items-center gap-4 p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Link\r\n to={`/administration/users/${user.id}`}\r\n className=\"flex items-center gap-4 flex-1 min-w-0 hover:opacity-80 transition-opacity\"\r\n >\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-100)] flex items-center justify-center\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-700)]\">\r\n {user.fullName.split(' ').map(n => n.at(0)).join('').toUpperCase().slice(0, 2)}\r\n </span>\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"font-medium text-[var(--text-primary)] truncate\">{user.fullName}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)] truncate\">{user.email}</div>\r\n </div>\r\n </Link>\r\n <button\r\n onClick={() => handleRemoveUser(user.id)}\r\n disabled={removingUserId === user.id}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--error-text)] transition-colors disabled:opacity-50\"\r\n title={t('roleDetail.users.remove')}\r\n >\r\n {removingUserId === user.id ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Add User Modal */}\r\n {addingUser && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\r\n <div className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] w-full max-w-md p-6 m-4 max-h-[90vh] overflow-y-auto\">\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">\r\n {t('roleDetail.users.addTitle')}\r\n </h2>\r\n <button\r\n onClick={() => setAddingUser(false)}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-tertiary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"mb-4\">\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-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n value={userSearchTerm}\r\n onChange={(e) => setUserSearchTerm(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n placeholder={t('roleDetail.users.searchPlaceholder')}\r\n />\r\n </div>\r\n </div>\r\n\r\n {loadingUsers ? (\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 </div>\r\n ) : (\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {availableUsers\r\n .filter(u =>\r\n !role.users.some(ru => ru.id === u.id) &&\r\n (userSearchTerm === '' ||\r\n u.fullName.toLowerCase().includes(userSearchTerm.toLowerCase()) ||\r\n u.email.toLowerCase().includes(userSearchTerm.toLowerCase()))\r\n )\r\n .map(user => (\r\n <label\r\n key={user.id}\r\n className={`flex items-center gap-3 cursor-pointer p-3 rounded-[var(--radius-button)] transition-colors ${\r\n selectedUserId === user.id\r\n ? 'bg-[var(--color-accent-500)]/10 border border-[var(--color-accent-500)]'\r\n : 'hover:bg-[var(--bg-hover)] border border-transparent'\r\n }`}\r\n htmlFor={`user-${user.id}`}\r\n >\r\n <input\r\n id={`user-${user.id}`}\r\n type=\"radio\"\r\n name=\"selectedUser\"\r\n checked={selectedUserId === user.id}\r\n onChange={() => setSelectedUserId(user.id)}\r\n className=\"w-4 h-4 text-[var(--color-accent-600)] focus:ring-[var(--color-accent-500)]\"\r\n />\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"text-[var(--text-primary)] font-medium\">{user.fullName}</span>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{user.email}</p>\r\n </div>\r\n </label>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex justify-end gap-3 mt-6\">\r\n <button\r\n onClick={() => setAddingUser(false)}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] font-medium transition-colors\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={handleAssignUser}\r\n disabled={!selectedUserId || assigningUser}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white font-medium transition-colors disabled:opacity-50\"\r\n >\r\n {assigningUser && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.add')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Translations Tab */}\r\n {activeTab === 'translations' && (\r\n <div className=\"space-y-6\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('roleDetail.translations.title')} ({translations.length})\r\n </h3>\r\n {availableLanguages.length > 0 && (\r\n <button\r\n onClick={() => setShowAddTranslation(true)}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('roleDetail.translations.add')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Add new translation form */}\r\n {showAddTranslation && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--color-accent-500)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h4 className=\"font-medium text-[var(--text-primary)]\">\r\n {t('roleDetail.translations.addNew')}\r\n </h4>\r\n <button\r\n onClick={cancelEditTranslation}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)]\"\r\n >\r\n <X className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n </button>\r\n </div>\r\n <div className=\"grid gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.language')}\r\n </label>\r\n <select\r\n value={newTranslationLang}\r\n onChange={e => setNewTranslationLang(e.target.value)}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n >\r\n <option value=\"\">{t('roleDetail.translations.selectLanguage')}</option>\r\n {availableLanguages.map(lang => (\r\n <option key={lang.code} value={lang.code}>{lang.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n {newTranslationLang && (\r\n <>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.name')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.name}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, name: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.shortName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.shortName}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, shortName: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.description')}\r\n </label>\r\n <textarea\r\n value={translationForm.description || ''}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, description: e.target.value }))}\r\n rows={2}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n onClick={cancelEditTranslation}\r\n className=\"px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] text-sm font-medium\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={() => handleSaveTranslation(newTranslationLang)}\r\n disabled={savingTranslation || !translationForm.name || !translationForm.shortName}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium disabled:opacity-50\"\r\n >\r\n {savingTranslation && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {loadingTranslations && (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <Loader2 className=\"w-6 h-6 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loadingTranslations && translations.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.translations.noTranslations')}\r\n </div>\r\n )}\r\n {!loadingTranslations && translations.length > 0 && (\r\n <div className=\"space-y-3\">\r\n {translations.map(trans => {\r\n const langInfo = SUPPORTED_LANGUAGES.find(l => l.code === trans.languageCode);\r\n const isEditing = editingTranslation === trans.languageCode;\r\n\r\n return (\r\n <div\r\n key={trans.languageCode}\r\n className={`p-4 rounded-[var(--radius-card)] border ${\r\n isEditing\r\n ? 'bg-[var(--bg-primary)] border-[var(--color-accent-500)]'\r\n : 'bg-[var(--bg-primary)] border-[var(--border-color)]'\r\n }`}\r\n >\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"px-2 py-0.5 text-xs font-medium rounded bg-[var(--bg-tertiary)] text-[var(--text-secondary)] uppercase\">\r\n {trans.languageCode}\r\n </span>\r\n <span className=\"text-sm text-[var(--text-secondary)]\">\r\n {langInfo?.label || trans.languageCode}\r\n </span>\r\n </div>\r\n {!isEditing && (\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => startEditTranslation(trans)}\r\n className=\"p-1.5 rounded hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--color-accent-600)]\"\r\n title={t('common.edit')}\r\n >\r\n <Edit2 className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => handleDeleteTranslation(trans.languageCode)}\r\n className=\"p-1.5 rounded hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--error-text)]\"\r\n title={t('common.delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {isEditing ? (\r\n <div className=\"grid gap-3 mt-3\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.name')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.name}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, name: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.shortName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.shortName}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, shortName: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.description')}\r\n </label>\r\n <textarea\r\n value={translationForm.description || ''}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, description: e.target.value }))}\r\n rows={2}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n onClick={cancelEditTranslation}\r\n className=\"px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] text-sm font-medium\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={() => handleSaveTranslation(trans.languageCode)}\r\n disabled={savingTranslation || !translationForm.name || !translationForm.shortName}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium disabled:opacity-50\"\r\n >\r\n {savingTranslation && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"grid gap-1\">\r\n <div className=\"font-medium text-[var(--text-primary)]\">{trans.name}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('roleDetail.translations.shortName')}: {trans.shortName}\r\n </div>\r\n {trans.description && (\r\n <div className=\"text-sm text-[var(--text-tertiary)] mt-1\">{trans.description}</div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["ACTION_ICONS","jsx","Shield","Eye","Plus","Edit","Trash2","UserPlus","Play","ACTION_COLORS","applyApplicationModuleFilterHelper","grouped","applicationFilter","moduleFilter","app","m","applyStatusFilterHelper","statusFilters","getModuleStatus","status","SectionResourceRows","section","resources","moduleIndex","sectionIndex","collapsedSections","renderResourceRow","hasResources","isSectionCollapsed","jsxs","React","resource","resourceIndex","RolePermissionMatrix","roleId","t","useTranslation","user","useAuth","collapsedApps","toggleApp","useCollapsibleState","collapsedModules","setCollapsedModules","useState","setCollapsedSections","setStatusFilters","openPopover","setOpenPopover","setApplicationFilter","setModuleFilter","canEditSystemRoles","useMemo","hasFullAccess","loading","error","roles","filteredResources","hasChanges","saving","saveSuccess","saveError","togglePermission","saveChanges","resetChanges","getPermissionInheritance","usePermissionMatrix","role","r","isRoleEditable","toggleStatusFilter","prev","next","toggleModule","moduleId","toggleSection","sectionId","filterOptions","applications","modules","appKey","a","b","handleTogglePermission","useCallback","permissionId","isPermissionGrantedFn","info","moduleWithSections","calculateModuleWithSectionsStatus","getResourceStatus","calculatePermissionStatus","getGrantedPermissions","p","applyApplicationModuleFilter","applyStatusFilter","groupedResources","groupByApplicationWithSections","totalModuleCount","sum","handleToggleCollapse","resourceId","level","handleCellClick","Loader2","AlertCircle","getRoleResourceIcon","Database","FileText","Box","getRoleResourceLabelClass","getRolePaddingClass","renderToggleButton","hasChildren","isCollapsed","ChevronRight","ChevronDown","renderPermissionBadges","grantedPermissions","action","actionColor","icon","rowIndex","grantedCount","isPopoverOpen","buttonRef","createRef","cellBg","getPermissionCellBackground","paddingLeft","rowBgClass","PermissionStatusIndicator","PermissionPopover","_","permId","Check","X","Save","e","mod","Star","Ban","appGroup","isAppCollapsed","FolderOpen","module","sections","hasSections","isModuleCollapsed","sectionWithResources","SUPPORTED_LANGUAGES","RoleDetailPage","useParams","navigate","useNavigate","setRole","setLoading","setSaving","activeTab","setActiveTab","setError","success","setSuccess","formData","setFormData","availableRoles","setAvailableRoles","ROLE_CATEGORIES","translations","setTranslations","loadingTranslations","setLoadingTranslations","editingTranslation","setEditingTranslation","translationForm","setTranslationForm","savingTranslation","setSavingTranslation","showAddTranslation","setShowAddTranslation","newTranslationLang","setNewTranslationLang","addingUser","setAddingUser","availableUsers","setAvailableUsers","loadingUsers","setLoadingUsers","userSearchTerm","setUserSearchTerm","selectedUserId","setSelectedUserId","assigningUser","setAssigningUser","removingUserId","setRemovingUserId","addingGroup","setAddingGroup","availableGroups","setAvailableGroups","loadingGroups","setLoadingGroups","groupSearchTerm","setGroupSearchTerm","selectedGroupId","setSelectedGroupId","assigningGroup","setAssigningGroup","removingGroupId","setRemovingGroupId","loadRole","roleData","rolesData","adminApi","err","useEffect","handleSaveInfo","updateData","loadTranslations","data","startEditTranslation","trans","cancelEditTranslation","handleSaveTranslation","languageCode","handleDeleteTranslation","availableLanguages","lang","openAddUser","handleAssignUser","handleRemoveUser","userId","openAddGroup","groupsApi","handleAssignGroup","handleRemoveGroup","groupId","tabs","Settings","Users","UsersRound","Languages","Breadcrumb","ArrowLeft","Lock","AlertTriangle","CheckCircle","tab","cat","group","Link","Search","g","rg","n","u","ru","Fragment","langInfo","l","isEditing","Edit2"],"mappings":"kVAkBMA,GAAgD,CACpD,IAAKC,EAAAA,IAACC,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,EACjC,KAAMD,EAAAA,IAACE,EAAAA,IAAA,CAAI,UAAU,SAAA,CAAU,EAC/B,OAAQF,EAAAA,IAACG,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EAClC,OAAQH,EAAAA,IAACI,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EAClC,OAAQJ,EAAAA,IAACK,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,EACpC,OAAQL,EAAAA,IAACM,EAAAA,SAAA,CAAS,UAAU,SAAA,CAAU,EACtC,QAASN,EAAAA,IAACO,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,CACrC,EAEMC,GAAwC,CAC5C,IAAK,gFACL,KAAM,0EACN,OAAQ,mFACR,OAAQ,mFACR,OAAQ,6EACR,OAAQ,gFACR,QAAS,kFACX,EAGA,SAASC,GACPC,EACAC,EACAC,EACA,CACA,OAAOF,EACJ,OAAOG,GAAOF,IAAsB,OAASE,EAAI,cAAgBF,CAAiB,EAClF,IAAIE,IAAQ,CACX,GAAGA,EACH,QAASA,EAAI,QAAQ,OAAOC,GAAKF,IAAiB,OAASE,EAAE,OAAO,cAAgBF,CAAY,CAAA,EAChG,EACD,UAAcC,EAAI,QAAQ,OAAS,CAAC,CACzC,CAGA,SAASE,GACPL,EACAM,EACAC,EACA,CACA,OAAOP,EAAQ,IAAIG,IAAQ,CACzB,GAAGA,EACH,QAASA,EAAI,QAAQ,OAAOC,GAAK,CAC/B,KAAM,CAAE,OAAAI,CAAA,EAAWD,EAAgBH,CAAC,EACpC,OAAOE,EAAc,IAAIE,CAAM,CACjC,CAAC,CAAA,EACD,EAAE,UAAcL,EAAI,QAAQ,OAAS,CAAC,CAC1C,CAYA,SAASM,GAAoB,CAC3B,QAAAC,EACA,UAAAC,EACA,YAAAC,EACA,aAAAC,EACA,kBAAAC,EACA,kBAAAC,CACF,EAA6B,CAC3B,MAAMC,EAAeL,EAAU,OAAS,EAClCM,EAAqBH,EAAkB,IAAIJ,EAAQ,EAAE,EAE3D,OACEQ,OAACC,EAAM,SAAN,CAEE,SAAA,CAAAJ,EAAkBL,EAASE,EAAcC,EAAe,EAAG,UAAWG,EAAcC,CAAkB,EAGtGD,GAAgB,CAACC,GAAsBN,EAAU,IAAI,CAACS,EAAUC,IAC/DN,EAAkBK,EAAUR,EAAcC,EAAeQ,EAAgB,EAAG,WAAY,GAAO,EAAK,CAAA,CACtG,CAAA,EAPmBX,EAAQ,EAQ7B,CAEJ,CAEO,SAASY,GAAqB,CAAE,OAAAC,GAAmD,CACxF,KAAM,CAAE,EAAAC,CAAA,EAAMC,GAAAA,eAAe,OAAO,EAC9B,CAAE,KAAAC,CAAA,EAASC,UAAA,EAEX,CAAE,cAAAC,EAAe,UAAAC,CAAA,EAAcC,sBAAA,EAC/B,CAACC,EAAkBC,CAAmB,EAAIC,EAAAA,SAAsB,IAAI,GAAK,EACzE,CAACnB,EAAmBoB,CAAoB,EAAID,EAAAA,SAAsB,IAAI,GAAK,EAC3E,CAAC3B,EAAe6B,EAAgB,EAAIF,EAAAA,SAAgC,IAAI,GAAK,EAC7E,CAACG,GAAaC,CAAc,EAAIJ,EAAAA,SAAwB,IAAI,EAG5D,CAAChC,EAAmBqC,CAAoB,EAAIL,EAAAA,SAAiB,KAAK,EAClE,CAAC/B,EAAcqC,CAAe,EAAIN,EAAAA,SAAiB,KAAK,EAGxDO,GAAqBC,EAAAA,QAAQ,IAC5Bf,EACEgB,EAAAA,cAAchB,EAAK,WAAW,EADnB,GAEjB,CAACA,CAAI,CAAC,EAEH,CACJ,QAAAiB,GACA,MAAAC,GACA,MAAAC,EACA,kBAAAC,EACA,WAAAC,EACA,OAAAC,EACA,YAAAC,EACA,UAAAC,EACA,iBAAAC,EACA,YAAAC,EACA,aAAAC,EACA,yBAAAC,CAAA,EACEC,EAAAA,oBAAoB,CAAE,mBAAAf,GAAoB,EAGxCgB,EAAOf,EAAAA,QAAQ,IACZI,EAAM,KAAKY,GAAKA,EAAE,KAAOlC,CAAM,EACrC,CAACsB,EAAOtB,CAAM,CAAC,EAGZmC,EAAiBjB,EAAAA,QAAQ,IACzB,GAACe,GACDA,EAAK,UAAY,CAAChB,IAErB,CAACgB,EAAMhB,EAAkB,CAAC,EAEvBmB,EAAsBnD,GAA6B,CACvD2B,GAAiByB,GAAQ,CACvB,MAAMC,EAAO,IAAI,IAAID,CAAI,EACzB,OAAIC,EAAK,IAAIrD,CAAM,EACjBqD,EAAK,OAAOrD,CAAM,EAElBqD,EAAK,IAAIrD,CAAM,EAEVqD,CACT,CAAC,CACH,EAEMC,EAAgBC,GAAqB,CACzC/B,EAAoB4B,GAAQ,CAC1B,MAAMC,EAAO,IAAI,IAAID,CAAI,EACzB,OAAIC,EAAK,IAAIE,CAAQ,EACnBF,EAAK,OAAOE,CAAQ,EAEpBF,EAAK,IAAIE,CAAQ,EAEZF,CACT,CAAC,CACH,EAEMG,GAAiBC,GAAsB,CAC3C/B,EAAqB0B,GAAQ,CAC3B,MAAMC,EAAO,IAAI,IAAID,CAAI,EACzB,OAAIC,EAAK,IAAII,CAAS,EACpBJ,EAAK,OAAOI,CAAS,EAErBJ,EAAK,IAAII,CAAS,EAEbJ,CACT,CAAC,CACH,EAGMK,EAAgBzB,EAAAA,QAAQ,IAAM,CAClC,MAAM0B,EAAiD,CAAA,EACjDC,EAA4D,CAAA,EAElE,OAAAtB,EAAkB,QAAQ1B,GAAY,CACpC,GAAIA,EAAS,QAAU,SAAU,CAC/B,MAAMiD,EAASjD,EAAS,iBACnB+C,EAAa,QAAUG,EAAE,MAAQD,CAAM,GAC1CF,EAAa,KAAK,CAChB,IAAK/C,EAAS,iBACd,MAAOA,EAAS,gBAAA,CACjB,EAGHgD,EAAQ,KAAK,CACX,IAAKhD,EAAS,iBACd,OAAQA,EAAS,YACjB,MAAOA,EAAS,WAAA,CACjB,CACH,CACF,CAAC,EAEM,CACL,aAAc+C,EAAa,KAAK,CAACG,EAAGC,IAAMD,EAAE,MAAM,cAAcC,EAAE,KAAK,CAAC,EACxE,QAASH,EAAQ,KAAK,CAACE,EAAGC,IAAMD,EAAE,MAAM,cAAcC,EAAE,KAAK,CAAC,CAAA,CAElE,EAAG,CAACzB,CAAiB,CAAC,EAGhB0B,GAAyBC,cAAaC,GAAyB,CAC/D,CAAClB,GAAQ,CAACE,GACdP,EAAiBK,EAAK,GAAIkB,CAAY,CACxC,EAAG,CAAClB,EAAME,EAAgBP,CAAgB,CAAC,EAGrCwB,EAAwBF,cAAaC,GAAkC,CAC3E,GAAI,CAAClB,EAAM,MAAO,GAClB,MAAMoB,EAAOtB,EAAyBE,EAAK,GAAIkB,CAAY,EAC3D,OAAOE,EAAK,UAAYA,EAAK,WAC/B,EAAG,CAACpB,EAAMF,CAAwB,CAAC,EAG7B/C,GAAkBkE,cAAaI,GAC5BC,GAAAA,kCACLD,EAAmB,OACnBA,EAAmB,SACnBF,CAAA,EAED,CAACA,CAAqB,CAAC,EAGpBI,GAAoBN,cAAarD,GAC9B4D,GAAAA,0BAA0B5D,EAAUuD,CAAqB,EAC/D,CAACA,CAAqB,CAAC,EAGpBM,EAAwBR,cAAarD,GACpCoC,EAEEpC,EAAS,YACb,OAAO8D,GAAK,CACX,MAAMN,EAAOtB,EAAyBE,EAAK,GAAI0B,EAAE,EAAE,EACnD,OAAON,EAAK,UAAYA,EAAK,WAC/B,CAAC,EACA,IAAIM,GAAKA,EAAE,MAAM,EAPF,CAAA,EAQjB,CAAC1B,EAAMF,CAAwB,CAAC,EAG7B6B,GAA+BV,cAAazE,GACzCD,GAAmCC,EAASC,EAAmBC,CAAY,EACjF,CAACD,EAAmBC,CAAY,CAAC,EAE9BkF,EAAoBX,cAAazE,GACjCM,EAAc,OAAS,EAAUN,EAC9BK,GAAwBL,EAASM,EAAeC,EAAe,EACrE,CAACD,EAAeC,EAAe,CAAC,EAE7B8E,EAAmB5C,EAAAA,QAAQ,IAAM,CACrC,IAAIzC,EAAUsF,GAAAA,+BAA+BxC,CAAiB,EAC9D,OAAA9C,EAAUmF,GAA6BnF,CAAO,EAC9CA,EAAUoF,EAAkBpF,CAAO,EAC5BA,CACT,EAAG,CAAC8C,EAAmBqC,GAA8BC,CAAiB,CAAC,EAGjEG,GAAmB9C,EAAAA,QAAQ,IACxB4C,EAAiB,OAAO,CAACG,EAAKrF,IACnCqF,EAAMrF,EAAI,QAAQ,OAAQ,CAAC,EAC5B,CAACkF,CAAgB,CAAC,EAEfI,GAAuBhB,EAAAA,YAAY,CAACiB,EAAoBC,IAA6C,CACrGA,IAAU,SACZ7B,EAAa4B,CAAU,EACdC,IAAU,WACnB3B,GAAc0B,CAAU,CAE5B,EAAG,CAAC5B,EAAcE,EAAa,CAAC,EAE1B4B,GAAmBF,GAAuB,CAE5CrD,EADED,KAAgBsD,EACH,KAEAA,CAFI,CAIvB,EAEA,GAAI/C,GACF,aACG,MAAA,CAAI,UAAU,yCACb,SAAAzB,EAAAA,KAAC,MAAA,CAAI,UAAU,cACb,SAAA,CAAA5B,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,kEAAA,CAAmE,QACrF,IAAA,CAAE,UAAU,+BAAgC,SAAArE,EAAE,yBAAyB,CAAA,CAAE,CAAA,CAAA,CAC5E,CAAA,CACF,EAIJ,GAAIoB,GACF,aACG,MAAA,CAAI,UAAU,4FACb,SAAA1B,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAACwG,EAAAA,YAAA,CAAY,UAAU,kCAAA,CAAmC,EAC1DxG,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA4B,SAAAsD,EAAA,CAAM,CAAA,CAAA,CACjD,CAAA,CACF,EAIJ,GAAI,CAACY,EACH,aACG,MAAA,CAAI,UAAU,iDACZ,SAAAhC,EAAE,qBAAqB,EAC1B,EAIJ,MAAMuE,GAAuBJ,GACvBA,IAAU,WAAmBrG,EAAAA,IAAC0G,EAAAA,SAAA,CAAS,UAAU,uCAAuC,EACxFL,IAAU,UAAkBrG,EAAAA,IAAC2G,EAAAA,SAAA,CAAS,UAAU,uCAAuC,EACpF3G,EAAAA,IAAC4G,EAAAA,IAAA,CAAI,UAAU,0CAAA,CAA2C,EAG7DC,GAA6BR,GAC7BA,IAAU,WAAmB,kCAC7BA,IAAU,UAAkB,+BACzB,yCAGHS,EAAuBT,GACvBA,IAAU,WAAmB,QAC7BA,IAAU,UAAkB,QACzB,QAGHU,GAAqB,CAACC,EAAsBZ,EAAoBC,EAA0CY,IACzGD,EAEHhH,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMmG,GAAqBC,EAAYC,CAAK,EACrD,UAAU,2CAET,SAAAY,QACEC,EAAAA,aAAA,CAAa,UAAU,mCAAmC,EAE3DlH,EAAAA,IAACmH,EAAAA,YAAA,CAAY,UAAU,kCAAA,CAAmC,CAAA,CAAA,EATvC,KAerBC,GAA0BC,GAC1BA,EAAmB,SAAW,QAE7B,OAAA,CAAK,UAAU,0CACb,SAAAnF,EAAE,2BAA2B,EAChC,EAGGmF,EAAmB,IAAKC,GAAW,CACxC,MAAMC,EAAc/G,GAAc8G,CAAM,GAAK,qFACvCE,EAAOzH,GAAauH,CAAM,GAAKtH,EAAAA,IAACE,MAAA,CAAI,UAAU,UAAU,EAC9D,OACE0B,EAAAA,KAAC,MAAA,CAEC,UAAW,yGAAyG2F,CAAW,GAC/H,MAAOrF,EAAE,uBAAuBoF,IAAW,IAAM,MAAQA,CAAM,cAAc,EAE5E,SAAA,CAAAE,EACDxH,EAAAA,IAAC,OAAA,CAAK,UAAU,aACb,SAAAkC,EAAE,uBAAuBoF,IAAW,IAAM,MAAQA,CAAM,QAAQ,CAAA,CACnE,CAAA,CAAA,EAPKA,CAAA,CAUX,CAAC,EAGG7F,GAAoB,CACxBK,EACA2F,EACApB,EACAW,EAAuB,GACvBC,EAAuB,KACpB,CACH,KAAM,CAAE,OAAA/F,EAAQ,aAAAwG,GAAiBjC,GAAkB3D,CAAQ,EACrD6F,EAAgB7E,KAAgBhB,EAAS,GACzC8F,EAAYC,EAAAA,UAAA,EACZC,EAASC,GAAAA,4BAA4B7G,CAAM,EAC3CmG,GAAqB1B,EAAsB7D,CAAQ,EACnDkG,EAAclB,EAAoBT,CAAK,EACvC4B,EAAaR,EAAW,IAAM,EAAI,aAAe,cAEvD,OACE7F,EAAAA,KAAC,KAAA,CAEC,UAAW,8BAA8BqG,CAAU,GAEnD,SAAA,CAAAjI,EAAAA,IAAC,KAAA,CACC,UAAW,sBAAsBiI,CAAU,cAAcD,CAAW,GACpE,MAAO,CAAE,MAAO,QAAS,SAAU,QAAS,SAAU,OAAA,EAEtD,SAAApG,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACZ,SAAA,CAAAmF,GAAmBC,EAAalF,EAAS,GAAIuE,EAAOY,CAAW,EAC/DR,GAAoBJ,CAAK,EAC1BrG,EAAAA,IAAC,QAAK,UAAW,WAAW6G,GAA0BR,CAAK,CAAC,GACzD,SAAAvE,EAAS,WAAA,CACZ,EACAF,EAAAA,KAAC,OAAA,CAAK,UAAU,mCAAmC,SAAA,CAAA,IAC/CE,EAAS,YAAY,OAAO,GAAA,CAAA,CAChC,CAAA,CAAA,CACF,CAAA,CAAA,EAGFF,EAAAA,KAAC,KAAA,CACC,UAAW,kCAAkCkG,CAAM,GACnD,MAAO,CAAE,MAAO,OAAQ,SAAU,OAAQ,SAAU,MAAA,EAEpD,SAAA,CAAA9H,EAAAA,IAAC,SAAA,CACC,IAAK4H,EACL,KAAK,SACL,QAAS,IAAMxD,GAAkBkC,GAAgBxE,EAAS,EAAE,EAC5D,SAAU,CAACsC,EACX,UAAW,yFACRA,EAEG,mBADA,+BAEN,IACEuD,EAAgB,wCAA0C,EAC5D,GACA,MACGvD,EAEG,GAAGF,EAAK,IAAI,MAAMpC,EAAS,WAAW,KAAK4F,CAAY,IAAI5F,EAAS,YAAY,MAAM,GADtF,GAAGoC,EAAK,IAAI,MAAMhC,EAAE,gCAAgC,CAAC,GAI3D,SAAAlC,EAAAA,IAACkI,GAAAA,0BAAA,CACC,OAAAhH,EACA,aAAAwG,EACA,WAAY5F,EAAS,YAAY,MAAA,CAAA,CACnC,CAAA,EAED6F,GAAiBvD,GAChBpE,EAAAA,IAACmI,GAAAA,kBAAA,CACC,KAAK,WACL,KAAAjE,EACA,SAAApC,EACA,mBAAoBoD,GACpB,QAAS,IAAMnC,EAAe,IAAI,EAClC,yBAA0B,CAACqF,GAAGC,KAAWrE,EAAyBE,EAAK,GAAImE,EAAM,CAAA,CAAA,CACnF,CAAA,CAAA,EAIJrI,EAAAA,IAAC,KAAA,CAAG,UAAU,YACZ,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,yBACZ,SAAAoH,GAAuBC,EAAkB,CAAA,CAC5C,CAAA,CACF,CAAA,CAAA,EA/DKvF,EAAS,EAAA,CAkEpB,EAEA,OACEF,EAAAA,KAAC,MAAA,CAAI,UAAU,YAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,eACZ,SAAA,CAAA+B,SACE,MAAA,CAAI,UAAU,kIACb,SAAA/B,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAACsI,EAAAA,MAAA,CAAM,UAAU,oCAAA,CAAqC,QACrD,IAAA,CAAE,UAAU,iDACV,SAAApG,EAAE,2BAA4B,0BAA0B,CAAA,CAC3D,CAAA,CAAA,CACF,CAAA,CACF,EAED,CAACyB,GAAeD,GACf1D,EAAAA,IAAC,MAAA,CAAI,UAAU,4HACb,SAAA4B,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,8CAAA,CAA+C,QACjE,IAAA,CAAE,UAAU,8CACV,SAAArE,EAAE,gBAAiB,wBAAwB,CAAA,CAC9C,CAAA,CAAA,CACF,CAAA,CACF,EAED,CAACyB,GAAe,CAACD,GAAUD,GAC1B7B,EAAAA,KAAC,MAAA,CAAI,UAAU,kIACb,SAAA,CAAA5B,MAAC,KAAE,UAAU,qCACV,SAAAkC,EAAE,6BAA8B,0BAA0B,EAC7D,EACAN,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CACC,QAASmC,EACT,SAAUL,EACV,UAAU,+NAEV,SAAA,CAAA1D,EAAAA,IAACuI,EAAAA,EAAA,CAAE,UAAU,SAAA,CAAU,EACtBrG,EAAE,eAAe,CAAA,CAAA,CAAA,EAEpBN,EAAAA,KAAC,SAAA,CACC,QAASkC,EACT,SAAUJ,EACV,UAAU,qLAET,SAAA,CAAAA,EAAS1D,EAAAA,IAACuG,WAAQ,UAAU,sBAAA,CAAuB,EAAKvG,EAAAA,IAACwI,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EAClFtG,EAAE,aAAa,CAAA,CAAA,CAAA,CAClB,CAAA,CACF,CAAA,EACF,EAED,CAACyB,GAAe,CAACD,GAAU,CAACD,GAC3BzD,EAAAA,IAAC,MAAA,CAAI,UAAU,UAAA,CAAW,CAAA,EAE9B,EAGC4D,SACE,MAAA,CAAI,UAAU,4FACb,SAAAhC,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAACwG,EAAAA,YAAA,CAAY,UAAU,kCAAA,CAAmC,EAC1DxG,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAoC,SAAA4D,CAAA,CAAU,CAAA,CAAA,CAC7D,CAAA,CACF,EAKFhC,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAA,EAAAA,KAAC,QAAA,CAAM,UAAU,uCACd,SAAA,CAAAM,EAAE,qCAAqC,EAAE,GAAA,EAC5C,EACAN,EAAAA,KAAC,SAAA,CACC,MAAOjB,EACP,SAAW8H,GAAM,CACfzF,EAAqByF,EAAE,OAAO,KAAK,EACnCxF,EAAgB,KAAK,CACvB,EACA,UAAU,iNAEV,SAAA,CAAAjD,MAAC,SAAA,CAAO,MAAM,MAAO,SAAAkC,EAAE,yCAAyC,EAAE,EACjE0C,EAAc,aACZ,IAAI/D,GACHb,EAAAA,IAAC,SAAA,CAAqB,MAAOa,EAAI,IAAM,SAAAA,EAAI,KAAA,EAA9BA,EAAI,GAAgC,CAClD,CAAA,CAAA,CAAA,CACL,EACF,EAEAe,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAA,EAAAA,KAAC,QAAA,CAAM,UAAU,uCACd,SAAA,CAAAM,EAAE,gCAAgC,EAAE,GAAA,EACvC,EACAN,EAAAA,KAAC,SAAA,CACC,MAAOhB,EACP,SAAW6H,GAAMxF,EAAgBwF,EAAE,OAAO,KAAK,EAC/C,UAAU,iNAEV,SAAA,CAAAzI,MAAC,SAAA,CAAO,MAAM,MAAO,SAAAkC,EAAE,oCAAoC,EAAE,EAC5D0C,EAAc,QACZ,OAAO8D,GACL/H,IAAsB,OAAS+H,EAAI,MAAQ/H,CAAA,EAE7C,IAAI+H,GACH1I,EAAAA,IAAC,SAAA,CAAwC,MAAO0I,EAAI,OAAS,SAAAA,EAAI,KAAA,EAApD,GAAGA,EAAI,GAAG,IAAIA,EAAI,MAAM,EAAkC,CACxE,CAAA,CAAA,CAAA,CACL,CAAA,CACF,CAAA,EACF,EAGA9G,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,OAAA,CAAK,UAAU,mDACb,SAAA,CAAAM,EAAE,gCAAgC,EAAE,GAAA,EACvC,EACAN,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMyC,EAAmB,KAAK,EACvC,UAAW,8FACTrD,EAAc,IAAI,KAAK,EACnB,mFACA,wHACN,GAEA,SAAA,CAAAhB,EAAAA,IAACsI,EAAAA,MAAA,CAAM,UAAW,eAAetH,EAAc,IAAI,KAAK,EAAI,GAAK,2BAA2B,EAAA,CAAI,EAC/FkB,EAAE,sBAAsB,CAAA,CAAA,CAAA,EAE3BN,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMyC,EAAmB,MAAM,EACxC,UAAW,8FACTrD,EAAc,IAAI,MAAM,EACpB,mFACA,wHACN,GAEA,SAAA,CAAAhB,EAAAA,IAAC2I,EAAAA,KAAA,CAAK,UAAW,eAAe3H,EAAc,IAAI,MAAM,EAAI,GAAK,2BAA2B,EAAA,CAAI,EAC/FkB,EAAE,qBAAqB,CAAA,CAAA,CAAA,EAE1BN,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMyC,EAAmB,WAAW,EAC7C,UAAW,8FACTrD,EAAc,IAAI,WAAW,EACzB,0EACA,qHACN,GAEA,SAAA,CAAAhB,EAAAA,IAACE,EAAAA,IAAA,CAAI,UAAW,eAAec,EAAc,IAAI,WAAW,EAAI,GAAK,wBAAwB,EAAA,CAAI,EAChGkB,EAAE,sBAAsB,CAAA,CAAA,CAAA,EAE3BN,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMyC,EAAmB,MAAM,EACxC,UAAW,8FACTrD,EAAc,IAAI,MAAM,EACpB,6EACA,sHACN,GAEA,SAAA,CAAAhB,EAAAA,IAAC4I,EAAAA,IAAA,CAAI,UAAW,eAAe5H,EAAc,IAAI,MAAM,EAAI,GAAK,0BAA0B,EAAA,CAAI,EAC7FkB,EAAE,kBAAkB,CAAA,CAAA,CAAA,CACvB,EACF,EACClB,EAAc,KAAO,GACpBhB,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM6C,GAAiB,IAAI,GAAK,EACzC,UAAU,wFAET,WAAE,0BAA0B,CAAA,CAAA,CAC/B,EAEJ,QAGC,MAAA,CAAI,UAAU,0BACb,SAAAjB,EAAAA,KAAC,OAAA,CAAK,UAAU,sGACb,SAAA,CAAAqE,GAAiB,IAAE/D,EAAE,qBAAqB,CAAA,CAAA,CAC7C,CAAA,CACF,EAGAlC,EAAAA,IAAC,MAAA,CAAI,UAAU,qCACb,SAAA4B,EAAAA,KAAC,QAAA,CAAM,UAAU,kBAAkB,MAAO,CAAE,MAAO,MAAA,EACjD,SAAA,CAAA5B,MAAC,QAAA,CAAM,UAAU,yDACf,SAAA4B,EAAAA,KAAC,KAAA,CACC,SAAA,CAAA5B,EAAAA,IAAC,KAAA,CACC,MAAM,MACN,UAAU,0HACV,MAAO,CAAE,MAAO,QAAS,SAAU,QAAS,SAAU,QAAS,OAAQ,OAAQ,cAAe,QAAA,EAE7F,WAAE,sBAAsB,CAAA,CAAA,EAE3BA,EAAAA,IAAC,KAAA,CACC,MAAM,MACN,UAAU,6FACV,MAAO,CAAE,MAAO,OAAQ,SAAU,OAAQ,SAAU,OAAQ,OAAQ,OAAQ,cAAe,QAAA,EAE1F,WAAE,wBAAwB,CAAA,CAAA,EAE7BA,EAAAA,IAAC,KAAA,CACC,MAAM,MACN,UAAU,2FACV,MAAO,CAAE,OAAQ,OAAQ,cAAe,QAAA,EAEvC,WAAE,yBAAyB,CAAA,CAAA,CAC9B,CAAA,CACF,CAAA,CACF,QACC,QAAA,CAAM,UAAU,6CACd,SAAA+F,EAAiB,IAAK8C,GAAa,CAClC,MAAM9D,EAAS8D,EAAS,YAClBC,EAAiBxG,EAAc,IAAIyC,CAAM,EAE/C,OACEnD,OAACC,EAAM,SAAN,CAEC,SAAA,CAAAD,EAAAA,KAAC,KAAA,CAAG,UAAU,0BACZ,SAAA,CAAA5B,EAAAA,IAAC,KAAA,CACC,UAAU,uDACV,MAAO,CAAE,MAAO,QAAS,SAAU,QAAS,SAAU,OAAA,EAEtD,SAAA4B,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMW,EAAUwC,CAAM,EAC/B,UAAU,4DAET,SAAA,CAAA+D,EACC9I,EAAAA,IAACkH,gBAAa,UAAU,sCAAA,CAAuC,EAE/DlH,EAAAA,IAACmH,EAAAA,YAAA,CAAY,UAAU,sCAAA,CAAuC,EAEhEnH,EAAAA,IAAC+I,EAAAA,WAAA,CAAW,UAAU,sCAAA,CAAuC,EAC7D/I,EAAAA,IAAC,OAAA,CAAK,UAAU,mDACb,WAAS,YACZ,EACA4B,EAAAA,KAAC,OAAA,CAAK,UAAU,2CACb,SAAA,CAAAiH,EAAS,QAAQ,OAAO,UAAQA,EAAS,QAAQ,OAAS,EAAI,IAAM,EAAA,CAAA,CACvE,CAAA,CAAA,CAAA,CACF,CAAA,EAEF7I,EAAAA,IAAC,KAAA,CAAG,UAAU,WAAA,CAAY,EAC1BA,EAAAA,IAAC,KAAA,CAAG,UAAU,WAAA,CAAY,CAAA,EAC5B,EAGC,CAAC8I,GAAkBD,EAAS,QAAQ,IAAI,CAACtD,EAAoBjE,IAAgB,CAC5E,KAAM,CAAE,OAAA0H,EAAQ,SAAAC,CAAA,EAAa1D,EACvB2D,EAAcD,EAAS,OAAS,EAChCE,EAAoB1G,EAAiB,IAAIuG,EAAO,EAAE,EAExD,OACEpH,OAACC,EAAM,SAAN,CAEE,SAAA,CAAAJ,GAAkBuH,EAAQ1H,EAAa,SAAU4H,EAAaC,CAAiB,EAG/ED,GAAe,CAACC,GAAqBF,EAAS,IAAI,CAACG,EAAsB7H,KAAiB,CACzF,KAAM,CAAE,QAAAH,EAAS,UAAAC,CAAA,EAAc+H,EAE/B,OACEpJ,EAAAA,IAACmB,GAAA,CAEC,QAAAC,EACA,UAAAC,EACA,YAAAC,EACA,aAAAC,GACA,kBAAAC,EACA,kBAAAC,EAAA,EANKL,EAAQ,EAAA,CASnB,CAAC,CAAA,CAAA,EAnBkB4H,EAAO,EAoB5B,CAEJ,CAAC,CAAA,CAAA,EA1DkBjE,CA2DrB,CAEJ,CAAC,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CACF,EAECkB,KAAqB,GACpBjG,EAAAA,IAAC,MAAA,CAAI,UAAU,iDACZ,SAAAkC,EAAE,yBAAyB,CAAA,CAC9B,CAAA,EAEJ,CAEJ,CCxsBA,MAAMmH,GAAsB,CAC1B,CAAE,KAAM,KAAM,MAAO,UAAA,EACrB,CAAE,KAAM,KAAM,MAAO,SAAA,EACrB,CAAE,KAAM,KAAM,MAAO,UAAA,EACrB,CAAE,KAAM,KAAM,MAAO,SAAA,CACvB,EAEO,SAASC,IAA+B,CAC7C,KAAM,CAAE,EAAApH,CAAA,EAAMC,GAAAA,eAAe,OAAO,EAC9B,CAAE,GAAIF,CAAA,EAAWsH,aAAA,EACjBC,EAAWC,GAAAA,YAAA,EAEX,CAACvF,EAAMwF,CAAO,EAAI/G,EAAAA,SAA+B,IAAI,EACrD,CAACU,EAASsG,CAAU,EAAIhH,EAAAA,SAAS,EAAI,EACrC,CAACe,EAAQkG,CAAS,EAAIjH,EAAAA,SAAS,EAAK,EACpC,CAACkH,EAAWC,EAAY,EAAInH,EAAAA,SAAgB,MAAM,EAClD,CAACW,GAAOyG,CAAQ,EAAIpH,EAAAA,SAAwB,IAAI,EAChD,CAACqH,EAASC,CAAU,EAAItH,EAAAA,SAAwB,IAAI,EAEpD,CAACuH,EAAUC,CAAW,EAAIxH,WAAS,CACvC,KAAM,GACN,UAAW,GACX,SAAU,SACV,YAAa,GACb,aAAc,IAAA,CACf,EACK,CAACyH,GAAgBC,EAAiB,EAAI1H,EAAAA,SAAwB,CAAA,CAAE,EAEhE2H,GAAkC,CAAC,SAAU,QAAS,UAAW,cAAe,SAAU,QAAQ,EAGlG,CAACC,EAAcC,CAAe,EAAI7H,EAAAA,SAA+B,CAAA,CAAE,EACnE,CAAC8H,EAAqBC,CAAsB,EAAI/H,EAAAA,SAAS,EAAK,EAC9D,CAACgI,EAAoBC,CAAqB,EAAIjI,EAAAA,SAAwB,IAAI,EAC1E,CAACkI,EAAiBC,CAAkB,EAAInI,WAAuC,CACnF,KAAM,GACN,UAAW,GACX,YAAa,EAAA,CACd,EACK,CAACoI,EAAmBC,CAAoB,EAAIrI,EAAAA,SAAS,EAAK,EAC1D,CAACsI,EAAoBC,CAAqB,EAAIvI,EAAAA,SAAS,EAAK,EAC5D,CAACwI,EAAoBC,CAAqB,EAAIzI,EAAAA,SAAS,EAAE,EAGzD,CAAC0I,GAAYC,CAAa,EAAI3I,EAAAA,SAAS,EAAK,EAC5C,CAAC4I,GAAgBC,CAAiB,EAAI7I,EAAAA,SAAwB,CAAA,CAAE,EAChE,CAAC8I,GAAcC,EAAe,EAAI/I,EAAAA,SAAS,EAAK,EAChD,CAACgJ,EAAgBC,EAAiB,EAAIjJ,EAAAA,SAAS,EAAE,EACjD,CAACkJ,EAAgBC,CAAiB,EAAInJ,EAAAA,SAAwB,IAAI,EAClE,CAACoJ,GAAeC,EAAgB,EAAIrJ,EAAAA,SAAS,EAAK,EAClD,CAACsJ,GAAgBC,EAAiB,EAAIvJ,EAAAA,SAAwB,IAAI,EAGlE,CAACwJ,GAAaC,CAAc,EAAIzJ,EAAAA,SAAS,EAAK,EAC9C,CAAC0J,GAAiBC,EAAkB,EAAI3J,EAAAA,SAAyB,CAAA,CAAE,EACnE,CAAC4J,GAAeC,CAAgB,EAAI7J,EAAAA,SAAS,EAAK,EAClD,CAAC8J,EAAiBC,CAAkB,EAAI/J,EAAAA,SAAS,EAAE,EACnD,CAACgK,EAAiBC,CAAkB,EAAIjK,EAAAA,SAAwB,IAAI,EACpE,CAACkK,EAAgBC,CAAiB,EAAInK,EAAAA,SAAS,EAAK,EACpD,CAACoK,EAAiBC,CAAkB,EAAIrK,EAAAA,SAAwB,IAAI,EAEpEsK,EAAW9H,EAAAA,YAAY,SAAY,CACvC,GAAKlD,EACL,GAAI,CACF0H,EAAW,EAAI,EACf,KAAM,CAACuD,EAAUC,CAAS,EAAI,MAAM,QAAQ,IAAI,CAC9CC,WAAS,MAAM,QAAQnL,CAAM,EAC7BmL,EAAAA,SAAS,MAAM,OAAA,CAAO,CACvB,EACD1D,EAAQwD,CAAQ,EAEhB7C,GAAkB8C,EAAU,OAAOhJ,IAAKA,GAAE,KAAOlC,CAAM,CAAC,EACxDkI,EAAY,CACV,KAAM+C,EAAS,KACf,UAAWA,EAAS,UACpB,SAAUA,EAAS,SACnB,YAAaA,EAAS,aAAe,GACrC,aAAcA,EAAS,YAAA,CACxB,CACH,OAASG,EAAK,CACZ,QAAQ,MAAM,uBAAwBA,CAAG,EACzCtD,EAAS7H,EAAE,8BAA8B,CAAC,CAC5C,QAAA,CACEyH,EAAW,EAAK,CAClB,CACF,EAAG,CAAC1H,EAAQC,CAAC,CAAC,EAEdoL,EAAAA,UAAU,IAAM,CACdL,EAAA,CACF,EAAG,CAACA,CAAQ,CAAC,EAEb,MAAMM,GAAiB,MAAO9E,GAAuB,CAEnD,GADAA,EAAE,eAAA,EACE,GAACxG,GAAU,CAACiC,GAEhB,CAAA0F,EAAU,EAAI,EACdG,EAAS,IAAI,EACbE,EAAW,IAAI,EAEf,GAAI,CACF,MAAMuD,EAAgC,CACpC,KAAMtD,EAAS,KACf,UAAWA,EAAS,UACpB,SAAUA,EAAS,SACnB,YAAaA,EAAS,aAAe,OACrC,aAAcA,EAAS,cAAgB,MAAA,EAEzC,MAAMkD,EAAAA,SAAS,MAAM,OAAOnL,EAAQuL,CAAU,EAC9CvD,EAAW/H,EAAE,0BAA0B,CAAC,EACxC+K,EAAA,CACF,OAASI,EAAc,CACrBtD,EAASsD,aAAe,MAAQA,EAAI,QAAUnL,EAAE,8BAA8B,CAAC,CACjF,QAAA,CACE0H,EAAU,EAAK,CACjB,EACF,EAGM6D,EAAmBtI,EAAAA,YAAY,SAAY,CAC/C,GAAKlD,EACL,CAAAyI,EAAuB,EAAI,EAC3B,GAAI,CACF,MAAMgD,EAAO,MAAMN,EAAAA,SAAS,MAAM,gBAAgBnL,CAAM,EACxDuI,EAAgBkD,CAAI,CACtB,OAASL,EAAK,CACZ,QAAQ,MAAM,+BAAgCA,CAAG,CACnD,QAAA,CACE3C,EAAuB,EAAK,CAC9B,EACF,EAAG,CAACzI,CAAM,CAAC,EAEXqL,EAAAA,UAAU,IAAM,CACVzD,IAAc,gBAAkBU,EAAa,SAAW,GAC1DkD,EAAA,CAEJ,EAAG,CAAC5D,EAAWU,EAAa,OAAQkD,CAAgB,CAAC,EAErD,MAAME,EAAwBC,GAA8B,CAC1DhD,EAAsBgD,EAAM,YAAY,EACxC9C,EAAmB,CACjB,KAAM8C,EAAM,KACZ,UAAWA,EAAM,UACjB,YAAaA,EAAM,aAAe,EAAA,CACnC,CACH,EAEMC,GAAwB,IAAM,CAClCjD,EAAsB,IAAI,EAC1BM,EAAsB,EAAK,EAC3BJ,EAAmB,CAAE,KAAM,GAAI,UAAW,GAAI,YAAa,GAAI,EAC/DM,EAAsB,EAAE,CAC1B,EAEM0C,GAAwB,MAAOC,GAAyB,CAC5D,GAAK9L,EACL,CAAA+I,EAAqB,EAAI,EACzBjB,EAAS,IAAI,EACb,GAAI,CACF,MAAMqD,EAAAA,SAAS,MAAM,kBAAkBnL,EAAQ8L,EAAclD,CAAe,EAC5EZ,EAAW/H,EAAE,+BAA+B,CAAC,EAC7C0I,EAAsB,IAAI,EAC1BM,EAAsB,EAAK,EAC3BE,EAAsB,EAAE,EACxBqC,EAAA,CACF,OAASJ,EAAK,CACZtD,EAASsD,aAAe,MAAQA,EAAI,QAAUnL,EAAE,8BAA8B,CAAC,CACjF,QAAA,CACE8I,EAAqB,EAAK,CAC5B,EACF,EAEMgD,GAA0B,MAAOD,GAAyB,CAC9D,GAAK9L,GACA,QAAQC,EAAE,uCAAuC,CAAC,EACvD,GAAI,CACF,MAAMkL,EAAAA,SAAS,MAAM,kBAAkBnL,EAAQ8L,CAAY,EAC3D9D,EAAW/H,EAAE,iCAAiC,CAAC,EAC/CuL,EAAA,CACF,OAASJ,EAAK,CACZtD,EAASsD,aAAe,MAAQA,EAAI,QAAUnL,EAAE,8BAA8B,CAAC,CACjF,CACF,EAEM+L,GAAqB5E,GAAoB,OAC7C6E,GAAQ,CAAC3D,EAAa,KAAKrI,GAAKA,EAAE,eAAiBgM,EAAK,IAAI,CAAA,EAIxDC,GAAc,SAAY,CAC9B7C,EAAc,EAAI,EAClBQ,EAAkB,IAAI,EACtBF,GAAkB,EAAE,EACpBF,GAAgB,EAAI,EACpB,GAAI,CACF,MAAMgC,EAAO,MAAMN,WAAS,MAAM,OAAO,CAAE,YAAa,GAAM,EAC9D5B,EAAkBkC,EAAK,KAAK,CAC9B,OAASL,EAAK,CACZ,QAAQ,MAAM,wBAAyBA,CAAG,CAC5C,QAAA,CACE3B,GAAgB,EAAK,CACvB,CACF,EAEM0C,GAAmB,SAAY,CACnC,GAAI,GAACnM,GAAU,CAAC4J,GAChB,CAAAG,GAAiB,EAAI,EACrB,GAAI,CACF,MAAMoB,EAAAA,SAAS,MAAM,WAAWnL,EAAQ4J,CAAc,EACtDP,EAAc,EAAK,EACnBQ,EAAkB,IAAI,EACtB7B,EAAW/H,EAAE,2BAA2B,CAAC,EACzC+K,EAAA,CACF,OAASI,EAAK,CACZtD,EAASsD,aAAe,MAAQA,EAAI,QAAUnL,EAAE,gCAAgC,CAAC,CACnF,QAAA,CACE8J,GAAiB,EAAK,CACxB,EACF,EAEMqC,GAAmB,MAAOC,GAAmB,CACjD,GAAKrM,GACA,QAAQC,EAAE,gCAAgC,CAAC,EAChD,CAAAgK,GAAkBoC,CAAM,EACxB,GAAI,CACF,MAAMlB,EAAAA,SAAS,MAAM,WAAWnL,EAAQqM,CAAM,EAC9CrE,EAAW/H,EAAE,0BAA0B,CAAC,EACxC+K,EAAA,CACF,OAASI,EAAK,CACZtD,EAASsD,aAAe,MAAQA,EAAI,QAAUnL,EAAE,gCAAgC,CAAC,CACnF,QAAA,CACEgK,GAAkB,IAAI,CACxB,EACF,EAGMqC,GAAe,SAAY,CAC/BnC,EAAe,EAAI,EACnBQ,EAAmB,IAAI,EACvBF,EAAmB,EAAE,EACrBF,EAAiB,EAAI,EACrB,GAAI,CACF,MAAMkB,EAAO,MAAMc,GAAAA,UAAU,OAAA,EAC7BlC,GAAmBoB,CAAI,CACzB,OAASL,EAAK,CACZ,QAAQ,MAAM,yBAA0BA,CAAG,CAC7C,QAAA,CACEb,EAAiB,EAAK,CACxB,CACF,EAEMiC,GAAoB,SAAY,CACpC,GAAI,GAACxM,GAAU,CAAC0K,GAChB,CAAAG,EAAkB,EAAI,EACtB,GAAI,CACF,MAAMM,EAAAA,SAAS,MAAM,YAAYnL,EAAQ0K,CAAe,EACxDP,EAAe,EAAK,EACpBQ,EAAmB,IAAI,EACvB3C,EAAW/H,EAAE,4BAA4B,CAAC,EAC1C+K,EAAA,CACF,OAASI,EAAK,CACZtD,EAASsD,aAAe,MAAQA,EAAI,QAAUnL,EAAE,gCAAgC,CAAC,CACnF,QAAA,CACE4K,EAAkB,EAAK,CACzB,EACF,EAEM4B,GAAoB,MAAOC,GAAoB,CACnD,GAAK1M,GACA,QAAQC,EAAE,iCAAiC,CAAC,EACjD,CAAA8K,EAAmB2B,CAAO,EAC1B,GAAI,CACF,MAAMvB,EAAAA,SAAS,MAAM,YAAYnL,EAAQ0M,CAAO,EAChD1E,EAAW/H,EAAE,2BAA2B,CAAC,EACzC+K,EAAA,CACF,OAASI,EAAK,CACZtD,EAASsD,aAAe,MAAQA,EAAI,QAAUnL,EAAE,gCAAgC,CAAC,CACnF,QAAA,CACE8K,EAAmB,IAAI,CACzB,EACF,EAEM4B,GAA8D,CAClE,CAAE,GAAI,OAAQ,MAAO1M,EAAE,sBAAsB,EAAG,KAAMlC,EAAAA,IAAC6O,EAAAA,SAAA,CAAS,UAAU,SAAA,CAAU,CAAA,EACpF,CAAE,GAAI,cAAe,MAAO3M,EAAE,6BAA6B,EAAG,KAAMlC,EAAAA,IAACC,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,CAAA,EAChG,CAAE,GAAI,QAAS,MAAOiC,EAAE,uBAAuB,EAAG,KAAMlC,EAAAA,IAAC8O,EAAAA,MAAA,CAAM,UAAU,SAAA,CAAU,CAAA,EACnF,CAAE,GAAI,SAAU,MAAO5M,EAAE,wBAAwB,EAAG,KAAMlC,EAAAA,IAAC+O,EAAAA,WAAA,CAAW,UAAU,SAAA,CAAU,CAAA,EAC1F,CAAE,GAAI,eAAgB,MAAO7M,EAAE,8BAA8B,EAAG,KAAMlC,EAAAA,IAACgP,EAAAA,UAAA,CAAU,UAAU,SAAA,CAAU,CAAA,CAAG,EAG1G,OAAI3L,EAEArD,MAAC,OAAI,UAAU,wCACb,eAACuG,EAAAA,QAAA,CAAQ,UAAU,sDAAsD,CAAA,CAC3E,EAICrC,EAeHtC,EAAAA,KAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAA5B,EAAAA,IAACiP,EAAAA,WAAA,CACC,MAAO,CACL,CAAE,MAAO/M,EAAE,cAAc,EAAG,KAAM,iBAAA,EAClC,CAAE,MAAOA,EAAE,cAAe,OAAO,EAAG,KAAM,mCAAA,EAC1C,CAAE,MAAOgC,GAAM,MAAQ,QAAA,CAAS,CAClC,CAAA,EAIFtC,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMwJ,EAAS,mCAAmC,EAC3D,UAAU,kFAEV,SAAAxJ,EAAAA,IAACkP,EAAAA,UAAA,CAAU,UAAU,sCAAA,CAAuC,CAAA,CAAA,EAE9DtN,EAAAA,KAAC,MAAA,CAAI,UAAU,SACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAAC,KAAA,CAAG,UAAU,2DAA4D,SAAAkE,EAAK,KAAK,EACnFA,EAAK,UACJtC,OAAC,OAAA,CAAK,UAAU,kKACd,SAAA,CAAA5B,EAAAA,IAACmP,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EACzBjN,EAAE,cAAc,CAAA,CAAA,CACnB,CAAA,EAEJ,EACCgC,EAAK,aACJlE,EAAAA,IAAC,KAAE,UAAU,yDAA0D,WAAK,WAAA,CAAY,CAAA,EAE5F,EACA4B,EAAAA,KAAC,MAAA,CAAI,UAAU,+DACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAAC8O,EAAAA,MAAA,CAAM,UAAU,SAAA,CAAU,SAC1B,OAAA,CAAM,SAAA,CAAA5K,EAAK,MAAM,OAAO,IAAEhC,EAAE,uBAAuB,CAAA,CAAA,CAAE,CAAA,EACxD,EACAN,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAAC+O,EAAAA,WAAA,CAAW,UAAU,SAAA,CAAU,SAC/B,OAAA,CAAM,SAAA,CAAA7K,EAAK,QAAQ,QAAU,EAAE,IAAEhC,EAAE,wBAAwB,CAAA,CAAA,CAAE,CAAA,EAChE,EACAN,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAACC,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,SAC3B,OAAA,CAAM,SAAA,CAAAiE,EAAK,YAAY,OAAO,IAAEhC,EAAE,mBAAmB,CAAA,CAAA,CAAE,CAAA,CAAA,CAC1D,CAAA,CAAA,CACF,CAAA,EACF,EAGCoB,IACC1B,EAAAA,KAAC,MAAA,CAAI,UAAU,6IACb,SAAA,CAAA5B,EAAAA,IAACoP,EAAAA,cAAA,CAAc,UAAU,uBAAA,CAAwB,EAChD9L,EAAA,EACH,EAED0G,GACCpI,EAAAA,KAAC,MAAA,CAAI,UAAU,mJACb,SAAA,CAAA5B,EAAAA,IAACqP,EAAAA,YAAA,CAAY,UAAU,uBAAA,CAAwB,EAC9CrF,CAAA,EACH,QAKD,MAAA,CAAI,UAAU,2GACZ,SAAA4E,GAAK,IAAIU,GACR1N,EAAAA,KAAC,SAAA,CAEC,QAAS,IAAMkI,GAAawF,EAAI,EAAE,EAClC,UAAW,kGACTzF,IAAcyF,EAAI,GACd,0CACA,yDACN,GAEC,SAAA,CAAAA,EAAI,KACLtP,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,WAAI,KAAA,CAAM,CAAA,CAAA,EATzCsP,EAAI,EAAA,CAWZ,EACH,EAGA1N,EAAAA,KAAC,MAAA,CAAI,UAAU,uGAEZ,SAAA,CAAAiI,IAAc,QACbjI,EAAAA,KAAC,OAAA,CAAK,SAAU2L,GAAgB,UAAU,sBAExC,SAAA,CAAA3L,OAAC,MAAA,CACC,SAAA,CAAA5B,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,oBAAoB,EACzB,EACAlC,EAAAA,IAAC,MAAA,CAAI,UAAU,qJACZ,WAAK,EAAA,CACR,CAAA,EACF,SAGC,MAAA,CACC,SAAA,CAAA4B,EAAAA,KAAC,QAAA,CAAM,UAAU,8DACd,SAAA,CAAAM,EAAE,iBAAiB,EAAE,IAAA,EACxB,EACAlC,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,SAAQ,GACR,MAAOkK,EAAS,KAChB,SAAUzB,GAAK0B,EAAY7F,IAAS,CAAE,GAAGA,EAAM,KAAMmE,EAAE,OAAO,KAAA,EAAQ,EACtE,UAAU,2MAAA,CAAA,CACZ,EACF,SAGC,MAAA,CACC,SAAA,CAAA7G,EAAAA,KAAC,QAAA,CAAM,UAAU,8DACd,SAAA,CAAAM,EAAE,2BAA2B,EAAE,IAAA,EAClC,EACAlC,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,SAAQ,GACR,MAAOkK,EAAS,UAChB,SAAUzB,GAAK0B,EAAY7F,IAAS,CAAE,GAAGA,EAAM,UAAWmE,EAAE,OAAO,KAAA,EAAQ,EAC3E,UAAU,2MAAA,CAAA,QAEX,IAAA,CAAE,UAAU,2CACV,SAAAvG,EAAE,+BAA+B,CAAA,CACpC,CAAA,EACF,SAGC,MAAA,CACC,SAAA,CAAAN,EAAAA,KAAC,QAAA,CAAM,UAAU,8DACd,SAAA,CAAAM,EAAE,0BAA0B,EAAE,IAAA,EACjC,EACAlC,EAAAA,IAAC,SAAA,CACC,MAAOkK,EAAS,SAChB,SAAUzB,GAAK0B,EAAY7F,IAAS,CAAE,GAAGA,EAAM,SAAUmE,EAAE,OAAO,KAAA,EAAwB,EAC1F,UAAU,4MAET,SAAA6B,GAAgB,IAAIiF,GACnBvP,MAAC,UAAiB,MAAOuP,EACtB,SAAArN,EAAE,yBAAyBqN,EAAI,YAAA,CAAa,EAAE,CAAA,EADpCA,CAEb,CACD,CAAA,CAAA,QAEF,IAAA,CAAE,UAAU,2CACV,SAAArN,EAAE,8BAA8B,CAAA,CACnC,CAAA,EACF,SAGC,MAAA,CACC,SAAA,CAAAlC,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,4BAA4B,EACjC,EACAN,EAAAA,KAAC,SAAA,CACC,MAAOsI,EAAS,cAAgB,GAChC,SAAUzB,GAAK0B,EAAY7F,IAAS,CAAE,GAAGA,EAAM,aAAcmE,EAAE,OAAO,OAAS,IAAA,EAAO,EACtF,UAAU,4MAEV,SAAA,CAAAzI,MAAC,SAAA,CAAO,MAAM,GAAI,SAAAkC,EAAE,0BAA0B,EAAE,EAC/CkI,GAAe,IAAI,UACjB,SAAA,CAAkB,MAAO,EAAE,GACzB,SAAA,CAAA,EAAE,KAAK,KAAGlI,EAAE,yBAAyB,EAAE,SAAS,YAAA,CAAa,EAAE,EAAE,GAAA,CAAA,EADvD,EAAE,EAEf,CACD,CAAA,CAAA,CAAA,QAEF,IAAA,CAAE,UAAU,2CACV,SAAAA,EAAE,gCAAgC,CAAA,CACrC,CAAA,EACF,SAGC,MAAA,CACC,SAAA,CAAAlC,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,wBAAwB,EAC7B,EACAlC,EAAAA,IAAC,WAAA,CACC,MAAOkK,EAAS,YAChB,SAAUzB,GAAK0B,EAAY7F,IAAS,CAAE,GAAGA,EAAM,YAAamE,EAAE,OAAO,KAAA,EAAQ,EAC7E,KAAM,EACN,UAAU,uNAAA,CAAA,CACZ,EACF,SAGC,MAAA,CACC,SAAA,CAAAzI,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,4BAA4B,EACjC,EACAlC,EAAAA,IAAC,OAAI,UAAU,0BACZ,WAAK,SACJ4B,EAAAA,KAAC,OAAA,CAAK,UAAU,sKACd,SAAA,CAAA5B,EAAAA,IAACmP,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EACzBjN,EAAE,8BAA8B,CAAA,CAAA,CACnC,QAEC,OAAA,CAAK,UAAU,mIACb,SAAAA,EAAE,8BAA8B,EACnC,CAAA,CAEJ,CAAA,EACF,EAGAN,EAAAA,KAAC,MAAA,CAAI,UAAU,mFACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAA5B,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,sBAAsB,EAC3B,EACAlC,EAAAA,IAAC,MAAA,CAAI,UAAU,qCACZ,SAAA,IAAI,KAAKkE,EAAK,SAAS,EAAE,eAAA,CAAe,CAC3C,CAAA,EACF,EACCA,EAAK,WACJtC,EAAAA,KAAC,MAAA,CACC,SAAA,CAAA5B,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,sBAAsB,EAC3B,EACAlC,EAAAA,IAAC,MAAA,CAAI,UAAU,qCACZ,SAAA,IAAI,KAAKkE,EAAK,SAAS,EAAE,eAAA,CAAe,CAC3C,CAAA,CAAA,CACF,CAAA,EAEJ,EAEAlE,EAAAA,IAAC,MAAA,CAAI,UAAU,wBACb,SAAA4B,EAAAA,KAAC,SAAA,CACC,KAAK,SACL,SAAU8B,EACV,UAAU,gMAET,SAAA,CAAAA,EAAS1D,EAAAA,IAACuG,WAAQ,UAAU,sBAAA,CAAuB,EAAKvG,EAAAA,IAACwI,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EAClFtG,EAAE,aAAa,CAAA,CAAA,CAAA,CAClB,CACF,CAAA,EACF,EAID2H,IAAc,eAAiB5H,GAC9BjC,EAAAA,IAACgC,IAAqB,OAAAC,EAAgB,EAIvC4H,IAAc,UACbjI,OAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,mDACX,SAAA,CAAAM,EAAE,yBAAyB,EAAE,KAAGgC,EAAK,QAAQ,QAAU,EAAE,GAAA,EAC5D,EACAtC,EAAAA,KAAC,SAAA,CACC,QAAS2M,GACT,UAAU,sLAEV,SAAA,CAAAvO,EAAAA,IAACG,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EACzB+B,EAAE,uBAAuB,CAAA,CAAA,CAAA,CAC5B,EACF,EAEE,CAACgC,EAAK,QAAUA,EAAK,OAAO,SAAW,EACvClE,EAAAA,IAAC,MAAA,CAAI,UAAU,iDACZ,WAAE,4BAA4B,CAAA,CACjC,EAEAA,EAAAA,IAAC,MAAA,CAAI,UAAU,aACZ,SAAAkE,EAAK,OAAO,IAAIsL,GACf5N,EAAAA,KAAC,MAAA,CAEC,UAAU,sHAEV,SAAA,CAAAA,EAAAA,KAAC6N,GAAAA,KAAA,CACC,GAAI,gCAAgCD,EAAM,EAAE,GAC5C,UAAU,6EAEV,SAAA,CAAAxP,EAAAA,IAAC,OAAI,UAAU,uFACb,eAAC+O,EAAAA,WAAA,CAAW,UAAU,yCAAyC,CAAA,CACjE,EACAnN,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAA5B,EAAAA,IAAC,MAAA,CAAI,UAAU,kDAAmD,SAAAwP,EAAM,KAAK,EAC7E5N,EAAAA,KAAC,MAAA,CAAI,UAAU,gDACZ,SAAA,CAAA4N,EAAM,aAAa,IAAEtN,EAAE,2BAA2B,EAClDsN,EAAM,aAAe,MAAMA,EAAM,WAAW,EAAA,CAAA,CAC/C,CAAA,CAAA,CACF,CAAA,CAAA,CAAA,EAEFxP,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM0O,GAAkBc,EAAM,EAAE,EACzC,SAAUzC,IAAoByC,EAAM,GACpC,UAAU,kKACV,MAAOtN,EAAE,0BAA0B,EAElC,SAAA6K,IAAoByC,EAAM,GACzBxP,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,sBAAA,CAAuB,EAE1CvG,EAAAA,IAACK,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,CAAA,CAAA,CAEhC,CAAA,EA7BKmP,EAAM,EAAA,CA+Bd,EACH,EAIDrD,UACE,MAAA,CAAI,UAAU,mFACb,SAAAvK,EAAAA,KAAC,MAAA,CAAI,UAAU,iJACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAA5B,MAAC,KAAA,CAAG,UAAU,+CACX,SAAAkC,EAAE,4BAA4B,EACjC,EACAlC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMoM,EAAe,EAAK,EACnC,UAAU,kFAEV,SAAApM,EAAAA,IAACuI,EAAAA,EAAA,CAAE,UAAU,qCAAA,CAAsC,CAAA,CAAA,CACrD,EACF,QAEC,MAAA,CAAI,UAAU,OACb,SAAA3G,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAA5B,EAAAA,IAAC0P,EAAAA,OAAA,CAAO,UAAU,8EAAA,CAA+E,EACjG1P,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAOyM,EACP,SAAWhE,GAAMiE,EAAmBjE,EAAE,OAAO,KAAK,EAClD,UAAU,kNACV,YAAavG,EAAE,qCAAqC,CAAA,CAAA,CACtD,CAAA,CACF,CAAA,CACF,EAECqK,GACCvM,EAAAA,IAAC,MAAA,CAAI,UAAU,wCACb,SAAAA,MAACuG,EAAAA,QAAA,CAAQ,UAAU,sDAAsD,EAC3E,EAEAvG,EAAAA,IAAC,MAAA,CAAI,UAAU,qCACZ,SAAAqM,GACE,OAAOsD,GACN,CAACzL,EAAK,QAAQ,KAAK0L,GAAMA,EAAG,KAAOD,EAAE,EAAE,IACtClD,IAAoB,IACnBkD,EAAE,KAAK,YAAA,EAAc,SAASlD,EAAgB,YAAA,CAAa,IAC1DkD,EAAE,aAAe,IAAI,YAAA,EAAc,SAASlD,EAAgB,aAAa,EAAA,EAE7E,IAAI+C,GACH5N,EAAAA,KAAC,QAAA,CAEC,UAAW,+FACT+K,IAAoB6C,EAAM,GACtB,0EACA,sDACN,GACA,QAAS,SAASA,EAAM,EAAE,GAE1B,SAAA,CAAAxP,EAAAA,IAAC,QAAA,CACC,GAAI,SAASwP,EAAM,EAAE,GACrB,KAAK,QACL,KAAK,gBACL,QAAS7C,IAAoB6C,EAAM,GACnC,SAAU,IAAM5C,EAAmB4C,EAAM,EAAE,EAC3C,UAAU,6EAAA,CAAA,EAEZ5N,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAA5B,EAAAA,IAAC,OAAA,CAAK,UAAU,yCAA0C,SAAAwP,EAAM,KAAK,EACrE5N,EAAAA,KAAC,IAAA,CAAE,UAAU,sCACV,SAAA,CAAA4N,EAAM,YAAY,IAAEtN,EAAE,2BAA2B,EACjDsN,EAAM,aAAe,MAAMA,EAAM,WAAW,EAAA,CAAA,CAC/C,CAAA,CAAA,CACF,CAAA,CAAA,EAtBKA,EAAM,EAAA,CAwBd,EACL,EAGF5N,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAA5B,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMoM,EAAe,EAAK,EACnC,UAAU,uJAET,WAAE,eAAe,CAAA,CAAA,EAEpBxK,EAAAA,KAAC,SAAA,CACC,QAAS6M,GACT,SAAU,CAAC9B,GAAmBE,EAC9B,UAAU,gMAET,SAAA,CAAAA,GAAkB7M,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,sBAAA,CAAuB,EAC5DrE,EAAE,YAAY,CAAA,CAAA,CAAA,CACjB,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,CAAA,EAEJ,EAID2H,IAAc,SACbjI,OAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,mDACX,SAAA,CAAAM,EAAE,wBAAwB,EAAE,KAAGgC,EAAK,MAAM,OAAO,GAAA,EACpD,EACAtC,EAAAA,KAAC,SAAA,CACC,QAASuM,GACT,UAAU,sLAEV,SAAA,CAAAnO,EAAAA,IAACG,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EACzB+B,EAAE,sBAAsB,CAAA,CAAA,CAAA,CAC3B,EACF,EAECgC,EAAK,MAAM,SAAW,EACrBlE,EAAAA,IAAC,MAAA,CAAI,UAAU,iDACZ,SAAAkC,EAAE,0BAA0B,EAC/B,QAEC,MAAA,CAAI,UAAU,aACZ,SAAAgC,EAAK,MAAM,IAAI9B,GACdR,EAAAA,KAAC,MAAA,CAEC,UAAU,sHAEV,SAAA,CAAAA,EAAAA,KAAC6N,GAAAA,KAAA,CACC,GAAI,yBAAyBrN,EAAK,EAAE,GACpC,UAAU,6EAEV,SAAA,CAAApC,EAAAA,IAAC,MAAA,CAAI,UAAU,uFACb,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAU,qDACb,SAAAoC,EAAK,SAAS,MAAM,GAAG,EAAE,IAAIyN,GAAKA,EAAE,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,YAAA,EAAc,MAAM,EAAG,CAAC,CAAA,CAC/E,EACF,EACAjO,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAA5B,EAAAA,IAAC,MAAA,CAAI,UAAU,kDAAmD,SAAAoC,EAAK,SAAS,EAChFpC,EAAAA,IAAC,MAAA,CAAI,UAAU,gDAAiD,WAAK,KAAA,CAAM,CAAA,CAAA,CAC7E,CAAA,CAAA,CAAA,EAEFA,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMqO,GAAiBjM,EAAK,EAAE,EACvC,SAAU6J,KAAmB7J,EAAK,GAClC,UAAU,kKACV,MAAOF,EAAE,yBAAyB,EAEjC,SAAA+J,KAAmB7J,EAAK,GACvBpC,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,sBAAA,CAAuB,EAE1CvG,EAAAA,IAACK,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,CAAA,CAAA,CAEhC,CAAA,EA5BK+B,EAAK,EAAA,CA8Bb,EACH,EAIDiJ,UACE,MAAA,CAAI,UAAU,mFACb,SAAAzJ,EAAAA,KAAC,MAAA,CAAI,UAAU,iJACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAA5B,MAAC,KAAA,CAAG,UAAU,+CACX,SAAAkC,EAAE,2BAA2B,EAChC,EACAlC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMsL,EAAc,EAAK,EAClC,UAAU,kFAEV,SAAAtL,EAAAA,IAACuI,EAAAA,EAAA,CAAE,UAAU,qCAAA,CAAsC,CAAA,CAAA,CACrD,EACF,QAEC,MAAA,CAAI,UAAU,OACb,SAAA3G,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAA5B,EAAAA,IAAC0P,EAAAA,OAAA,CAAO,UAAU,8EAAA,CAA+E,EACjG1P,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAO2L,EACP,SAAWlD,GAAMmD,GAAkBnD,EAAE,OAAO,KAAK,EACjD,UAAU,kNACV,YAAavG,EAAE,oCAAoC,CAAA,CAAA,CACrD,CAAA,CACF,CAAA,CACF,EAECuJ,GACCzL,EAAAA,IAAC,MAAA,CAAI,UAAU,wCACb,SAAAA,MAACuG,EAAAA,QAAA,CAAQ,UAAU,sDAAsD,EAC3E,EAEAvG,EAAAA,IAAC,MAAA,CAAI,UAAU,qCACZ,SAAAuL,GACE,OAAOuE,GACN,CAAC5L,EAAK,MAAM,KAAK6L,GAAMA,EAAG,KAAOD,EAAE,EAAE,IACpCnE,IAAmB,IAClBmE,EAAE,SAAS,YAAA,EAAc,SAASnE,EAAe,YAAA,CAAa,GAC9DmE,EAAE,MAAM,YAAA,EAAc,SAASnE,EAAe,aAAa,EAAA,EAE9D,IAAIvJ,GACHR,EAAAA,KAAC,QAAA,CAEC,UAAW,+FACTiK,IAAmBzJ,EAAK,GACpB,0EACA,sDACN,GACA,QAAS,QAAQA,EAAK,EAAE,GAExB,SAAA,CAAApC,EAAAA,IAAC,QAAA,CACC,GAAI,QAAQoC,EAAK,EAAE,GACnB,KAAK,QACL,KAAK,eACL,QAASyJ,IAAmBzJ,EAAK,GACjC,SAAU,IAAM0J,EAAkB1J,EAAK,EAAE,EACzC,UAAU,6EAAA,CAAA,EAEZR,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAA5B,EAAAA,IAAC,OAAA,CAAK,UAAU,yCAA0C,SAAAoC,EAAK,SAAS,EACxEpC,EAAAA,IAAC,IAAA,CAAE,UAAU,sCAAuC,WAAK,KAAA,CAAM,CAAA,CAAA,CACjE,CAAA,CAAA,EAnBKoC,EAAK,EAAA,CAqBb,EACL,EAGFR,EAAAA,KAAC,MAAA,CAAI,UAAU,8BACb,SAAA,CAAA5B,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMsL,EAAc,EAAK,EAClC,UAAU,uJAET,WAAE,eAAe,CAAA,CAAA,EAEpB1J,EAAAA,KAAC,SAAA,CACC,QAASwM,GACT,SAAU,CAACvC,GAAkBE,GAC7B,UAAU,gMAET,SAAA,CAAAA,IAAiB/L,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,sBAAA,CAAuB,EAC3DrE,EAAE,YAAY,CAAA,CAAA,CAAA,CACjB,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,CAAA,EAEJ,EAID2H,IAAc,gBACbjI,OAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,mDACX,SAAA,CAAAM,EAAE,+BAA+B,EAAE,KAAGqI,EAAa,OAAO,GAAA,EAC7D,EACC0D,GAAmB,OAAS,GAC3BrM,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMsJ,EAAsB,EAAI,EACzC,UAAU,sLAEV,SAAA,CAAAlL,EAAAA,IAACG,EAAAA,KAAA,CAAK,UAAU,SAAA,CAAU,EACzB+B,EAAE,6BAA6B,CAAA,CAAA,CAAA,CAClC,EAEJ,EAGC+I,GACCrJ,EAAAA,KAAC,MAAA,CAAI,UAAU,kGACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAA5B,MAAC,KAAA,CAAG,UAAU,yCACX,SAAAkC,EAAE,gCAAgC,EACrC,EACAlC,EAAAA,IAAC,SAAA,CACC,QAAS6N,GACT,UAAU,yCAEV,SAAA7N,EAAAA,IAACuI,EAAAA,EAAA,CAAE,UAAU,sCAAA,CAAuC,CAAA,CAAA,CACtD,EACF,EACA3G,EAAAA,KAAC,MAAA,CAAI,UAAU,aACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAA5B,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,kCAAkC,EACvC,EACAN,EAAAA,KAAC,SAAA,CACC,MAAOuJ,EACP,SAAU1C,GAAK2C,EAAsB3C,EAAE,OAAO,KAAK,EACnD,UAAU,yIAEV,SAAA,CAAAzI,MAAC,SAAA,CAAO,MAAM,GAAI,SAAAkC,EAAE,wCAAwC,EAAE,EAC7D+L,GAAmB,IAAIC,GACtBlO,EAAAA,IAAC,SAAA,CAAuB,MAAOkO,EAAK,KAAO,SAAAA,EAAK,KAAA,EAAnCA,EAAK,IAAoC,CACvD,CAAA,CAAA,CAAA,CACH,EACF,EACC/C,GACCvJ,EAAAA,KAAAoO,WAAA,CACE,SAAA,CAAApO,OAAC,MAAA,CACC,SAAA,CAAA5B,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,8BAA8B,EACnC,EACAlC,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAO6K,EAAgB,KACvB,SAAUpC,GAAKqC,EAAmBxG,IAAS,CAAE,GAAGA,EAAM,KAAMmE,EAAE,OAAO,KAAA,EAAQ,EAC7E,UAAU,wIAAA,CAAA,CACZ,EACF,SACC,MAAA,CACC,SAAA,CAAAzI,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,mCAAmC,EACxC,EACAlC,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAO6K,EAAgB,UACvB,SAAUpC,GAAKqC,EAAmBxG,IAAS,CAAE,GAAGA,EAAM,UAAWmE,EAAE,OAAO,KAAA,EAAQ,EAClF,UAAU,wIAAA,CAAA,CACZ,EACF,SACC,MAAA,CACC,SAAA,CAAAzI,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,qCAAqC,EAC1C,EACAlC,EAAAA,IAAC,WAAA,CACC,MAAO6K,EAAgB,aAAe,GACtC,SAAUpC,GAAKqC,EAAmBxG,IAAS,CAAE,GAAGA,EAAM,YAAamE,EAAE,OAAO,KAAA,EAAQ,EACpF,KAAM,EACN,UAAU,oJAAA,CAAA,CACZ,EACF,EACA7G,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAA5B,EAAAA,IAAC,SAAA,CACC,QAAS6N,GACT,UAAU,+IAET,WAAE,eAAe,CAAA,CAAA,EAEpBjM,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMkM,GAAsB3C,CAAkB,EACvD,SAAUJ,GAAqB,CAACF,EAAgB,MAAQ,CAACA,EAAgB,UACzE,UAAU,wLAET,SAAA,CAAAE,GAAqB/K,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,sBAAA,CAAuB,EAC/DrE,EAAE,aAAa,CAAA,CAAA,CAAA,CAClB,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CAEJ,CAAA,EACF,EAGDuI,SACE,MAAA,CAAI,UAAU,yCACb,SAAAzK,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,qDAAA,CAAsD,CAAA,CAC3E,EAED,CAACkE,GAAuBF,EAAa,SAAW,GAC/CvK,EAAAA,IAAC,MAAA,CAAI,UAAU,iDACZ,SAAAkC,EAAE,wCAAwC,CAAA,CAC7C,EAED,CAACuI,GAAuBF,EAAa,OAAS,GAC7CvK,EAAAA,IAAC,MAAA,CAAI,UAAU,YACZ,SAAAuK,EAAa,IAAIqD,GAAS,CACzB,MAAMqC,EAAW5G,GAAoB,QAAU6G,EAAE,OAAStC,EAAM,YAAY,EACtEuC,GAAYxF,IAAuBiD,EAAM,aAE/C,OACEhM,EAAAA,KAAC,MAAA,CAEC,UAAW,2CACTuO,GACI,0DACA,qDACN,GAEA,SAAA,CAAAvO,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAAC,OAAA,CAAK,UAAU,yGACb,SAAA4N,EAAM,aACT,QACC,OAAA,CAAK,UAAU,uCACb,SAAAqC,GAAU,OAASrC,EAAM,YAAA,CAC5B,CAAA,EACF,EACC,CAACuC,IACAvO,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAA5B,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM2N,EAAqBC,CAAK,EACzC,UAAU,6GACV,MAAO1L,EAAE,aAAa,EAEtB,SAAAlC,EAAAA,IAACoQ,EAAAA,MAAA,CAAM,UAAU,SAAA,CAAU,CAAA,CAAA,EAE7BpQ,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMgO,GAAwBJ,EAAM,YAAY,EACzD,UAAU,uGACV,MAAO1L,EAAE,eAAe,EAExB,SAAAlC,EAAAA,IAACK,EAAAA,OAAA,CAAO,UAAU,SAAA,CAAU,CAAA,CAAA,CAC9B,CAAA,CACF,CAAA,EAEJ,EAEC8P,GACCvO,EAAAA,KAAC,MAAA,CAAI,UAAU,kBACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAA5B,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,8BAA8B,EACnC,EACAlC,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAO6K,EAAgB,KACvB,SAAUpC,GAAKqC,EAAmBxG,KAAS,CAAE,GAAGA,GAAM,KAAMmE,EAAE,OAAO,KAAA,EAAQ,EAC7E,UAAU,wIAAA,CAAA,CACZ,EACF,SACC,MAAA,CACC,SAAA,CAAAzI,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,mCAAmC,EACxC,EACAlC,EAAAA,IAAC,QAAA,CACC,KAAK,OACL,MAAO6K,EAAgB,UACvB,SAAUpC,GAAKqC,EAAmBxG,KAAS,CAAE,GAAGA,GAAM,UAAWmE,EAAE,OAAO,KAAA,EAAQ,EAClF,UAAU,wIAAA,CAAA,CACZ,EACF,SACC,MAAA,CACC,SAAA,CAAAzI,MAAC,QAAA,CAAM,UAAU,8DACd,SAAAkC,EAAE,qCAAqC,EAC1C,EACAlC,EAAAA,IAAC,WAAA,CACC,MAAO6K,EAAgB,aAAe,GACtC,SAAUpC,GAAKqC,EAAmBxG,KAAS,CAAE,GAAGA,GAAM,YAAamE,EAAE,OAAO,KAAA,EAAQ,EACpF,KAAM,EACN,UAAU,oJAAA,CAAA,CACZ,EACF,EACA7G,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAA5B,EAAAA,IAAC,SAAA,CACC,QAAS6N,GACT,UAAU,+IAET,WAAE,eAAe,CAAA,CAAA,EAEpBjM,EAAAA,KAAC,SAAA,CACC,QAAS,IAAMkM,GAAsBF,EAAM,YAAY,EACvD,SAAU7C,GAAqB,CAACF,EAAgB,MAAQ,CAACA,EAAgB,UACzE,UAAU,wLAET,SAAA,CAAAE,GAAqB/K,EAAAA,IAACuG,EAAAA,QAAA,CAAQ,UAAU,sBAAA,CAAuB,EAC/DrE,EAAE,aAAa,CAAA,CAAA,CAAA,CAClB,CAAA,CACF,CAAA,CAAA,CACF,EAEAN,EAAAA,KAAC,MAAA,CAAI,UAAU,aACb,SAAA,CAAA5B,EAAAA,IAAC,MAAA,CAAI,UAAU,yCAA0C,SAAA4N,EAAM,KAAK,EACpEhM,EAAAA,KAAC,MAAA,CAAI,UAAU,uCACZ,SAAA,CAAAM,EAAE,mCAAmC,EAAE,KAAG0L,EAAM,SAAA,EACnD,EACCA,EAAM,aACL5N,EAAAA,IAAC,OAAI,UAAU,2CAA4C,WAAM,WAAA,CAAY,CAAA,CAAA,CAEjF,CAAA,CAAA,EAjGG4N,EAAM,YAAA,CAqGjB,CAAC,CAAA,CACH,CAAA,CAAA,CAEJ,CAAA,CAAA,CAEJ,CAAA,EACF,EAlxBEhM,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACb,SAAA,CAAA5B,MAAC,IAAA,CAAE,UAAU,+BAAgC,SAAAkC,EAAE,qBAAqB,EAAE,EACtElC,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMwJ,EAAS,mCAAmC,EAC3D,UAAU,wFAET,WAAE,uBAAuB,CAAA,CAAA,CAC5B,EACF,CA4wBN"}
|
|
1
|
+
{"version":3,"file":"RoleDetailPage-JTm5lD1_.js","sources":["../../src/components/platform/administration/permissions/RolePermissionMatrix.tsx","../../src/pages/platform/administration/permissions/RoleDetailPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\r\nimport React, { useState, useMemo, useCallback, createRef } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Loader2, AlertCircle, ChevronDown, ChevronRight, FolderOpen, Box, FileText, Database, Check, Star, Eye, Ban, Save, X, Plus, Edit, Trash2, UserPlus, Play, Shield } from 'lucide-react';\r\nimport { usePermissionMatrix } from '@/hooks/usePermissionMatrix';\r\nimport { useCollapsibleState } from '@/hooks/useCollapsibleState';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { hasFullAccess } from '@/utils/permissions';\r\nimport { groupByApplicationWithSections, calculatePermissionStatus, calculateModuleWithSectionsStatus, getPermissionCellBackground } from '@/utils/permissionUtils';\r\nimport { PermissionStatusIndicator } from './PermissionStatusIndicator';\r\nimport { PermissionPopover } from '../PermissionPopover';\r\nimport type { ResourceNode, PermissionStatus, ModuleWithSections } from './types';\r\n\r\ninterface RolePermissionMatrixProps {\r\n readonly roleId: string;\r\n}\r\n\r\n// Action icons and colors (same as PermissionCellPopover)\r\nconst ACTION_ICONS: Record<string, React.ReactNode> = {\r\n '*': <Shield className=\"h-3 w-3\" />,\r\n read: <Eye className=\"h-3 w-3\" />,\r\n create: <Plus className=\"h-3 w-3\" />,\r\n update: <Edit className=\"h-3 w-3\" />,\r\n delete: <Trash2 className=\"h-3 w-3\" />,\r\n assign: <UserPlus className=\"h-3 w-3\" />,\r\n execute: <Play className=\"h-3 w-3\" />,\r\n};\r\n\r\nconst ACTION_COLORS: Record<string, string> = {\r\n '*': 'bg-[var(--accent-bg)] text-[var(--accent-text)] border-[var(--accent-border)]',\r\n read: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n create: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n update: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n delete: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\r\n assign: 'bg-[var(--accent-bg)] text-[var(--accent-text)] border-[var(--accent-border)]',\r\n execute: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n};\r\n\r\n// Pure function to apply application/module filter\r\nfunction applyApplicationModuleFilterHelper(\r\n grouped: ReturnType<typeof groupByApplicationWithSections>,\r\n applicationFilter: string,\r\n moduleFilter: string\r\n) {\r\n return grouped\r\n .filter(app => applicationFilter === 'all' || app.application === applicationFilter)\r\n .map(app => ({\r\n ...app,\r\n modules: app.modules.filter(m => moduleFilter === 'all' || m.module.moduleLabel === moduleFilter)\r\n }))\r\n .filter(app => app.modules.length > 0);\r\n}\r\n\r\n// Pure function to apply status filter\r\nfunction applyStatusFilterHelper(\r\n grouped: ReturnType<typeof groupByApplicationWithSections>,\r\n statusFilters: Set<PermissionStatus>,\r\n getModuleStatus: (m: ModuleWithSections) => { status: PermissionStatus; grantedCount: number; totalCount: number }\r\n) {\r\n return grouped.map(app => ({\r\n ...app,\r\n modules: app.modules.filter(m => {\r\n const { status } = getModuleStatus(m);\r\n return statusFilters.has(status);\r\n })\r\n })).filter(app => app.modules.length > 0);\r\n}\r\n\r\n// Sub-component for rendering section and resource rows\r\ninterface SectionResourceRowsProps {\r\n readonly section: ResourceNode;\r\n readonly resources: ResourceNode[];\r\n readonly moduleIndex: number;\r\n readonly sectionIndex: number;\r\n readonly collapsedSections: Set<string>;\r\n readonly renderResourceRow: (resource: ResourceNode, rowIndex: number, level: 'module' | 'section' | 'resource', hasChildren: boolean, isCollapsed: boolean) => React.ReactNode;\r\n}\r\n\r\nfunction SectionResourceRows({\r\n section,\r\n resources,\r\n moduleIndex,\r\n sectionIndex,\r\n collapsedSections,\r\n renderResourceRow,\r\n}: SectionResourceRowsProps) {\r\n const hasResources = resources.length > 0;\r\n const isSectionCollapsed = collapsedSections.has(section.id);\r\n\r\n return (\r\n <React.Fragment key={section.id}>\r\n {/* Section Row */}\r\n {renderResourceRow(section, moduleIndex + sectionIndex + 1, 'section', hasResources, isSectionCollapsed)}\r\n\r\n {/* Resource Rows (if section has resources and is not collapsed) */}\r\n {hasResources && !isSectionCollapsed && resources.map((resource, resourceIndex) =>\r\n renderResourceRow(resource, moduleIndex + sectionIndex + resourceIndex + 2, 'resource', false, false)\r\n )}\r\n </React.Fragment>\r\n );\r\n}\r\n\r\nexport function RolePermissionMatrix({ roleId }: RolePermissionMatrixProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const { user } = useAuth();\r\n\r\n const { collapsedApps, toggleApp } = useCollapsibleState();\r\n const [collapsedModules, setCollapsedModules] = useState<Set<string>>(new Set());\r\n const [collapsedSections, setCollapsedSections] = useState<Set<string>>(new Set());\r\n const [statusFilters, setStatusFilters] = useState<Set<PermissionStatus>>(new Set());\r\n const [openPopover, setOpenPopover] = useState<string | null>(null);\r\n\r\n // Filter states\r\n const [applicationFilter, setApplicationFilter] = useState<string>('all');\r\n const [moduleFilter, setModuleFilter] = useState<string>('all');\r\n\r\n // Super Admin can edit system roles\r\n const canEditSystemRoles = useMemo(() => {\r\n if (!user) return false;\r\n return hasFullAccess(user.permissions);\r\n }, [user]);\r\n\r\n const {\r\n loading,\r\n error,\r\n roles,\r\n filteredResources,\r\n hasChanges,\r\n saving,\r\n saveSuccess,\r\n saveError,\r\n togglePermission,\r\n saveChanges,\r\n resetChanges,\r\n getPermissionInheritance,\r\n } = usePermissionMatrix({ canEditSystemRoles });\r\n\r\n // Find the specific role\r\n const role = useMemo(() => {\r\n return roles.find(r => r.id === roleId);\r\n }, [roles, roleId]);\r\n\r\n // Check if role is editable\r\n const isRoleEditable = useMemo(() => {\r\n if (!role) return false;\r\n if (role.isSystem && !canEditSystemRoles) return false;\r\n return true;\r\n }, [role, canEditSystemRoles]);\r\n\r\n const toggleStatusFilter = (status: PermissionStatus) => {\r\n setStatusFilters(prev => {\r\n const next = new Set(prev);\r\n if (next.has(status)) {\r\n next.delete(status);\r\n } else {\r\n next.add(status);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const toggleModule = (moduleId: string) => {\r\n setCollapsedModules(prev => {\r\n const next = new Set(prev);\r\n if (next.has(moduleId)) {\r\n next.delete(moduleId);\r\n } else {\r\n next.add(moduleId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const toggleSection = (sectionId: string) => {\r\n setCollapsedSections(prev => {\r\n const next = new Set(prev);\r\n if (next.has(sectionId)) {\r\n next.delete(sectionId);\r\n } else {\r\n next.add(sectionId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n // Build filter options from resources\r\n const filterOptions = useMemo(() => {\r\n const applications: { app: string; label: string }[] = [];\r\n const modules: { app: string; module: string; label: string }[] = [];\r\n\r\n filteredResources.forEach(resource => {\r\n if (resource.level === 'module') {\r\n const appKey = resource.applicationLabel;\r\n if (!applications.find(a => a.app === appKey)) {\r\n applications.push({\r\n app: resource.applicationLabel,\r\n label: resource.applicationLabel\r\n });\r\n }\r\n\r\n modules.push({\r\n app: resource.applicationLabel,\r\n module: resource.moduleLabel,\r\n label: resource.moduleLabel\r\n });\r\n }\r\n });\r\n\r\n return {\r\n applications: applications.sort((a, b) => a.label.localeCompare(b.label)),\r\n modules: modules.sort((a, b) => a.label.localeCompare(b.label))\r\n };\r\n }, [filteredResources]);\r\n\r\n // Handle permission toggle\r\n const handleTogglePermission = useCallback((permissionId: string) => {\r\n if (!role || !isRoleEditable) return;\r\n togglePermission(role.id, permissionId);\r\n }, [role, isRoleEditable, togglePermission]);\r\n\r\n // Check if a permission is granted\r\n const isPermissionGrantedFn = useCallback((permissionId: string): boolean => {\r\n if (!role) return false;\r\n const info = getPermissionInheritance(role.id, permissionId);\r\n return info.isDirect || info.isInherited;\r\n }, [role, getPermissionInheritance]);\r\n\r\n // Calculate permission status for this role on a module (including sections)\r\n const getModuleStatus = useCallback((moduleWithSections: ModuleWithSections): { status: PermissionStatus; grantedCount: number; totalCount: number } => {\r\n return calculateModuleWithSectionsStatus(\r\n moduleWithSections.module,\r\n moduleWithSections.sections,\r\n isPermissionGrantedFn\r\n );\r\n }, [isPermissionGrantedFn]);\r\n\r\n // Calculate permission status for a single resource\r\n const getResourceStatus = useCallback((resource: ResourceNode): { status: PermissionStatus; grantedCount: number } => {\r\n return calculatePermissionStatus(resource, isPermissionGrantedFn);\r\n }, [isPermissionGrantedFn]);\r\n\r\n // Get granted permissions for a resource\r\n const getGrantedPermissions = useCallback((resource: ResourceNode): string[] => {\r\n if (!role) return [];\r\n\r\n return resource.permissions\r\n .filter(p => {\r\n const info = getPermissionInheritance(role.id, p.id);\r\n return info.isDirect || info.isInherited;\r\n })\r\n .map(p => p.action);\r\n }, [role, getPermissionInheritance]);\r\n\r\n\r\n const applyApplicationModuleFilter = useCallback((grouped: ReturnType<typeof groupByApplicationWithSections>) => {\r\n return applyApplicationModuleFilterHelper(grouped, applicationFilter, moduleFilter);\r\n }, [applicationFilter, moduleFilter]);\r\n\r\n const applyStatusFilter = useCallback((grouped: ReturnType<typeof groupByApplicationWithSections>) => {\r\n if (statusFilters.size === 0) return grouped;\r\n return applyStatusFilterHelper(grouped, statusFilters, getModuleStatus);\r\n }, [statusFilters, getModuleStatus]);\r\n\r\n const groupedResources = useMemo(() => {\r\n let grouped = groupByApplicationWithSections(filteredResources);\r\n grouped = applyApplicationModuleFilter(grouped);\r\n grouped = applyStatusFilter(grouped);\r\n return grouped;\r\n }, [filteredResources, applyApplicationModuleFilter, applyStatusFilter]);\r\n\r\n // Get total module count for stats\r\n const totalModuleCount = useMemo(() => {\r\n return groupedResources.reduce((sum, app) =>\r\n sum + app.modules.length, 0);\r\n }, [groupedResources]);\r\n\r\n const handleToggleCollapse = useCallback((resourceId: string, level: 'module' | 'section' | 'resource') => {\r\n if (level === 'module') {\r\n toggleModule(resourceId);\r\n } else if (level === 'section') {\r\n toggleSection(resourceId);\r\n }\r\n }, [toggleModule, toggleSection]);\r\n\r\n const handleCellClick = (resourceId: string) => {\r\n if (openPopover === resourceId) {\r\n setOpenPopover(null);\r\n } else {\r\n setOpenPopover(resourceId);\r\n }\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <div className=\"text-center\">\r\n <Loader2 className=\"h-8 w-8 animate-spin text-[var(--color-accent-500)] mx-auto mb-4\" />\r\n <p className=\"text-[var(--text-secondary)]\">{t('userPermissions.loading')}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <p className=\"text-[var(--error-text)]\">{error}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!role) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.notFound')}\r\n </div>\r\n );\r\n }\r\n\r\n const getRoleResourceIcon = (level: 'module' | 'section' | 'resource') => {\r\n if (level === 'resource') return <Database className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n if (level === 'section') return <FileText className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n return <Box className=\"h-3.5 w-3.5 text-[var(--text-secondary)]\" />;\r\n };\r\n\r\n const getRoleResourceLabelClass = (level: 'module' | 'section' | 'resource'): string => {\r\n if (level === 'resource') return 'text-[var(--text-muted)] italic';\r\n if (level === 'section') return 'text-[var(--text-secondary)]';\r\n return 'font-medium text-[var(--text-primary)]';\r\n };\r\n\r\n const getRolePaddingClass = (level: 'module' | 'section' | 'resource'): string => {\r\n if (level === 'resource') return 'pl-28';\r\n if (level === 'section') return 'pl-22';\r\n return 'pl-16';\r\n };\r\n\r\n const renderToggleButton = (hasChildren: boolean, resourceId: string, level: 'module' | 'section' | 'resource', isCollapsed: boolean) => {\r\n if (!hasChildren) return null;\r\n return (\r\n <button\r\n onClick={() => handleToggleCollapse(resourceId, level)}\r\n className=\"p-0.5 hover:bg-[var(--bg-hover)] rounded\"\r\n >\r\n {isCollapsed ? (\r\n <ChevronRight className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n );\r\n };\r\n\r\n const renderPermissionBadges = (grantedPermissions: string[]) => {\r\n if (grantedPermissions.length === 0) {\r\n return (\r\n <span className=\"text-xs text-[var(--text-muted)] italic\">\r\n {t('assignments.noPermissions')}\r\n </span>\r\n );\r\n }\r\n return grantedPermissions.map((action) => {\r\n const actionColor = ACTION_COLORS[action] || 'bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)]';\r\n const icon = ACTION_ICONS[action] || <Eye className=\"h-3 w-3\" />;\r\n return (\r\n <div\r\n key={action}\r\n className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-[var(--radius-badge)] border text-xs font-medium ${actionColor}`}\r\n title={t(`assignments.actions.${action === '*' ? 'all' : action}.description`)}\r\n >\r\n {icon}\r\n <span className=\"capitalize\">\r\n {t(`assignments.actions.${action === '*' ? 'all' : action}.label`)}\r\n </span>\r\n </div>\r\n );\r\n });\r\n };\r\n\r\n const renderResourceRow = (\r\n resource: ResourceNode,\r\n rowIndex: number,\r\n level: 'module' | 'section' | 'resource',\r\n hasChildren: boolean = false,\r\n isCollapsed: boolean = false\r\n ) => {\r\n const { status, grantedCount } = getResourceStatus(resource);\r\n const isPopoverOpen = openPopover === resource.id;\r\n const buttonRef = createRef<HTMLButtonElement>();\r\n const cellBg = getPermissionCellBackground(status);\r\n const grantedPermissions = getGrantedPermissions(resource);\r\n const paddingLeft = getRolePaddingClass(level);\r\n const rowBgClass = rowIndex % 2 === 0 ? 'item-light' : 'item-medium';\r\n\r\n return (\r\n <tr\r\n key={resource.id}\r\n className={`hover:bg-[var(--bg-hover)] ${rowBgClass}`}\r\n >\r\n <td\r\n className={`sticky left-0 z-10 ${rowBgClass} px-3 py-2 ${paddingLeft}`}\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n {renderToggleButton(hasChildren, resource.id, level, isCollapsed)}\r\n {getRoleResourceIcon(level)}\r\n <span className={`text-sm ${getRoleResourceLabelClass(level)}`}>\r\n {resource.moduleLabel}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n ({resource.permissions.length})\r\n </span>\r\n </div>\r\n </td>\r\n\r\n <td\r\n className={`px-0 py-1 text-center relative ${cellBg}`}\r\n style={{ width: '60px', minWidth: '60px', maxWidth: '60px' }}\r\n >\r\n <button\r\n ref={buttonRef}\r\n type=\"button\"\r\n onClick={() => isRoleEditable && handleCellClick(resource.id)}\r\n disabled={!isRoleEditable}\r\n className={`w-full h-full min-h-[36px] flex items-center justify-center rounded transition-colors ${\r\n !isRoleEditable\r\n ? 'cursor-not-allowed opacity-50'\r\n : 'hover:opacity-80'\r\n } ${\r\n isPopoverOpen ? 'ring-2 ring-[var(--color-accent-500)]' : ''\r\n }`}\r\n title={\r\n !isRoleEditable\r\n ? `${role.name} - ${t('assignments.systemRoleReadOnly')}`\r\n : `${role.name} - ${resource.moduleLabel}: ${grantedCount}/${resource.permissions.length}`\r\n }\r\n >\r\n <PermissionStatusIndicator\r\n status={status}\r\n grantedCount={grantedCount}\r\n totalCount={resource.permissions.length}\r\n />\r\n </button>\r\n {isPopoverOpen && isRoleEditable && (\r\n <PermissionPopover\r\n mode=\"editable\"\r\n role={role}\r\n resource={resource}\r\n onTogglePermission={handleTogglePermission}\r\n onClose={() => setOpenPopover(null)}\r\n getPermissionInheritance={(_, permId) => getPermissionInheritance(role.id, permId)}\r\n />\r\n )}\r\n </td>\r\n\r\n <td className=\"px-3 py-2\">\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {renderPermissionBadges(grantedPermissions)}\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Fixed height container for save banner to prevent layout shift */}\r\n <div className=\"min-h-[52px]\">\r\n {saveSuccess && (\r\n <div className=\"flex items-center justify-between p-3 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <Check className=\"h-4 w-4 text-[var(--success-text)]\" />\r\n <p className=\"text-sm text-[var(--success-text)] font-medium\">\r\n {t('common.savedSuccessfully', 'Sauvegardé avec succès !')}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n {!saveSuccess && saving && (\r\n <div className=\"flex items-center justify-between p-3 rounded-[var(--radius-card)] bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <Loader2 className=\"h-4 w-4 animate-spin text-[var(--info-text)]\" />\r\n <p className=\"text-sm text-[var(--info-text)] font-medium\">\r\n {t('common.saving', 'Sauvegarde en cours...')}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n {!saveSuccess && !saving && hasChanges && (\r\n <div className=\"flex items-center justify-between p-3 rounded-[var(--radius-card)] bg-[var(--warning-bg)] border border-[var(--warning-border)]\">\r\n <p className=\"text-sm text-[var(--warning-text)]\">\r\n {t('assignments.unsavedChanges', 'You have unsaved changes')}\r\n </p>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={resetChanges}\r\n disabled={saving}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-50\"\r\n >\r\n <X className=\"h-4 w-4\" />\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={saveChanges}\r\n disabled={saving}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50\"\r\n >\r\n {saving ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Save className=\"h-4 w-4\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n {!saveSuccess && !saving && !hasChanges && (\r\n <div className=\"h-[52px]\" />\r\n )}\r\n </div>\r\n\r\n {/* Save error */}\r\n {saveError && (\r\n <div className=\"p-3 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2\">\r\n <AlertCircle className=\"h-4 w-4 text-[var(--error-text)]\" />\r\n <p className=\"text-sm text-[var(--error-text)]\">{saveError}</p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n\r\n {/* Filter Dropdowns */}\r\n <div className=\"flex flex-wrap items-center gap-4\">\r\n <div className=\"flex items-center gap-2\">\r\n <label className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('userPermissions.filters.application')}:\r\n </label>\r\n <select\r\n value={applicationFilter}\r\n onChange={(e) => {\r\n setApplicationFilter(e.target.value);\r\n setModuleFilter('all');\r\n }}\r\n className=\"px-3 py-1.5 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('userPermissions.filters.allApplications')}</option>\r\n {filterOptions.applications\r\n .map(app => (\r\n <option key={app.app} value={app.app}>{app.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <label className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('userPermissions.filters.module')}:\r\n </label>\r\n <select\r\n value={moduleFilter}\r\n onChange={(e) => setModuleFilter(e.target.value)}\r\n className=\"px-3 py-1.5 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('userPermissions.filters.allModules')}</option>\r\n {filterOptions.modules\r\n .filter(mod =>\r\n (applicationFilter === 'all' || mod.app === applicationFilter)\r\n )\r\n .map(mod => (\r\n <option key={`${mod.app}:${mod.module}`} value={mod.module}>{mod.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n\r\n {/* Status Filter Buttons - Using CSS variables for colors */}\r\n <div className=\"flex flex-wrap items-center gap-3\">\r\n <span className=\"text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('userPermissions.filterByStatus')}:\r\n </span>\r\n <div className=\"flex flex-wrap gap-2\">\r\n <button\r\n onClick={() => toggleStatusFilter('all')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('all')\r\n ? 'bg-[var(--success-bg)] border-[var(--success-border)] text-[var(--success-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--success-border)]'\r\n }`}\r\n >\r\n <Check className={`h-3.5 w-3.5 ${statusFilters.has('all') ? '' : 'text-[var(--success-dot)]'}`} />\r\n {t('assignments.complete')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('some')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('some')\r\n ? 'bg-[var(--warning-bg)] border-[var(--warning-border)] text-[var(--warning-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--warning-border)]'\r\n }`}\r\n >\r\n <Star className={`h-3.5 w-3.5 ${statusFilters.has('some') ? '' : 'text-[var(--warning-dot)]'}`} />\r\n {t('assignments.partial')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('read-only')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('read-only')\r\n ? 'bg-[var(--info-bg)] border-[var(--info-border)] text-[var(--info-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--info-border)]'\r\n }`}\r\n >\r\n <Eye className={`h-3.5 w-3.5 ${statusFilters.has('read-only') ? '' : 'text-[var(--info-dot)]'}`} />\r\n {t('assignments.readOnly')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('none')}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border transition-colors ${\r\n statusFilters.has('none')\r\n ? 'bg-[var(--error-bg)] border-[var(--error-border)] text-[var(--error-text)]'\r\n : 'bg-[var(--bg-tertiary)] border-[var(--border-color)] text-[var(--text-secondary)] hover:border-[var(--error-border)]'\r\n }`}\r\n >\r\n <Ban className={`h-3.5 w-3.5 ${statusFilters.has('none') ? '' : 'text-[var(--text-muted)]'}`} />\r\n {t('assignments.none')}\r\n </button>\r\n </div>\r\n {statusFilters.size > 0 && (\r\n <button\r\n onClick={() => setStatusFilters(new Set())}\r\n className=\"text-xs text-[var(--color-accent-500)] hover:text-[var(--color-accent-600)] underline\"\r\n >\r\n {t('assignments.clearFilters')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Stats */}\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--bg-tertiary)] text-[var(--text-secondary)]\">\r\n {totalModuleCount} {t('assignments.modules')}\r\n </span>\r\n </div>\r\n\r\n {/* Permission Matrix Table - Same style as PermissionMatrixTable */}\r\n <div className=\"overflow-x-auto overflow-y-visible\">\r\n <table className=\"border-collapse\" style={{ width: 'auto' }}>\r\n <thead className=\"item-medium border-b border-[var(--item-color-border)]\">\r\n <tr>\r\n <th\r\n scope=\"col\"\r\n className=\"sticky left-0 z-20 item-medium px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('assignments.resource')}\r\n </th>\r\n <th\r\n scope=\"col\"\r\n className=\"px-2 text-center text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ width: '60px', minWidth: '60px', maxWidth: '60px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('userPermissions.status')}\r\n </th>\r\n <th\r\n scope=\"col\"\r\n className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('assignments.permissions')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--item-color-border)]\">\r\n {groupedResources.map((appGroup) => {\r\n const appKey = appGroup.application;\r\n const isAppCollapsed = collapsedApps.has(appKey);\r\n\r\n return (\r\n <React.Fragment key={appKey}>\r\n {/* Application Header Row */}\r\n <tr className=\"bg-[var(--bg-tertiary)]\">\r\n <td\r\n className=\"sticky left-0 z-10 px-3 py-2 bg-[var(--bg-tertiary)]\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <button\r\n onClick={() => toggleApp(appKey)}\r\n className=\"flex items-center gap-3 w-full text-left hover:opacity-80\"\r\n >\r\n {isAppCollapsed ? (\r\n <ChevronRight className=\"h-4 w-4 text-[var(--text-secondary)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-4 w-4 text-[var(--text-secondary)]\" />\r\n )}\r\n <FolderOpen className=\"h-4 w-4 text-[var(--text-secondary)]\" />\r\n <span className=\"text-sm font-semibold text-[var(--text-primary)]\">\r\n {appGroup.application}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)] ml-auto\">\r\n {appGroup.modules.length} module{appGroup.modules.length > 1 ? 's' : ''}\r\n </span>\r\n </button>\r\n </td>\r\n <td className=\"px-0 py-2\" />\r\n <td className=\"px-0 py-2\" />\r\n </tr>\r\n\r\n {/* Module, Section and Resource Rows */}\r\n {!isAppCollapsed && appGroup.modules.map((moduleWithSections, moduleIndex) => {\r\n const { module, sections } = moduleWithSections;\r\n const hasSections = sections.length > 0;\r\n const isModuleCollapsed = collapsedModules.has(module.id);\r\n\r\n return (\r\n <React.Fragment key={module.id}>\r\n {/* Module Row */}\r\n {renderResourceRow(module, moduleIndex, 'module', hasSections, isModuleCollapsed)}\r\n\r\n {/* Section and Resource Rows (if module has sections and is not collapsed) */}\r\n {hasSections && !isModuleCollapsed && sections.map((sectionWithResources, sectionIndex) => {\r\n const { section, resources } = sectionWithResources;\r\n\r\n return (\r\n <SectionResourceRows\r\n key={section.id}\r\n section={section}\r\n resources={resources}\r\n moduleIndex={moduleIndex}\r\n sectionIndex={sectionIndex}\r\n collapsedSections={collapsedSections}\r\n renderResourceRow={renderResourceRow}\r\n />\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n {totalModuleCount === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('assignments.noResources')}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useParams, useNavigate, Link } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n ArrowLeft,\r\n Shield,\r\n Users,\r\n Settings,\r\n Loader2,\r\n Save,\r\n Lock,\r\n AlertTriangle,\r\n CheckCircle,\r\n Languages,\r\n Plus,\r\n Trash2,\r\n Edit2,\r\n X,\r\n UsersRound,\r\n Search\r\n} from 'lucide-react';\r\nimport {\r\n adminApi,\r\n type RoleDetailDto,\r\n type RoleListDto,\r\n type UpdateRoleRequest,\r\n type RoleTranslationDto,\r\n type UpdateRoleTranslationRequest,\r\n type RoleCategory,\r\n type UserListDto\r\n} from '@/services/api/adminApi';\r\nimport { groupsApi, type GroupListDto } from '@/services/api/groupsApi';\r\nimport { RolePermissionMatrix } from '@/components/platform/administration/permissions/RolePermissionMatrix';\r\n\r\ntype TabId = 'info' | 'permissions' | 'users' | 'groups' | 'translations';\r\n\r\nconst SUPPORTED_LANGUAGES = [\r\n { code: 'fr', label: 'Français' },\r\n { code: 'en', label: 'English' },\r\n { code: 'it', label: 'Italiano' },\r\n { code: 'de', label: 'Deutsch' }\r\n];\r\n\r\nexport function RoleDetailPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const { id: roleId } = useParams<{ id: string }>();\r\n const navigate = useNavigate();\r\n\r\n const [role, setRole] = useState<RoleDetailDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [activeTab, setActiveTab] = useState<TabId>('info');\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n\r\n const [formData, setFormData] = useState({\r\n name: '',\r\n shortName: '',\r\n category: 'Custom' as RoleCategory,\r\n description: '',\r\n parentRoleId: null as string | null\r\n });\r\n const [availableRoles, setAvailableRoles] = useState<RoleListDto[]>([]);\r\n\r\n const ROLE_CATEGORIES: RoleCategory[] = ['Global', 'Admin', 'Manager', 'Contributor', 'Viewer', 'Custom'];\r\n\r\n // Translation state\r\n const [translations, setTranslations] = useState<RoleTranslationDto[]>([]);\r\n const [loadingTranslations, setLoadingTranslations] = useState(false);\r\n const [editingTranslation, setEditingTranslation] = useState<string | null>(null);\r\n const [translationForm, setTranslationForm] = useState<UpdateRoleTranslationRequest>({\r\n name: '',\r\n shortName: '',\r\n description: ''\r\n });\r\n const [savingTranslation, setSavingTranslation] = useState(false);\r\n const [showAddTranslation, setShowAddTranslation] = useState(false);\r\n const [newTranslationLang, setNewTranslationLang] = useState('');\r\n\r\n // User assignment state\r\n const [addingUser, setAddingUser] = useState(false);\r\n const [availableUsers, setAvailableUsers] = useState<UserListDto[]>([]);\r\n const [loadingUsers, setLoadingUsers] = useState(false);\r\n const [userSearchTerm, setUserSearchTerm] = useState('');\r\n const [selectedUserId, setSelectedUserId] = useState<string | null>(null);\r\n const [assigningUser, setAssigningUser] = useState(false);\r\n const [removingUserId, setRemovingUserId] = useState<string | null>(null);\r\n\r\n // Group assignment state\r\n const [addingGroup, setAddingGroup] = useState(false);\r\n const [availableGroups, setAvailableGroups] = useState<GroupListDto[]>([]);\r\n const [loadingGroups, setLoadingGroups] = useState(false);\r\n const [groupSearchTerm, setGroupSearchTerm] = useState('');\r\n const [selectedGroupId, setSelectedGroupId] = useState<string | null>(null);\r\n const [assigningGroup, setAssigningGroup] = useState(false);\r\n const [removingGroupId, setRemovingGroupId] = useState<string | null>(null);\r\n\r\n const loadRole = useCallback(async () => {\r\n if (!roleId) return;\r\n try {\r\n setLoading(true);\r\n const [roleData, rolesData] = await Promise.all([\r\n adminApi.roles.getById(roleId),\r\n adminApi.roles.getAll()\r\n ]);\r\n setRole(roleData);\r\n // Filter out current role from available parent roles\r\n setAvailableRoles(rolesData.filter(r => r.id !== roleId));\r\n setFormData({\r\n name: roleData.name,\r\n shortName: roleData.shortName,\r\n category: roleData.category,\r\n description: roleData.description || '',\r\n parentRoleId: roleData.parentRoleId\r\n });\r\n } catch (err) {\r\n console.error('Failed to load role:', err);\r\n setError(t('roleDetail.errors.loadFailed'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [roleId, t]);\r\n\r\n useEffect(() => {\r\n loadRole();\r\n }, [loadRole]);\r\n\r\n const handleSaveInfo = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!roleId || !role) return;\r\n\r\n setSaving(true);\r\n setError(null);\r\n setSuccess(null);\r\n\r\n try {\r\n const updateData: UpdateRoleRequest = {\r\n name: formData.name,\r\n shortName: formData.shortName,\r\n category: formData.category,\r\n description: formData.description || undefined,\r\n parentRoleId: formData.parentRoleId || undefined\r\n };\r\n await adminApi.roles.update(roleId, updateData);\r\n setSuccess(t('roleDetail.success.saved'));\r\n loadRole();\r\n } catch (err: unknown) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.saveFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n // Translation functions\r\n const loadTranslations = useCallback(async () => {\r\n if (!roleId) return;\r\n setLoadingTranslations(true);\r\n try {\r\n const data = await adminApi.roles.getTranslations(roleId);\r\n setTranslations(data);\r\n } catch (err) {\r\n console.error('Failed to load translations:', err);\r\n } finally {\r\n setLoadingTranslations(false);\r\n }\r\n }, [roleId]);\r\n\r\n useEffect(() => {\r\n if (activeTab === 'translations' && translations.length === 0) {\r\n loadTranslations();\r\n }\r\n }, [activeTab, translations.length, loadTranslations]);\r\n\r\n const startEditTranslation = (trans: RoleTranslationDto) => {\r\n setEditingTranslation(trans.languageCode);\r\n setTranslationForm({\r\n name: trans.name,\r\n shortName: trans.shortName,\r\n description: trans.description || ''\r\n });\r\n };\r\n\r\n const cancelEditTranslation = () => {\r\n setEditingTranslation(null);\r\n setShowAddTranslation(false);\r\n setTranslationForm({ name: '', shortName: '', description: '' });\r\n setNewTranslationLang('');\r\n };\r\n\r\n const handleSaveTranslation = async (languageCode: string) => {\r\n if (!roleId) return;\r\n setSavingTranslation(true);\r\n setError(null);\r\n try {\r\n await adminApi.roles.upsertTranslation(roleId, languageCode, translationForm);\r\n setSuccess(t('roleDetail.translations.saved'));\r\n setEditingTranslation(null);\r\n setShowAddTranslation(false);\r\n setNewTranslationLang('');\r\n loadTranslations();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.saveFailed'));\r\n } finally {\r\n setSavingTranslation(false);\r\n }\r\n };\r\n\r\n const handleDeleteTranslation = async (languageCode: string) => {\r\n if (!roleId) return;\r\n if (!confirm(t('roleDetail.translations.confirmDelete'))) return;\r\n try {\r\n await adminApi.roles.deleteTranslation(roleId, languageCode);\r\n setSuccess(t('roleDetail.translations.deleted'));\r\n loadTranslations();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.saveFailed'));\r\n }\r\n };\r\n\r\n const availableLanguages = SUPPORTED_LANGUAGES.filter(\r\n lang => !translations.some(t => t.languageCode === lang.code)\r\n );\r\n\r\n // User assignment functions\r\n const openAddUser = async () => {\r\n setAddingUser(true);\r\n setSelectedUserId(null);\r\n setUserSearchTerm('');\r\n setLoadingUsers(true);\r\n try {\r\n const data = await adminApi.users.getAll({ globalScope: true });\r\n setAvailableUsers(data.items);\r\n } catch (err) {\r\n console.error('Failed to load users:', err);\r\n } finally {\r\n setLoadingUsers(false);\r\n }\r\n };\r\n\r\n const handleAssignUser = async () => {\r\n if (!roleId || !selectedUserId) return;\r\n setAssigningUser(true);\r\n try {\r\n await adminApi.roles.assignUser(roleId, selectedUserId);\r\n setAddingUser(false);\r\n setSelectedUserId(null);\r\n setSuccess(t('roleDetail.users.assigned'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.assignFailed'));\r\n } finally {\r\n setAssigningUser(false);\r\n }\r\n };\r\n\r\n const handleRemoveUser = async (userId: string) => {\r\n if (!roleId) return;\r\n if (!confirm(t('roleDetail.users.confirmRemove'))) return;\r\n setRemovingUserId(userId);\r\n try {\r\n await adminApi.roles.removeUser(roleId, userId);\r\n setSuccess(t('roleDetail.users.removed'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.removeFailed'));\r\n } finally {\r\n setRemovingUserId(null);\r\n }\r\n };\r\n\r\n // Group assignment functions\r\n const openAddGroup = async () => {\r\n setAddingGroup(true);\r\n setSelectedGroupId(null);\r\n setGroupSearchTerm('');\r\n setLoadingGroups(true);\r\n try {\r\n const data = await groupsApi.getAll();\r\n setAvailableGroups(data);\r\n } catch (err) {\r\n console.error('Failed to load groups:', err);\r\n } finally {\r\n setLoadingGroups(false);\r\n }\r\n };\r\n\r\n const handleAssignGroup = async () => {\r\n if (!roleId || !selectedGroupId) return;\r\n setAssigningGroup(true);\r\n try {\r\n await adminApi.roles.assignGroup(roleId, selectedGroupId);\r\n setAddingGroup(false);\r\n setSelectedGroupId(null);\r\n setSuccess(t('roleDetail.groups.assigned'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.assignFailed'));\r\n } finally {\r\n setAssigningGroup(false);\r\n }\r\n };\r\n\r\n const handleRemoveGroup = async (groupId: string) => {\r\n if (!roleId) return;\r\n if (!confirm(t('roleDetail.groups.confirmRemove'))) return;\r\n setRemovingGroupId(groupId);\r\n try {\r\n await adminApi.roles.removeGroup(roleId, groupId);\r\n setSuccess(t('roleDetail.groups.removed'));\r\n loadRole();\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('roleDetail.errors.removeFailed'));\r\n } finally {\r\n setRemovingGroupId(null);\r\n }\r\n };\r\n\r\n const tabs: { id: TabId; label: string; icon: React.ReactNode }[] = [\r\n { id: 'info', label: t('roleDetail.tabs.info'), icon: <Settings className=\"w-4 h-4\" /> },\r\n { id: 'permissions', label: t('roleDetail.tabs.permissions'), icon: <Shield className=\"w-4 h-4\" /> },\r\n { id: 'users', label: t('roleDetail.tabs.users'), icon: <Users className=\"w-4 h-4\" /> },\r\n { id: 'groups', label: t('roleDetail.tabs.groups'), icon: <UsersRound className=\"w-4 h-4\" /> },\r\n { id: 'translations', label: t('roleDetail.tabs.translations'), icon: <Languages className=\"w-4 h-4\" /> }\r\n ];\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center h-64\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (!role) {\r\n return (\r\n <div className=\"text-center py-12\">\r\n <p className=\"text-[var(--text-secondary)]\">{t('roleDetail.notFound')}</p>\r\n <button\r\n onClick={() => navigate('/administration/permissions/roles')}\r\n className=\"mt-4 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white\"\r\n >\r\n {t('roleDetail.backToList')}\r\n </button>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('roles.title', 'Roles'), href: '/administration/permissions/roles' },\r\n { label: role?.name || 'Detail' }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center gap-4\">\r\n <button\r\n onClick={() => navigate('/administration/permissions/roles')}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <ArrowLeft className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-3\">\r\n <h1 className=\"text-xl sm:text-2xl font-bold text-[var(--text-primary)]\">{role.name}</h1>\r\n {role.isSystem && (\r\n <span className=\"flex items-center gap-1 px-2 py-1 rounded-[var(--radius-badge)] text-xs bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n <Lock className=\"w-3 h-3\" />\r\n {t('roles.system')}\r\n </span>\r\n )}\r\n </div>\r\n {role.description && (\r\n <p className=\"text-sm sm:text-base text-[var(--text-secondary)] mt-1\">{role.description}</p>\r\n )}\r\n </div>\r\n <div className=\"flex items-center gap-4 text-sm text-[var(--text-secondary)]\">\r\n <div className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n <span>{role.users.length} {t('roleDetail.usersCount')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n <UsersRound className=\"w-4 h-4\" />\r\n <span>{role.groups?.length || 0} {t('roleDetail.groupsCount')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-1\">\r\n <Shield className=\"w-4 h-4\" />\r\n <span>{role.permissions.length} {t('roles.permissions')}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Alerts */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] text-[var(--error-text)] flex items-center gap-2\">\r\n <AlertTriangle className=\"w-5 h-5 flex-shrink-0\" />\r\n {error}\r\n </div>\r\n )}\r\n {success && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)] text-[var(--success-text)] flex items-center gap-2\">\r\n <CheckCircle className=\"w-5 h-5 flex-shrink-0\" />\r\n {success}\r\n </div>\r\n )}\r\n\r\n\r\n {/* Tabs */}\r\n <div className=\"flex gap-1 p-1 bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)]\">\r\n {tabs.map(tab => (\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-2 rounded-[var(--radius-button)] font-medium transition-colors ${\r\n activeTab === tab.id\r\n ? 'bg-[var(--color-accent-600)] text-white'\r\n : 'text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n {tab.icon}\r\n <span className=\"hidden sm:inline\">{tab.label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Tab Content */}\r\n <div className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4 sm:p-6\">\r\n {/* Info Tab */}\r\n {activeTab === 'info' && (\r\n <form onSubmit={handleSaveInfo} className=\"space-y-6 max-w-2xl\">\r\n {/* ID (read-only) */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.id')}\r\n </label>\r\n <div className=\"px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-tertiary)] text-[var(--text-secondary)] font-mono text-sm\">\r\n {role.id}\r\n </div>\r\n </div>\r\n\r\n {/* Name */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roles.form.name')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.name}\r\n onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Short Name */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.shortName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.shortName}\r\n onChange={e => setFormData(prev => ({ ...prev, shortName: e.target.value }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n <p className=\"mt-1 text-xs text-[var(--text-tertiary)]\">\r\n {t('roleDetail.info.shortNameHelp')}\r\n </p>\r\n </div>\r\n\r\n {/* Category */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.category')} *\r\n </label>\r\n <select\r\n value={formData.category}\r\n onChange={e => setFormData(prev => ({ ...prev, category: e.target.value as RoleCategory }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n {ROLE_CATEGORIES.map(cat => (\r\n <option key={cat} value={cat}>\r\n {t(`roleDetail.categories.${cat.toLowerCase()}`)}\r\n </option>\r\n ))}\r\n </select>\r\n <p className=\"mt-1 text-xs text-[var(--text-tertiary)]\">\r\n {t('roleDetail.info.categoryHelp')}\r\n </p>\r\n </div>\r\n\r\n {/* Parent Role */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.parentRole')}\r\n </label>\r\n <select\r\n value={formData.parentRoleId || ''}\r\n onChange={e => setFormData(prev => ({ ...prev, parentRoleId: e.target.value || null }))}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"\">{t('roleDetail.info.noParent')}</option>\r\n {availableRoles.map(r => (\r\n <option key={r.id} value={r.id}>\r\n {r.name} ({t(`roleDetail.categories.${r.category.toLowerCase()}`)})\r\n </option>\r\n ))}\r\n </select>\r\n <p className=\"mt-1 text-xs text-[var(--text-tertiary)]\">\r\n {t('roleDetail.info.parentRoleHelp')}\r\n </p>\r\n </div>\r\n\r\n {/* Description */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roles.form.description')}\r\n </label>\r\n <textarea\r\n value={formData.description}\r\n onChange={e => setFormData(prev => ({ ...prev, description: e.target.value }))}\r\n rows={3}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] resize-none\"\r\n />\r\n </div>\r\n\r\n {/* System Role Badge */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.info.systemRole')}\r\n </label>\r\n <div className=\"flex items-center gap-2\">\r\n {role.isSystem ? (\r\n <span className=\"flex items-center gap-1.5 px-3 py-1.5 rounded-[var(--radius-badge)] text-sm bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n <Lock className=\"w-4 h-4\" />\r\n {t('roleDetail.info.isSystemRole')}\r\n </span>\r\n ) : (\r\n <span className=\"flex items-center gap-1.5 px-3 py-1.5 rounded-[var(--radius-badge)] text-sm bg-[var(--bg-tertiary)] text-[var(--text-secondary)]\">\r\n {t('roleDetail.info.isCustomRole')}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Metadata */}\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4 pt-4 border-t border-[var(--border-color)]\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.createdAt')}\r\n </label>\r\n <div className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(role.createdAt).toLocaleString()}\r\n </div>\r\n </div>\r\n {role.updatedAt && (\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.updatedAt')}\r\n </label>\r\n <div className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(role.updatedAt).toLocaleString()}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex justify-end pt-4\">\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white font-medium transition-colors disabled:opacity-50\"\r\n >\r\n {saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </form>\r\n )}\r\n\r\n {/* Permissions Tab - Matrix View */}\r\n {activeTab === 'permissions' && roleId && (\r\n <RolePermissionMatrix roleId={roleId} />\r\n )}\r\n\r\n {/* Groups Tab */}\r\n {activeTab === 'groups' && (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('roleDetail.groups.title')} ({role.groups?.length || 0})\r\n </h3>\r\n <button\r\n onClick={openAddGroup}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('roleDetail.groups.add')}\r\n </button>\r\n </div>\r\n\r\n {(!role.groups || role.groups.length === 0) ? (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.groups.noGroups')}\r\n </div>\r\n ) : (\r\n <div className=\"grid gap-3\">\r\n {role.groups.map(group => (\r\n <div\r\n key={group.id}\r\n className=\"flex items-center gap-4 p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Link\r\n to={`/administration/users/groups/${group.id}`}\r\n className=\"flex items-center gap-4 flex-1 min-w-0 hover:opacity-80 transition-opacity\"\r\n >\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-100)] flex items-center justify-center\">\r\n <UsersRound className=\"w-5 h-5 text-[var(--color-accent-700)]\" />\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"font-medium text-[var(--text-primary)] truncate\">{group.name}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)] truncate\">\r\n {group.membersCount} {t('roleDetail.groups.members')}\r\n {group.description && ` · ${group.description}`}\r\n </div>\r\n </div>\r\n </Link>\r\n <button\r\n onClick={() => handleRemoveGroup(group.id)}\r\n disabled={removingGroupId === group.id}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--error-text)] transition-colors disabled:opacity-50\"\r\n title={t('roleDetail.groups.remove')}\r\n >\r\n {removingGroupId === group.id ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Add Group Modal */}\r\n {addingGroup && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\r\n <div className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] w-full max-w-md p-6 m-4 max-h-[90vh] overflow-y-auto\">\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">\r\n {t('roleDetail.groups.addTitle')}\r\n </h2>\r\n <button\r\n onClick={() => setAddingGroup(false)}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-tertiary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"mb-4\">\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-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n value={groupSearchTerm}\r\n onChange={(e) => setGroupSearchTerm(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n placeholder={t('roleDetail.groups.searchPlaceholder')}\r\n />\r\n </div>\r\n </div>\r\n\r\n {loadingGroups ? (\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 </div>\r\n ) : (\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {availableGroups\r\n .filter(g =>\r\n !role.groups?.some(rg => rg.id === g.id) &&\r\n (groupSearchTerm === '' ||\r\n g.name.toLowerCase().includes(groupSearchTerm.toLowerCase()) ||\r\n (g.description || '').toLowerCase().includes(groupSearchTerm.toLowerCase()))\r\n )\r\n .map(group => (\r\n <label\r\n key={group.id}\r\n className={`flex items-center gap-3 cursor-pointer p-3 rounded-[var(--radius-button)] transition-colors ${\r\n selectedGroupId === group.id\r\n ? 'bg-[var(--color-accent-500)]/10 border border-[var(--color-accent-500)]'\r\n : 'hover:bg-[var(--bg-hover)] border border-transparent'\r\n }`}\r\n htmlFor={`group-${group.id}`}\r\n >\r\n <input\r\n id={`group-${group.id}`}\r\n type=\"radio\"\r\n name=\"selectedGroup\"\r\n checked={selectedGroupId === group.id}\r\n onChange={() => setSelectedGroupId(group.id)}\r\n className=\"w-4 h-4 text-[var(--color-accent-600)] focus:ring-[var(--color-accent-500)]\"\r\n />\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"text-[var(--text-primary)] font-medium\">{group.name}</span>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {group.memberCount} {t('roleDetail.groups.members')}\r\n {group.description && ` · ${group.description}`}\r\n </p>\r\n </div>\r\n </label>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex justify-end gap-3 mt-6\">\r\n <button\r\n onClick={() => setAddingGroup(false)}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] font-medium transition-colors\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={handleAssignGroup}\r\n disabled={!selectedGroupId || assigningGroup}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white font-medium transition-colors disabled:opacity-50\"\r\n >\r\n {assigningGroup && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.add')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Users Tab */}\r\n {activeTab === 'users' && (\r\n <div className=\"space-y-4\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('roleDetail.users.title')} ({role.users.length})\r\n </h3>\r\n <button\r\n onClick={openAddUser}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('roleDetail.users.add')}\r\n </button>\r\n </div>\r\n\r\n {role.users.length === 0 ? (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.users.noUsers')}\r\n </div>\r\n ) : (\r\n <div className=\"grid gap-3\">\r\n {role.users.map(user => (\r\n <div\r\n key={user.id}\r\n className=\"flex items-center gap-4 p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Link\r\n to={`/administration/users/${user.id}`}\r\n className=\"flex items-center gap-4 flex-1 min-w-0 hover:opacity-80 transition-opacity\"\r\n >\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-100)] flex items-center justify-center\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-700)]\">\r\n {user.fullName.split(' ').map(n => n.at(0)).join('').toUpperCase().slice(0, 2)}\r\n </span>\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"font-medium text-[var(--text-primary)] truncate\">{user.fullName}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)] truncate\">{user.email}</div>\r\n </div>\r\n </Link>\r\n <button\r\n onClick={() => handleRemoveUser(user.id)}\r\n disabled={removingUserId === user.id}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--error-text)] transition-colors disabled:opacity-50\"\r\n title={t('roleDetail.users.remove')}\r\n >\r\n {removingUserId === user.id ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Add User Modal */}\r\n {addingUser && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\r\n <div className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] w-full max-w-md p-6 m-4 max-h-[90vh] overflow-y-auto\">\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">\r\n {t('roleDetail.users.addTitle')}\r\n </h2>\r\n <button\r\n onClick={() => setAddingUser(false)}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-tertiary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"mb-4\">\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-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n value={userSearchTerm}\r\n onChange={(e) => setUserSearchTerm(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n placeholder={t('roleDetail.users.searchPlaceholder')}\r\n />\r\n </div>\r\n </div>\r\n\r\n {loadingUsers ? (\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 </div>\r\n ) : (\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {availableUsers\r\n .filter(u =>\r\n !role.users.some(ru => ru.id === u.id) &&\r\n (userSearchTerm === '' ||\r\n u.fullName.toLowerCase().includes(userSearchTerm.toLowerCase()) ||\r\n u.email.toLowerCase().includes(userSearchTerm.toLowerCase()))\r\n )\r\n .map(user => (\r\n <label\r\n key={user.id}\r\n className={`flex items-center gap-3 cursor-pointer p-3 rounded-[var(--radius-button)] transition-colors ${\r\n selectedUserId === user.id\r\n ? 'bg-[var(--color-accent-500)]/10 border border-[var(--color-accent-500)]'\r\n : 'hover:bg-[var(--bg-hover)] border border-transparent'\r\n }`}\r\n htmlFor={`user-${user.id}`}\r\n >\r\n <input\r\n id={`user-${user.id}`}\r\n type=\"radio\"\r\n name=\"selectedUser\"\r\n checked={selectedUserId === user.id}\r\n onChange={() => setSelectedUserId(user.id)}\r\n className=\"w-4 h-4 text-[var(--color-accent-600)] focus:ring-[var(--color-accent-500)]\"\r\n />\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"text-[var(--text-primary)] font-medium\">{user.fullName}</span>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{user.email}</p>\r\n </div>\r\n </label>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"flex justify-end gap-3 mt-6\">\r\n <button\r\n onClick={() => setAddingUser(false)}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] font-medium transition-colors\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={handleAssignUser}\r\n disabled={!selectedUserId || assigningUser}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white font-medium transition-colors disabled:opacity-50\"\r\n >\r\n {assigningUser && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.add')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Translations Tab */}\r\n {activeTab === 'translations' && (\r\n <div className=\"space-y-6\">\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('roleDetail.translations.title')} ({translations.length})\r\n </h3>\r\n {availableLanguages.length > 0 && (\r\n <button\r\n onClick={() => setShowAddTranslation(true)}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('roleDetail.translations.add')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Add new translation form */}\r\n {showAddTranslation && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--color-accent-500)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h4 className=\"font-medium text-[var(--text-primary)]\">\r\n {t('roleDetail.translations.addNew')}\r\n </h4>\r\n <button\r\n onClick={cancelEditTranslation}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)]\"\r\n >\r\n <X className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n </button>\r\n </div>\r\n <div className=\"grid gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.language')}\r\n </label>\r\n <select\r\n value={newTranslationLang}\r\n onChange={e => setNewTranslationLang(e.target.value)}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n >\r\n <option value=\"\">{t('roleDetail.translations.selectLanguage')}</option>\r\n {availableLanguages.map(lang => (\r\n <option key={lang.code} value={lang.code}>{lang.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n {newTranslationLang && (\r\n <>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.name')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.name}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, name: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.shortName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.shortName}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, shortName: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.description')}\r\n </label>\r\n <textarea\r\n value={translationForm.description || ''}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, description: e.target.value }))}\r\n rows={2}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n onClick={cancelEditTranslation}\r\n className=\"px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] text-sm font-medium\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={() => handleSaveTranslation(newTranslationLang)}\r\n disabled={savingTranslation || !translationForm.name || !translationForm.shortName}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium disabled:opacity-50\"\r\n >\r\n {savingTranslation && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {loadingTranslations && (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <Loader2 className=\"w-6 h-6 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loadingTranslations && translations.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {t('roleDetail.translations.noTranslations')}\r\n </div>\r\n )}\r\n {!loadingTranslations && translations.length > 0 && (\r\n <div className=\"space-y-3\">\r\n {translations.map(trans => {\r\n const langInfo = SUPPORTED_LANGUAGES.find(l => l.code === trans.languageCode);\r\n const isEditing = editingTranslation === trans.languageCode;\r\n\r\n return (\r\n <div\r\n key={trans.languageCode}\r\n className={`p-4 rounded-[var(--radius-card)] border ${\r\n isEditing\r\n ? 'bg-[var(--bg-primary)] border-[var(--color-accent-500)]'\r\n : 'bg-[var(--bg-primary)] border-[var(--border-color)]'\r\n }`}\r\n >\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"px-2 py-0.5 text-xs font-medium rounded bg-[var(--bg-tertiary)] text-[var(--text-secondary)] uppercase\">\r\n {trans.languageCode}\r\n </span>\r\n <span className=\"text-sm text-[var(--text-secondary)]\">\r\n {langInfo?.label || trans.languageCode}\r\n </span>\r\n </div>\r\n {!isEditing && (\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => startEditTranslation(trans)}\r\n className=\"p-1.5 rounded hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--color-accent-600)]\"\r\n title={t('common.edit')}\r\n >\r\n <Edit2 className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => handleDeleteTranslation(trans.languageCode)}\r\n className=\"p-1.5 rounded hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-[var(--error-text)]\"\r\n title={t('common.delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {isEditing ? (\r\n <div className=\"grid gap-3 mt-3\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.name')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.name}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, name: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.shortName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={translationForm.shortName}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, shortName: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('roleDetail.translations.description')}\r\n </label>\r\n <textarea\r\n value={translationForm.description || ''}\r\n onChange={e => setTranslationForm(prev => ({ ...prev, description: e.target.value }))}\r\n rows={2}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n onClick={cancelEditTranslation}\r\n className=\"px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)] hover:bg-[var(--bg-hover)] text-[var(--text-primary)] text-sm font-medium\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n onClick={() => handleSaveTranslation(trans.languageCode)}\r\n disabled={savingTranslation || !translationForm.name || !translationForm.shortName}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] hover:bg-[var(--color-accent-700)] text-white text-sm font-medium disabled:opacity-50\"\r\n >\r\n {savingTranslation && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {t('common.save')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"grid gap-1\">\r\n <div className=\"font-medium text-[var(--text-primary)]\">{trans.name}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('roleDetail.translations.shortName')}: {trans.shortName}\r\n </div>\r\n {trans.description && (\r\n <div className=\"text-sm text-[var(--text-tertiary)] mt-1\">{trans.description}</div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["ACTION_ICONS","jsx","Shield","Eye","Plus","Edit","Trash2","UserPlus","Play","ACTION_COLORS","applyApplicationModuleFilterHelper","grouped","applicationFilter","moduleFilter","app","m","applyStatusFilterHelper","statusFilters","getModuleStatus","status","SectionResourceRows","section","resources","moduleIndex","sectionIndex","collapsedSections","renderResourceRow","hasResources","isSectionCollapsed","jsxs","React","resource","resourceIndex","RolePermissionMatrix","roleId","t","useTranslation","user","useAuth","collapsedApps","toggleApp","useCollapsibleState","collapsedModules","setCollapsedModules","useState","setCollapsedSections","setStatusFilters","openPopover","setOpenPopover","setApplicationFilter","setModuleFilter","canEditSystemRoles","useMemo","hasFullAccess","loading","error","roles","filteredResources","hasChanges","saving","saveSuccess","saveError","togglePermission","saveChanges","resetChanges","getPermissionInheritance","usePermissionMatrix","role","r","isRoleEditable","toggleStatusFilter","prev","next","toggleModule","moduleId","toggleSection","sectionId","filterOptions","applications","modules","appKey","a","b","handleTogglePermission","useCallback","permissionId","isPermissionGrantedFn","info","moduleWithSections","calculateModuleWithSectionsStatus","getResourceStatus","calculatePermissionStatus","getGrantedPermissions","p","applyApplicationModuleFilter","applyStatusFilter","groupedResources","groupByApplicationWithSections","totalModuleCount","sum","handleToggleCollapse","resourceId","level","handleCellClick","Loader2","AlertCircle","getRoleResourceIcon","Database","FileText","Box","getRoleResourceLabelClass","getRolePaddingClass","renderToggleButton","hasChildren","isCollapsed","ChevronRight","ChevronDown","renderPermissionBadges","grantedPermissions","action","actionColor","icon","rowIndex","grantedCount","isPopoverOpen","buttonRef","createRef","cellBg","getPermissionCellBackground","paddingLeft","rowBgClass","PermissionStatusIndicator","PermissionPopover","_","permId","Check","X","Save","e","mod","Star","Ban","appGroup","isAppCollapsed","FolderOpen","module","sections","hasSections","isModuleCollapsed","sectionWithResources","SUPPORTED_LANGUAGES","RoleDetailPage","useParams","navigate","useNavigate","setRole","setLoading","setSaving","activeTab","setActiveTab","setError","success","setSuccess","formData","setFormData","availableRoles","setAvailableRoles","ROLE_CATEGORIES","translations","setTranslations","loadingTranslations","setLoadingTranslations","editingTranslation","setEditingTranslation","translationForm","setTranslationForm","savingTranslation","setSavingTranslation","showAddTranslation","setShowAddTranslation","newTranslationLang","setNewTranslationLang","addingUser","setAddingUser","availableUsers","setAvailableUsers","loadingUsers","setLoadingUsers","userSearchTerm","setUserSearchTerm","selectedUserId","setSelectedUserId","assigningUser","setAssigningUser","removingUserId","setRemovingUserId","addingGroup","setAddingGroup","availableGroups","setAvailableGroups","loadingGroups","setLoadingGroups","groupSearchTerm","setGroupSearchTerm","selectedGroupId","setSelectedGroupId","assigningGroup","setAssigningGroup","removingGroupId","setRemovingGroupId","loadRole","roleData","rolesData","adminApi","err","useEffect","handleSaveInfo","updateData","loadTranslations","data","startEditTranslation","trans","cancelEditTranslation","handleSaveTranslation","languageCode","handleDeleteTranslation","availableLanguages","lang","openAddUser","handleAssignUser","handleRemoveUser","userId","openAddGroup","groupsApi","handleAssignGroup","handleRemoveGroup","groupId","tabs","Settings","Users","UsersRound","Languages","Breadcrumb","ArrowLeft","Lock","AlertTriangle","CheckCircle","tab","cat","group","Link","Search","g","rg","n","u","ru","Fragment","langInfo","l","isEditing","Edit2"],"mappings":"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"}
|