@atlashub/smartstack 3.21.0 → 3.24.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.
Files changed (280) hide show
  1. package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js → AgentSkillsPage-BWQSCYl-.js} +2 -2
  2. package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js.map → AgentSkillsPage-BWQSCYl-.js.map} +1 -1
  3. package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js → AgentSkillsPage-IQcMnBaD.js} +2 -2
  4. package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js.map → AgentSkillsPage-IQcMnBaD.js.map} +1 -1
  5. package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js → AgentWorkloadPage-DqrjkvWL.js} +2 -2
  6. package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js.map → AgentWorkloadPage-DqrjkvWL.js.map} +1 -1
  7. package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js → AgentWorkloadPage-w-HiyFYP.js} +2 -2
  8. package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js.map → AgentWorkloadPage-w-HiyFYP.js.map} +1 -1
  9. package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js → ApiCatalogDetailPage-D3L8Yf4G.js} +3 -3
  10. package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js.map → ApiCatalogDetailPage-D3L8Yf4G.js.map} +1 -1
  11. package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js → ApiCatalogDetailPage-MPT3Kz6H.js} +2 -2
  12. package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js.map → ApiCatalogDetailPage-MPT3Kz6H.js.map} +1 -1
  13. package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js → ApiCatalogPage-D4Hg3uiS.js} +2 -2
  14. package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js.map → ApiCatalogPage-D4Hg3uiS.js.map} +1 -1
  15. package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js → ApiCatalogPage-DRg5Cz0r.js} +2 -2
  16. package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js.map → ApiCatalogPage-DRg5Cz0r.js.map} +1 -1
  17. package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js → ApplicationDetailPage-Caizuyn2.js} +2 -2
  18. package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js.map → ApplicationDetailPage-Caizuyn2.js.map} +1 -1
  19. package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js → ApplicationDetailPage-CuCW6aMB.js} +4 -4
  20. package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js.map → ApplicationDetailPage-CuCW6aMB.js.map} +1 -1
  21. package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js → ApplicationsDashboardPage-B2MW8-Kc.js} +2 -2
  22. package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js.map → ApplicationsDashboardPage-B2MW8-Kc.js.map} +1 -1
  23. package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js → ApplicationsDashboardPage-BDIjFIYZ.js} +3 -3
  24. package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js.map → ApplicationsDashboardPage-BDIjFIYZ.js.map} +1 -1
  25. package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js → ApplicationsGridPage-DV-FihKj.js} +2 -2
  26. package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js.map → ApplicationsGridPage-DV-FihKj.js.map} +1 -1
  27. package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js → ApplicationsGridPage-DXsTfXPI.js} +2 -2
  28. package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js.map → ApplicationsGridPage-DXsTfXPI.js.map} +1 -1
  29. package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js → ApplicationsListPage--CGkyBuJ.js} +2 -2
  30. package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js.map → ApplicationsListPage--CGkyBuJ.js.map} +1 -1
  31. package/dist/chunks/{ApplicationsListPage-C91v2rZt.js → ApplicationsListPage-JUX823bh.js} +2 -2
  32. package/dist/chunks/{ApplicationsListPage-C91v2rZt.js.map → ApplicationsListPage-JUX823bh.js.map} +1 -1
  33. package/dist/chunks/{ApplicationsPage-BCbgotIx.js → ApplicationsPage-6zgFye6w.js} +2 -2
  34. package/dist/chunks/{ApplicationsPage-BCbgotIx.js.map → ApplicationsPage-6zgFye6w.js.map} +1 -1
  35. package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js → ApplicationsPage-CQPuuiO6.js} +4 -4
  36. package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js.map → ApplicationsPage-CQPuuiO6.js.map} +1 -1
  37. package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js → AssignmentRulesPage-CFffeEbo.js} +2 -2
  38. package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js.map → AssignmentRulesPage-CFffeEbo.js.map} +1 -1
  39. package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js → AssignmentRulesPage-D78UeUId.js} +2 -2
  40. package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js.map → AssignmentRulesPage-D78UeUId.js.map} +1 -1
  41. package/dist/chunks/{AssignmentsPage-DmfBYQAD.js → AssignmentsPage-Cww2ifZF.js} +2 -2
  42. package/dist/chunks/{AssignmentsPage-DmfBYQAD.js.map → AssignmentsPage-Cww2ifZF.js.map} +1 -1
  43. package/dist/chunks/{AssignmentsPage-sRCCBmRc.js → AssignmentsPage-DE_QS2LO.js} +2 -2
  44. package/dist/chunks/{AssignmentsPage-sRCCBmRc.js.map → AssignmentsPage-DE_QS2LO.js.map} +1 -1
  45. package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js → AuthCallbackPage-CA2nO6DG.js} +2 -2
  46. package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js.map → AuthCallbackPage-CA2nO6DG.js.map} +1 -1
  47. package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js → AuthCallbackPage-CDUAoX-N.js} +2 -2
  48. package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js.map → AuthCallbackPage-CDUAoX-N.js.map} +1 -1
  49. package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js → ConfirmEmailPage-BqsILAYH.js} +2 -2
  50. package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js.map → ConfirmEmailPage-BqsILAYH.js.map} +1 -1
  51. package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js → ConfirmEmailPage-INeHCuMB.js} +2 -2
  52. package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js.map → ConfirmEmailPage-INeHCuMB.js.map} +1 -1
  53. package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js → CreateSupportTicketPage-BWeuV2aU.js} +2 -2
  54. package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js.map → CreateSupportTicketPage-BWeuV2aU.js.map} +1 -1
  55. package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js → CreateSupportTicketPage-OBwF4v7b.js} +2 -2
  56. package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js.map → CreateSupportTicketPage-OBwF4v7b.js.map} +1 -1
  57. package/dist/chunks/{DashboardPage-CUZ80NGV.js → DashboardPage-CKHqWrdS.js} +3 -3
  58. package/dist/chunks/{DashboardPage-CUZ80NGV.js.map → DashboardPage-CKHqWrdS.js.map} +1 -1
  59. package/dist/chunks/{DashboardPage-CaNOAstg.js → DashboardPage-COmc9b__.js} +3 -3
  60. package/dist/chunks/{DashboardPage-CaNOAstg.js.map → DashboardPage-COmc9b__.js.map} +1 -1
  61. package/dist/chunks/{DashboardPage-B48_rQFi.js → DashboardPage-CfKZHiSj.js} +2 -2
  62. package/dist/chunks/{DashboardPage-B48_rQFi.js.map → DashboardPage-CfKZHiSj.js.map} +1 -1
  63. package/dist/chunks/{DashboardPage-CUZV1J9t.js → DashboardPage-CwEZZ3jx.js} +2 -2
  64. package/dist/chunks/{DashboardPage-CUZV1J9t.js.map → DashboardPage-CwEZZ3jx.js.map} +1 -1
  65. package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js → EscalationConfigPage--7lgZ0kJ.js} +2 -2
  66. package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js.map → EscalationConfigPage--7lgZ0kJ.js.map} +1 -1
  67. package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js → EscalationConfigPage-DPyiBcqV.js} +2 -2
  68. package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js.map → EscalationConfigPage-DPyiBcqV.js.map} +1 -1
  69. package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js → ForceChangePasswordPage-BE-6umub.js} +2 -2
  70. package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js.map → ForceChangePasswordPage-BE-6umub.js.map} +1 -1
  71. package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js → ForceChangePasswordPage-CnsYoWmV.js} +2 -2
  72. package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js.map → ForceChangePasswordPage-CnsYoWmV.js.map} +1 -1
  73. package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js → ForgotPasswordPage-CSq4DnFF.js} +2 -2
  74. package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js.map → ForgotPasswordPage-CSq4DnFF.js.map} +1 -1
  75. package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js → ForgotPasswordPage-DZLVolAC.js} +2 -2
  76. package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js.map → ForgotPasswordPage-DZLVolAC.js.map} +1 -1
  77. package/dist/chunks/{GroupDetailPage-DFBvVO1S.js → GroupDetailPage-Bf9Wb_2j.js} +5 -5
  78. package/dist/chunks/{GroupDetailPage-DFBvVO1S.js.map → GroupDetailPage-Bf9Wb_2j.js.map} +1 -1
  79. package/dist/chunks/{GroupDetailPage-B2FkKrGG.js → GroupDetailPage-R-hf3rJ7.js} +2 -2
  80. package/dist/chunks/{GroupDetailPage-B2FkKrGG.js.map → GroupDetailPage-R-hf3rJ7.js.map} +1 -1
  81. package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js → MyAccessRequestsPage-BIisvWM6.js} +2 -2
  82. package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js.map → MyAccessRequestsPage-BIisvWM6.js.map} +1 -1
  83. package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js → MyAccessRequestsPage-BLSV7Tbx.js} +2 -2
  84. package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js.map → MyAccessRequestsPage-BLSV7Tbx.js.map} +1 -1
  85. package/dist/chunks/{MyTenantsPage-BEcYYdGR.js → MyTenantsPage-D-7k9CP1.js} +3 -3
  86. package/dist/chunks/{MyTenantsPage-BEcYYdGR.js.map → MyTenantsPage-D-7k9CP1.js.map} +1 -1
  87. package/dist/chunks/{MyTenantsPage-D9f85zjF.js → MyTenantsPage-DqGW6aDt.js} +2 -2
  88. package/dist/chunks/{MyTenantsPage-D9f85zjF.js.map → MyTenantsPage-DqGW6aDt.js.map} +1 -1
  89. package/dist/chunks/{MyTicketsPage-DJR8h6y1.js → MyTicketsPage--DgDsnZA.js} +2 -2
  90. package/dist/chunks/{MyTicketsPage-DJR8h6y1.js.map → MyTicketsPage--DgDsnZA.js.map} +1 -1
  91. package/dist/chunks/{MyTicketsPage-DiOUExKJ.js → MyTicketsPage-CqJ3Aqob.js} +2 -2
  92. package/dist/chunks/{MyTicketsPage-DiOUExKJ.js.map → MyTicketsPage-CqJ3Aqob.js.map} +1 -1
  93. package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js → NavigationAppsPage-Bebis_RT.js} +2 -2
  94. package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js.map → NavigationAppsPage-Bebis_RT.js.map} +1 -1
  95. package/dist/chunks/{NavigationAppsPage-If7tmCFY.js → NavigationAppsPage-THNPOAjv.js} +2 -2
  96. package/dist/chunks/{NavigationAppsPage-If7tmCFY.js.map → NavigationAppsPage-THNPOAjv.js.map} +1 -1
  97. package/dist/chunks/{NotificationsPage-C29Lln5o.js → NotificationsPage-CAbNW_Cn.js} +2 -2
  98. package/dist/chunks/{NotificationsPage-C29Lln5o.js.map → NotificationsPage-CAbNW_Cn.js.map} +1 -1
  99. package/dist/chunks/{NotificationsPage-BiaLRb0s.js → NotificationsPage-DxwizUhL.js} +2 -2
  100. package/dist/chunks/{NotificationsPage-BiaLRb0s.js.map → NotificationsPage-DxwizUhL.js.map} +1 -1
  101. package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js → OnboardingWizardPage-C6HlbJ3K.js} +2 -2
  102. package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js.map → OnboardingWizardPage-C6HlbJ3K.js.map} +1 -1
  103. package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js → OnboardingWizardPage-CyC2zONO.js} +2 -2
  104. package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js.map → OnboardingWizardPage-CyC2zONO.js.map} +1 -1
  105. package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js → PermissionDetailPage-BDHiNgky.js} +2 -2
  106. package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js.map → PermissionDetailPage-BDHiNgky.js.map} +1 -1
  107. package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js → PermissionDetailPage-C5K17ydY.js} +2 -2
  108. package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js.map → PermissionDetailPage-C5K17ydY.js.map} +1 -1
  109. package/dist/chunks/{PermissionsPage-l0PnY-EE.js → PermissionsPage-COI5LJPo.js} +2 -2
  110. package/dist/chunks/{PermissionsPage-l0PnY-EE.js.map → PermissionsPage-COI5LJPo.js.map} +1 -1
  111. package/dist/chunks/{PermissionsPage-DLy9U3P3.js → PermissionsPage-CkOwH2_d.js} +2 -2
  112. package/dist/chunks/{PermissionsPage-DLy9U3P3.js.map → PermissionsPage-CkOwH2_d.js.map} +1 -1
  113. package/dist/chunks/{PortalDashboardPage-DFBx38-x.js → PortalDashboardPage-CoEC4CmC.js} +2 -2
  114. package/dist/chunks/{PortalDashboardPage-DFBx38-x.js.map → PortalDashboardPage-CoEC4CmC.js.map} +1 -1
  115. package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js → PortalDashboardPage-DrYymEf-.js} +2 -2
  116. package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js.map → PortalDashboardPage-DrYymEf-.js.map} +1 -1
  117. package/dist/chunks/{PreferencesPage-BBu8yZQB.js → PreferencesPage-CJRaU3ba.js} +2 -2
  118. package/dist/chunks/{PreferencesPage-BBu8yZQB.js.map → PreferencesPage-CJRaU3ba.js.map} +1 -1
  119. package/dist/chunks/{PreferencesPage-B81MsNV1.js → PreferencesPage-Cqr9mAab.js} +2 -2
  120. package/dist/chunks/{PreferencesPage-B81MsNV1.js.map → PreferencesPage-Cqr9mAab.js.map} +1 -1
  121. package/dist/chunks/{ProfilePage-DDrl10zj.js → ProfilePage-BZVpg6-l.js} +2 -2
  122. package/dist/chunks/{ProfilePage-DDrl10zj.js.map → ProfilePage-BZVpg6-l.js.map} +1 -1
  123. package/dist/chunks/{ProfilePage-DPoXwdnc.js → ProfilePage-Cu_FITeL.js} +2 -2
  124. package/dist/chunks/{ProfilePage-DPoXwdnc.js.map → ProfilePage-Cu_FITeL.js.map} +1 -1
  125. package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js → ReferencesManagementPage-DUlVk9Ps.js} +3 -3
  126. package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js.map → ReferencesManagementPage-DUlVk9Ps.js.map} +1 -1
  127. package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js → ReferencesManagementPage-ZCuYtqd7.js} +2 -2
  128. package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js.map → ReferencesManagementPage-ZCuYtqd7.js.map} +1 -1
  129. package/dist/chunks/{RegisterPage-CiQib3-6.js → RegisterPage-C4xmVwh9.js} +2 -2
  130. package/dist/chunks/{RegisterPage-CiQib3-6.js.map → RegisterPage-C4xmVwh9.js.map} +1 -1
  131. package/dist/chunks/{RegisterPage-bXCcJD88.js → RegisterPage-DGyzoIHT.js} +2 -2
  132. package/dist/chunks/{RegisterPage-bXCcJD88.js.map → RegisterPage-DGyzoIHT.js.map} +1 -1
  133. package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js → ResetPasswordPage-DqDD6VPR.js} +2 -2
  134. package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js.map → ResetPasswordPage-DqDD6VPR.js.map} +1 -1
  135. package/dist/chunks/{ResetPasswordPage-CubPG3yv.js → ResetPasswordPage-Glu-aeqv.js} +2 -2
  136. package/dist/chunks/{ResetPasswordPage-CubPG3yv.js.map → ResetPasswordPage-Glu-aeqv.js.map} +1 -1
  137. package/dist/chunks/{ResolutionModal-Bg7XZmR1.js → ResolutionModal-CxjANAOP.js} +2 -2
  138. package/dist/chunks/{ResolutionModal-Bg7XZmR1.js.map → ResolutionModal-CxjANAOP.js.map} +1 -1
  139. package/dist/chunks/{ResolutionModal-DqRk_T0n.js → ResolutionModal-Duat18qV.js} +2 -2
  140. package/dist/chunks/{ResolutionModal-DqRk_T0n.js.map → ResolutionModal-Duat18qV.js.map} +1 -1
  141. package/dist/chunks/{RoleDetailPage-Blau6_4c.js → RoleDetailPage-BQffUSnt.js} +3 -3
  142. package/dist/chunks/{RoleDetailPage-Blau6_4c.js.map → RoleDetailPage-BQffUSnt.js.map} +1 -1
  143. package/dist/chunks/{RoleDetailPage-CiRVxxIP.js → RoleDetailPage-JTm5lD1_.js} +2 -2
  144. package/dist/chunks/{RoleDetailPage-CiRVxxIP.js.map → RoleDetailPage-JTm5lD1_.js.map} +1 -1
  145. package/dist/chunks/{RolesPage-Pm-RN3lP.js → RolesPage-B9rRzciI.js} +2 -2
  146. package/dist/chunks/{RolesPage-Pm-RN3lP.js.map → RolesPage-B9rRzciI.js.map} +1 -1
  147. package/dist/chunks/{RolesPage-Cb8joqdJ.js → RolesPage-BN8_zMOC.js} +2 -2
  148. package/dist/chunks/{RolesPage-Cb8joqdJ.js.map → RolesPage-BN8_zMOC.js.map} +1 -1
  149. package/dist/chunks/{SlaConfigPage-B86McKM6.js → SlaConfigPage-B7kZNig4.js} +2 -2
  150. package/dist/chunks/{SlaConfigPage-B86McKM6.js.map → SlaConfigPage-B7kZNig4.js.map} +1 -1
  151. package/dist/chunks/{SlaConfigPage-BY7gvYU6.js → SlaConfigPage-okvZfA_K.js} +2 -2
  152. package/dist/chunks/{SlaConfigPage-BY7gvYU6.js.map → SlaConfigPage-okvZfA_K.js.map} +1 -1
  153. package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js → SupportPermissionsPage-DGAPqJbl.js} +2 -2
  154. package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js.map → SupportPermissionsPage-DGAPqJbl.js.map} +1 -1
  155. package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js → SupportPermissionsPage-Dg_wLOme.js} +2 -2
  156. package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js.map → SupportPermissionsPage-Dg_wLOme.js.map} +1 -1
  157. package/dist/chunks/{TemplatesPage-BDguJ401.js → TemplatesPage-DT9fhlAU.js} +2 -2
  158. package/dist/chunks/{TemplatesPage-BDguJ401.js.map → TemplatesPage-DT9fhlAU.js.map} +1 -1
  159. package/dist/chunks/{TemplatesPage-DdnGgioU.js → TemplatesPage-DiEk538p.js} +2 -2
  160. package/dist/chunks/{TemplatesPage-DdnGgioU.js.map → TemplatesPage-DiEk538p.js.map} +1 -1
  161. package/dist/chunks/{TenantCard-ffwWsgFQ.js → TenantCard-BbSYk9_Z.js} +2 -2
  162. package/dist/chunks/{TenantCard-ffwWsgFQ.js.map → TenantCard-BbSYk9_Z.js.map} +1 -1
  163. package/dist/chunks/{TenantCard-CUjb6og9.js → TenantCard-CEkiKxcZ.js} +2 -2
  164. package/dist/chunks/{TenantCard-CUjb6og9.js.map → TenantCard-CEkiKxcZ.js.map} +1 -1
  165. package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js → TenantScopeSelector-BWfYxvEa.js} +2 -2
  166. package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js.map → TenantScopeSelector-BWfYxvEa.js.map} +1 -1
  167. package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js → TenantScopeSelector-D-BKgQPV.js} +2 -2
  168. package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js.map → TenantScopeSelector-D-BKgQPV.js.map} +1 -1
  169. package/dist/chunks/{TicketDetailPage-GOh9GX7E.js → TicketDetailPage-C1mNS9Up.js} +2 -2
  170. package/dist/chunks/{TicketDetailPage-GOh9GX7E.js.map → TicketDetailPage-C1mNS9Up.js.map} +1 -1
  171. package/dist/chunks/{TicketDetailPage-Du8WMyqf.js → TicketDetailPage-ieVDRh42.js} +2 -2
  172. package/dist/chunks/{TicketDetailPage-Du8WMyqf.js.map → TicketDetailPage-ieVDRh42.js.map} +1 -1
  173. package/dist/chunks/{TicketsPage-Bqd6moQy.js → TicketsPage-CnuWsnIW.js} +2 -2
  174. package/dist/chunks/{TicketsPage-Bqd6moQy.js.map → TicketsPage-CnuWsnIW.js.map} +1 -1
  175. package/dist/chunks/{TicketsPage-WdU4Bb7M.js → TicketsPage-jjyY15_D.js} +2 -2
  176. package/dist/chunks/{TicketsPage-WdU4Bb7M.js.map → TicketsPage-jjyY15_D.js.map} +1 -1
  177. package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js → UserCreateTicketPage-B8Tvf-ag.js} +2 -2
  178. package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js.map → UserCreateTicketPage-B8Tvf-ag.js.map} +1 -1
  179. package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js → UserCreateTicketPage-DnOsDlfO.js} +2 -2
  180. package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js.map → UserCreateTicketPage-DnOsDlfO.js.map} +1 -1
  181. package/dist/chunks/{UserDashboardPage-BP5WeXPS.js → UserDashboardPage-BrtkJ-NB.js} +2 -2
  182. package/dist/chunks/{UserDashboardPage-BP5WeXPS.js.map → UserDashboardPage-BrtkJ-NB.js.map} +1 -1
  183. package/dist/chunks/{UserDashboardPage-B53C8fUq.js → UserDashboardPage-KLB5CQP5.js} +2 -2
  184. package/dist/chunks/{UserDashboardPage-B53C8fUq.js.map → UserDashboardPage-KLB5CQP5.js.map} +1 -1
  185. package/dist/chunks/{UserDetailPage-B110bmGX.js → UserDetailPage-U7smBQoF.js} +5 -5
  186. package/dist/chunks/{UserDetailPage-B110bmGX.js.map → UserDetailPage-U7smBQoF.js.map} +1 -1
  187. package/dist/chunks/{UserDetailPage-CV2VCE46.js → UserDetailPage-_J6lcKAU.js} +2 -2
  188. package/dist/chunks/{UserDetailPage-CV2VCE46.js.map → UserDetailPage-_J6lcKAU.js.map} +1 -1
  189. package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js → UserTicketDetailPage-CWoYQgH-.js} +2 -2
  190. package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js.map → UserTicketDetailPage-CWoYQgH-.js.map} +1 -1
  191. package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js → UserTicketDetailPage-DkufSlvZ.js} +2 -2
  192. package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js.map → UserTicketDetailPage-DkufSlvZ.js.map} +1 -1
  193. package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js → UsersGroupsPage-C38s2-Rq.js} +3 -3
  194. package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js.map → UsersGroupsPage-C38s2-Rq.js.map} +1 -1
  195. package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js → UsersGroupsPage-Dq3rAteo.js} +2 -2
  196. package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js.map → UsersGroupsPage-Dq3rAteo.js.map} +1 -1
  197. package/dist/chunks/{UsersPage-Bg7033pp.js → UsersPage-B5C5KEUR.js} +2 -2
  198. package/dist/chunks/{UsersPage-Bg7033pp.js.map → UsersPage-B5C5KEUR.js.map} +1 -1
  199. package/dist/chunks/{UsersPage-TYAfwPY1.js → UsersPage-CXC9Hvq6.js} +2 -2
  200. package/dist/chunks/{UsersPage-TYAfwPY1.js.map → UsersPage-CXC9Hvq6.js.map} +1 -1
  201. package/dist/chunks/{accessRequestsApi-DZeDvzwv.js → accessRequestsApi-B-4TJ5_U.js} +2 -2
  202. package/dist/chunks/{accessRequestsApi-DZeDvzwv.js.map → accessRequestsApi-B-4TJ5_U.js.map} +1 -1
  203. package/dist/chunks/{accessRequestsApi-ZXFPCid2.js → accessRequestsApi-DZSfThpd.js} +2 -2
  204. package/dist/chunks/{accessRequestsApi-ZXFPCid2.js.map → accessRequestsApi-DZSfThpd.js.map} +1 -1
  205. package/dist/chunks/{aiApi-CsH8DXgs.js → aiApi-B20Teu2v.js} +2 -2
  206. package/dist/chunks/{aiApi-CsH8DXgs.js.map → aiApi-B20Teu2v.js.map} +1 -1
  207. package/dist/chunks/{aiApi-CVPzFTXa.js → aiApi-DMGz-RPM.js} +2 -2
  208. package/dist/chunks/{aiApi-CVPzFTXa.js.map → aiApi-DMGz-RPM.js.map} +1 -1
  209. package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js → applicationAnalyticsApi-Bwa75Fzd.js} +2 -2
  210. package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js.map → applicationAnalyticsApi-Bwa75Fzd.js.map} +1 -1
  211. package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js → applicationAnalyticsApi-CLBqRPfN.js} +2 -2
  212. package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js.map → applicationAnalyticsApi-CLBqRPfN.js.map} +1 -1
  213. package/dist/chunks/{groupsApi-BgCk2fsp.js → groupsApi-QzXI-5xu.js} +2 -2
  214. package/dist/chunks/{groupsApi-BgCk2fsp.js.map → groupsApi-QzXI-5xu.js.map} +1 -1
  215. package/dist/chunks/{groupsApi-BIbG665N.js → groupsApi-hB9kSWEd.js} +2 -2
  216. package/dist/chunks/{groupsApi-BIbG665N.js.map → groupsApi-hB9kSWEd.js.map} +1 -1
  217. package/dist/chunks/{index-Cb3LotuT.js → index--NGcBYUu.js} +3 -3
  218. package/dist/chunks/{index-Cb3LotuT.js.map → index--NGcBYUu.js.map} +1 -1
  219. package/dist/chunks/{index-C33zcyF4.js → index--aPwOFjF.js} +2 -2
  220. package/dist/chunks/{index-C33zcyF4.js.map → index--aPwOFjF.js.map} +1 -1
  221. package/dist/chunks/{index-sMr9qND_.js → index-0VrOtwP0.js} +2 -2
  222. package/dist/chunks/{index-sMr9qND_.js.map → index-0VrOtwP0.js.map} +1 -1
  223. package/dist/chunks/{index-DDKetfKq.js → index-37U271aw.js} +2 -2
  224. package/dist/chunks/{index-DDKetfKq.js.map → index-37U271aw.js.map} +1 -1
  225. package/dist/chunks/{index-B9fS7ir6.js → index-B7qZTuQ-.js} +2 -2
  226. package/dist/chunks/{index-B9fS7ir6.js.map → index-B7qZTuQ-.js.map} +1 -1
  227. package/dist/chunks/{index-CdjBY7L8.js → index-Bedzmqr-.js} +2 -2
  228. package/dist/chunks/{index-CdjBY7L8.js.map → index-Bedzmqr-.js.map} +1 -1
  229. package/dist/chunks/{index-CHG_O1fS.js → index-Betxo5g5.js} +2 -2
  230. package/dist/chunks/{index-CHG_O1fS.js.map → index-Betxo5g5.js.map} +1 -1
  231. package/dist/chunks/{index-jiGu-H8x.js → index-BmaJz475.js} +2 -2
  232. package/dist/chunks/{index-jiGu-H8x.js.map → index-BmaJz475.js.map} +1 -1
  233. package/dist/chunks/{index-C53JoVNk.js → index-Buhqag3v.js} +2 -2
  234. package/dist/chunks/{index-C53JoVNk.js.map → index-Buhqag3v.js.map} +1 -1
  235. package/dist/chunks/{index-DO0Rw7hX.js → index-C3VxlfKq.js} +2 -2
  236. package/dist/chunks/{index-DO0Rw7hX.js.map → index-C3VxlfKq.js.map} +1 -1
  237. package/dist/chunks/{index-CSQ60fpG.js → index-CgpRo8Oe.js} +2 -2
  238. package/dist/chunks/{index-CSQ60fpG.js.map → index-CgpRo8Oe.js.map} +1 -1
  239. package/dist/chunks/{index-B-e-ELsf.js → index-DOY0w8Iu.js} +8 -8
  240. package/dist/chunks/{index-B-e-ELsf.js.map → index-DOY0w8Iu.js.map} +1 -1
  241. package/dist/chunks/{index-D2REDIRX.js → index-DwuvIOrQ.js} +2 -2
  242. package/dist/chunks/{index-D2REDIRX.js.map → index-DwuvIOrQ.js.map} +1 -1
  243. package/dist/chunks/{index-DCcl7Qof.js → index-DzedSLdI.js} +2 -2
  244. package/dist/chunks/{index-DCcl7Qof.js.map → index-DzedSLdI.js.map} +1 -1
  245. package/dist/chunks/{index-2wUhd9Lu.js → index-IgLVXPg8.js} +10 -10
  246. package/dist/chunks/index-IgLVXPg8.js.map +1 -0
  247. package/dist/chunks/{index-CwSaRXXg.js → index-lpIzhufD.js} +1916 -1900
  248. package/dist/chunks/index-lpIzhufD.js.map +1 -0
  249. package/dist/chunks/{index-Cuwn2q-f.js → index-mLUKwbGl.js} +4 -4
  250. package/dist/chunks/{index-Cuwn2q-f.js.map → index-mLUKwbGl.js.map} +1 -1
  251. package/dist/chunks/{index-B0mk2tNY.js → index-tO6MMIFB.js} +2 -2
  252. package/dist/chunks/{index-B0mk2tNY.js.map → index-tO6MMIFB.js.map} +1 -1
  253. package/dist/chunks/{tenantIconMap-BpNANQ5s.js → tenantIconMap-BQD9byc8.js} +2 -2
  254. package/dist/chunks/{tenantIconMap-BpNANQ5s.js.map → tenantIconMap-BQD9byc8.js.map} +1 -1
  255. package/dist/chunks/{tenantIconMap-DtdUgvJO.js → tenantIconMap-CTMuSt18.js} +2 -2
  256. package/dist/chunks/{tenantIconMap-DtdUgvJO.js.map → tenantIconMap-CTMuSt18.js.map} +1 -1
  257. package/dist/chunks/{ticketingApi-Bu4rKwLl.js → ticketingApi-BNIdox5t.js} +2 -2
  258. package/dist/chunks/{ticketingApi-Bu4rKwLl.js.map → ticketingApi-BNIdox5t.js.map} +1 -1
  259. package/dist/chunks/{ticketingApi-r4Avm9iS.js → ticketingApi-J0vC_t7r.js} +2 -2
  260. package/dist/chunks/{ticketingApi-r4Avm9iS.js.map → ticketingApi-J0vC_t7r.js.map} +1 -1
  261. package/dist/chunks/{useAccessRequests-B9bF4swg.js → useAccessRequests-DCNNLnxk.js} +3 -3
  262. package/dist/chunks/{useAccessRequests-B9bF4swg.js.map → useAccessRequests-DCNNLnxk.js.map} +1 -1
  263. package/dist/chunks/{useAccessRequests-JyPUX3Om.js → useAccessRequests-DT7X4FAK.js} +2 -2
  264. package/dist/chunks/{useAccessRequests-JyPUX3Om.js.map → useAccessRequests-DT7X4FAK.js.map} +1 -1
  265. package/dist/chunks/{useUserAccessRequests-DjPQenC2.js → useUserAccessRequests-BYbmG4c7.js} +2 -2
  266. package/dist/chunks/{useUserAccessRequests-DjPQenC2.js.map → useUserAccessRequests-BYbmG4c7.js.map} +1 -1
  267. package/dist/chunks/{useUserAccessRequests-BB6FHW14.js → useUserAccessRequests-CylKxRN6.js} +2 -2
  268. package/dist/chunks/{useUserAccessRequests-BB6FHW14.js.map → useUserAccessRequests-CylKxRN6.js.map} +1 -1
  269. package/dist/hooks/useCollapsibleState.d.ts +5 -2
  270. package/dist/hooks/useCollapsibleState.d.ts.map +1 -1
  271. package/dist/i18n/config.d.ts +1 -0
  272. package/dist/i18n/config.d.ts.map +1 -1
  273. package/dist/main.d.ts +0 -1
  274. package/dist/main.d.ts.map +1 -1
  275. package/dist/smartstack.cjs +1 -1
  276. package/dist/smartstack.js +1 -1
  277. package/dist/utils/permissions.d.ts.map +1 -1
  278. package/package.json +1 -1
  279. package/dist/chunks/index-2wUhd9Lu.js.map +0 -1
  280. package/dist/chunks/index-CwSaRXXg.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"GroupDetailPage-B2FkKrGG.js","sources":["../../src/components/platform/administration/GroupRoleAssignment.tsx","../../src/components/platform/administration/GroupTenantsTab.tsx","../../src/components/platform/administration/GroupMembersTab.tsx","../../src/hooks/useGroupPermissions.ts","../../src/components/platform/administration/permissions/GroupPermissionMatrix.tsx","../../src/components/platform/administration/GroupApplicationsTab.tsx","../../src/components/ui/ScopeBanner.tsx","../../src/pages/platform/administration/users/GroupDetailPage.tsx"],"sourcesContent":["import { useState, useMemo, useRef, useCallback, useEffect } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Plus, Trash2, Loader2, Search, Building2, Globe, X, ChevronDown, Filter, AlertCircle, GitMerge } from 'lucide-react';\r\nimport { groupsApi, type GroupRoleDto, type InheritedGroupRoleDto } from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\nimport { getCustomRoleIcon } from '@/utils/roleUtils';\r\nimport { TenantScopeSelector, type ScopeValue } from '@/components/ui/TenantScopeSelector';\r\n\r\ninterface AdminTenantInfo {\r\n tenantId: string;\r\n tenantSlug: string;\r\n tenantName: string;\r\n tenantType: string;\r\n}\r\n\r\ninterface GroupRoleAssignmentProps {\r\n readonly groupId: string;\r\n readonly assignedRoles?: GroupRoleDto[];\r\n readonly onSave: (roleIds: string[]) => Promise<void>;\r\n readonly roles: RoleListDto[];\r\n readonly loading?: boolean;\r\n readonly tenantId?: string;\r\n readonly isGlobalScope?: boolean;\r\n readonly adminTenants?: AdminTenantInfo[];\r\n}\r\n\r\nconst CATEGORY_STYLES: Record<string, { bg: string; text: string }> = {\r\n Global: { bg: 'bg-[var(--accent-bg)]', text: 'text-[var(--color-accent-500)]' },\r\n Admin: { bg: 'bg-[var(--error-bg)]', text: 'text-[var(--error-text)]' },\r\n Manager: { bg: 'bg-[var(--warning-bg)]', text: 'text-[var(--warning-text)]' },\r\n Contributor: { bg: 'bg-[var(--success-bg)]', text: 'text-[var(--success-text)]' },\r\n Viewer: { bg: 'bg-[var(--info-bg)]', text: 'text-[var(--info-text)]' },\r\n Custom: { bg: 'bg-[var(--accent-bg)]', text: 'text-[var(--color-accent-700)]' },\r\n};\r\n\r\nconst DEFAULT_CATEGORY_STYLE = { bg: 'bg-[var(--bg-secondary)]', text: 'text-[var(--text-secondary)]' };\r\n\r\nexport function GroupRoleAssignment({\r\n groupId,\r\n assignedRoles = [],\r\n onSave,\r\n roles: rolesProp,\r\n loading = false,\r\n tenantId,\r\n isGlobalScope = true,\r\n adminTenants = [],\r\n}: GroupRoleAssignmentProps): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const roles = Array.isArray(rolesProp) ? rolesProp : [];\r\n\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [scopeFilter, setScopeFilter] = useState<string>('all');\r\n const [removing, setRemoving] = useState<string | null>(null);\r\n const [modalOpen, setModalOpen] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const removingRef = useRef(false);\r\n\r\n // Load group's tenants to restrict the overview filter\r\n const [groupTenants, setGroupTenants] = useState<Array<{ id: string; name: string }>>([]);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n groupsApi.getTenants(groupId).then(tenants => {\r\n if (!cancelled) {\r\n setGroupTenants(tenants.map(t => ({ id: t.tenantId, name: t.tenantName })));\r\n }\r\n }).catch(() => {\r\n if (!cancelled) setGroupTenants([]);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupId]);\r\n\r\n const [inheritedRoles, setInheritedRoles] = useState<InheritedGroupRoleDto[]>([]);\r\n const [inheritedLoading, setInheritedLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n setInheritedLoading(true);\r\n groupsApi.getInheritedRoles(groupId).then(roles => {\r\n if (!cancelled) setInheritedRoles(roles);\r\n }).catch(() => {\r\n if (!cancelled) setInheritedRoles([]);\r\n }).finally(() => {\r\n if (!cancelled) setInheritedLoading(false);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupId]);\r\n\r\n // Only show tenants the group belongs to\r\n const tenantOptions = useMemo(() => {\r\n return [...groupTenants].sort((a, b) => a.name.localeCompare(b.name));\r\n }, [groupTenants]);\r\n\r\n // --- Overview table: filtered by scope + search ---\r\n\r\n const filteredAssignedRoles = useMemo(() => {\r\n // First: scope filter\r\n let scoped = assignedRoles;\r\n if (scopeFilter === 'global') {\r\n scoped = scoped.filter(ar => ar.isGlobal);\r\n } else if (scopeFilter !== 'all') {\r\n scoped = scoped.filter(ar => ar.isGlobal || ar.tenantId === scopeFilter);\r\n }\r\n\r\n // Then: text search\r\n if (!searchQuery.trim()) return scoped;\r\n const query = searchQuery.toLowerCase().trim();\r\n return scoped.filter(ar =>\r\n ar.roleName.toLowerCase().includes(query) ||\r\n ar.tenantName?.toLowerCase().includes(query)\r\n );\r\n }, [assignedRoles, searchQuery, scopeFilter]);\r\n\r\n // Build a map of roleId -> RoleListDto for category lookup\r\n const roleMap = useMemo(() => {\r\n const map = new Map<string, RoleListDto>();\r\n for (const r of roles) map.set(r.id, r);\r\n return map;\r\n }, [roles]);\r\n\r\n const handleRemoveRole = useCallback(async (roleId: string, roleTenantId: string | null, isGlobal: boolean) => {\r\n if (removingRef.current) return;\r\n removingRef.current = true;\r\n setRemoving(roleId + (roleTenantId || 'global'));\r\n setError(null);\r\n\r\n try {\r\n await groupsApi.removeRole(groupId, roleId, isGlobal ? undefined : (roleTenantId ?? undefined));\r\n await onSave([]);\r\n } catch (err) {\r\n console.error('Failed to remove role assignment:', err);\r\n setError(t('admin:userRoles.errors.removeFailed', 'Erreur lors du retrait du rôle'));\r\n } finally {\r\n setRemoving(null);\r\n removingRef.current = false;\r\n }\r\n }, [groupId, onSave, t]);\r\n\r\n const handleOpenModal = useCallback(() => setModalOpen(true), []);\r\n const handleCloseModal = useCallback(() => setModalOpen(false), []);\r\n\r\n const handleAssigned = useCallback(async () => {\r\n await onSave([]);\r\n }, [onSave]);\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Error alert */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] flex items-center gap-3\">\r\n <AlertCircle className=\"w-5 h-5 text-[var(--error-text)] flex-shrink-0\" />\r\n <p className=\"flex-1 text-[var(--error-text)]\">{error}</p>\r\n <button onClick={() => setError(null)} className=\"ml-auto\">\r\n <X className=\"w-4 h-4 text-[var(--error-text)]\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Header: search + scope filter + assign button */}\r\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3\">\r\n <div className=\"flex items-center gap-3 flex-1\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]\" />\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n placeholder={t('admin:userRoles.search', 'Rechercher un rôle...')}\r\n className=\"w-full pl-10 pr-4 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] placeholder-[var(--text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n <div className=\"relative\">\r\n <select\r\n value={scopeFilter}\r\n onChange={(e) => setScopeFilter(e.target.value)}\r\n className=\"px-3 py-2 pr-8 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] appearance-none focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:userRoles.scopeAll', 'Tous les tenants')}</option>\r\n <option value=\"global\">{t('admin:roles.global', 'Global')}</option>\r\n {tenantOptions.map(to => (\r\n <option key={to.id} value={to.id}>{to.name}</option>\r\n ))}\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 pointer-events-none text-[var(--text-tertiary)]\" />\r\n </div>\r\n </div>\r\n <button\r\n onClick={handleOpenModal}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors text-sm font-medium\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:userRoles.assignRole', 'Assigner un rôle')}\r\n </button>\r\n </div>\r\n\r\n {/* Overview table */}\r\n {loading ? (\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 <div className=\"overflow-x-auto\">\r\n <table className=\"w-full border border-[var(--border-color)] rounded-[var(--radius-card)] overflow-hidden\">\r\n <thead className=\"bg-[var(--bg-tertiary)]\">\r\n <tr>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.name', 'Rôle')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.category', 'Catégorie')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.tenant', 'Tenant')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)] w-24\">\r\n {t('admin:roles.actions', 'Actions')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredAssignedRoles.length === 0 ? (\r\n <tr>\r\n <td colSpan={4} className=\"px-4 py-8 text-center text-[var(--text-muted)]\">\r\n {assignedRoles.length === 0\r\n ? t('admin:userRoles.noAssignedRoles', 'Aucun rôle assigné à ce groupe')\r\n : t('admin:userRoles.noRoles', 'Aucun rôle trouvé')}\r\n </td>\r\n </tr>\r\n ) : (\r\n filteredAssignedRoles.map((ar) => {\r\n const roleDetail = roleMap.get(ar.roleId);\r\n const category = roleDetail?.category || 'Custom';\r\n const catStyle = CATEGORY_STYLES[category] || DEFAULT_CATEGORY_STYLE;\r\n const customIcon = roleDetail ? getCustomRoleIcon(roleDetail.code) : null;\r\n const removingKey = ar.roleId + (ar.tenantId || 'global');\r\n const isRemoving = removing === removingKey;\r\n\r\n return (\r\n <tr key={removingKey} className=\"hover:bg-[var(--bg-hover)] transition-colors\">\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n {customIcon && <span>{customIcon}</span>}\r\n <span className=\"font-medium text-[var(--text-primary)]\">{ar.roleName}</span>\r\n </div>\r\n {ar.roleDescription && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5 max-w-xs truncate\">{ar.roleDescription}</p>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-full ${catStyle.bg} ${catStyle.text}`}>\r\n {category}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {ar.isGlobal ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--info-bg)] text-[var(--info-text)]\">\r\n <Globe className=\"w-3 h-3\" />\r\n {t('admin:roles.global', 'Global')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--accent-bg)] text-[var(--color-accent-700)]\">\r\n <Building2 className=\"w-3 h-3\" />\r\n {ar.tenantName || t('admin:roles.unknownTenant', 'Tenant')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <button\r\n onClick={() => handleRemoveRole(ar.roleId, ar.tenantId, ar.isGlobal)}\r\n disabled={isRemoving}\r\n className=\"p-1.5 rounded-[var(--radius-button)] text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors disabled:opacity-50\"\r\n title={t('admin:userRoles.removeRole', 'Retirer le rôle')}\r\n >\r\n {isRemoving ? (\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 </td>\r\n </tr>\r\n );\r\n })\r\n )}\r\n </tbody>\r\n </table>\r\n {assignedRoles.length > 0 && (\r\n <div className=\"px-4 py-2 text-xs text-[var(--text-muted)] bg-[var(--bg-tertiary)] border-t border-[var(--border-color)]\">\r\n {filteredAssignedRoles.length !== assignedRoles.length\r\n ? t('admin:userRoles.totalFiltered', '{{filtered}} / {{count}} rôle(s) affiché(s)', { filtered: filteredAssignedRoles.length, count: assignedRoles.length })\r\n : t('admin:userRoles.totalAssigned', '{{count}} rôle(s) assigné(s)', { count: assignedRoles.length })}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {modalOpen && (\r\n <AssignRoleModal\r\n groupId={groupId}\r\n assignedRoles={assignedRoles}\r\n initialTenantId={tenantId}\r\n initialIsGlobalScope={isGlobalScope}\r\n adminTenants={adminTenants}\r\n onAssigned={handleAssigned}\r\n onClose={handleCloseModal}\r\n />\r\n )}\r\n\r\n {/* Inherited Roles */}\r\n {inheritedLoading ? (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n ) : inheritedRoles.length > 0 && (\r\n <div className=\"space-y-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <GitMerge className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n <h3 className=\"text-sm font-semibold text-[var(--text-primary)]\">\r\n {t('groups:hierarchy.inheritedRoles', 'Rôles hérités')}\r\n </h3>\r\n <span className=\"text-xs text-[var(--text-muted)]\">({inheritedRoles.length})</span>\r\n </div>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('groups:hierarchy.inheritedRolesInfo', 'Ces rôles sont hérités des groupes ancêtres. Ils ne peuvent pas être retirés directement — modifiez le groupe ancêtre pour les gérer.')}\r\n </p>\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full border border-[var(--border-color)] rounded-[var(--radius-card)] overflow-hidden\">\r\n <thead className=\"bg-[var(--bg-tertiary)]\">\r\n <tr>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.name', 'Rôle')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.tenant', 'Tenant')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('groups:hierarchy.inheritedFrom', 'Hérité de')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {inheritedRoles.map((ir) => {\r\n const roleDetail = roleMap.get(ir.roleId);\r\n const category = roleDetail?.category || 'Custom';\r\n const catStyle = CATEGORY_STYLES[category] || DEFAULT_CATEGORY_STYLE;\r\n return (\r\n <tr key={ir.roleId + (ir.tenantId || 'global')} className=\"bg-[var(--bg-secondary)] opacity-80\">\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)]\">{ir.roleName}</span>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${catStyle.bg} ${catStyle.text}`}>\r\n {category}\r\n </span>\r\n </div>\r\n {ir.roleDescription && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5 max-w-xs truncate\">{ir.roleDescription}</p>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {ir.isGlobal ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--info-bg)] text-[var(--info-text)]\">\r\n <Globe className=\"w-3 h-3\" />\r\n {t('admin:roles.global', 'Global')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--accent-bg)] text-[var(--color-accent-700)]\">\r\n <Building2 className=\"w-3 h-3\" />\r\n {ir.tenantName || t('admin:roles.unknownTenant', 'Tenant')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className=\"inline-flex items-center gap-1 text-xs text-[var(--text-secondary)]\">\r\n <GitMerge className=\"w-3 h-3\" />\r\n {ir.inheritedFromGroupName}\r\n <span className=\"text-[var(--text-muted)]\">\r\n ({t('groups:hierarchy.level', 'Niveau {{level}}', { level: ir.level })})\r\n </span>\r\n </span>\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// --- Assign Role Modal ---\r\n\r\ninterface AssignRoleModalProps {\r\n readonly groupId: string;\r\n readonly assignedRoles: GroupRoleDto[];\r\n readonly initialTenantId?: string;\r\n readonly initialIsGlobalScope: boolean;\r\n readonly adminTenants: AdminTenantInfo[];\r\n readonly onAssigned: () => Promise<void>;\r\n readonly onClose: () => void;\r\n}\r\n\r\nfunction AssignRoleModal({\r\n groupId,\r\n assignedRoles,\r\n initialTenantId,\r\n initialIsGlobalScope,\r\n adminTenants,\r\n onAssigned,\r\n onClose,\r\n}: AssignRoleModalProps) {\r\n const { t } = useTranslation(['admin', 'groups', 'common']);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [filterCategory, setFilterCategory] = useState<string>('all');\r\n const [filterApplication, setFilterApplication] = useState<string>('all');\r\n const [saving, setSaving] = useState<string | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n const savingRef = useRef(false);\r\n\r\n // Load roles fresh from API when modal opens\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [rolesLoading, setRolesLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n setRolesLoading(true);\r\n adminApi.roles.getAssignable().then(result => {\r\n if (!cancelled) setRoles(Array.isArray(result) ? result : []);\r\n }).catch(() => {\r\n if (!cancelled) setRoles([]);\r\n }).finally(() => {\r\n if (!cancelled) setRolesLoading(false);\r\n });\r\n return () => { cancelled = true; };\r\n }, []);\r\n\r\n // Load group's tenants to restrict the scope selector\r\n const [groupTenantIds, setGroupTenantIds] = useState<Set<string> | null>(null);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n groupsApi.getTenants(groupId).then(tenants => {\r\n if (!cancelled) {\r\n setGroupTenantIds(new Set(tenants.map(t => t.tenantId)));\r\n }\r\n }).catch(() => {\r\n if (!cancelled) setGroupTenantIds(null);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupId]);\r\n\r\n // Load applications from the group's tenants (union of all tenant applications)\r\n const [applications, setApplications] = useState<Array<{ id: string; name: string }>>([]);\r\n\r\n useEffect(() => {\r\n if (!groupTenantIds || groupTenantIds.size === 0) {\r\n setApplications([]);\r\n return;\r\n }\r\n let cancelled = false;\r\n const tenantIds = Array.from(groupTenantIds);\r\n Promise.all(tenantIds.map(tid => adminApi.tenants.getApplications(tid)))\r\n .then(results => {\r\n if (cancelled) return;\r\n const appMap = new Map<string, string>();\r\n for (const apps of results) {\r\n for (const app of apps) {\r\n if (!appMap.has(app.applicationId)) {\r\n appMap.set(app.applicationId, app.label);\r\n }\r\n }\r\n }\r\n setApplications(\r\n Array.from(appMap.entries())\r\n .map(([id, name]) => ({ id, name }))\r\n .sort((a, b) => a.name.localeCompare(b.name))\r\n );\r\n })\r\n .catch(() => {\r\n if (!cancelled) setApplications([]);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupTenantIds]);\r\n\r\n // Only show tenants that the group belongs to\r\n const modalTenants = useMemo(() => {\r\n if (!groupTenantIds) return adminTenants;\r\n return adminTenants.filter(at => groupTenantIds.has(at.tenantId));\r\n }, [adminTenants, groupTenantIds]);\r\n\r\n // Local scope state for the modal (initialized from parent)\r\n const [modalScope, setModalScope] = useState<ScopeValue>(() => {\r\n if (initialIsGlobalScope || !initialTenantId) return 'global';\r\n const tenant = adminTenants.find(at => at.tenantId === initialTenantId);\r\n if (!tenant) return 'global';\r\n return {\r\n tenantId: tenant.tenantId,\r\n tenantSlug: tenant.tenantSlug,\r\n tenantUserId: '',\r\n tenantName: tenant.tenantName,\r\n };\r\n });\r\n\r\n const modalIsGlobal = modalScope === 'global';\r\n const modalTenantId = !modalIsGlobal ? modalScope.tenantId : undefined;\r\n\r\n // Roles already assigned for the modal's current scope\r\n const currentScopeRoleIds = useMemo(() => {\r\n const ids = new Set<string>();\r\n for (const ar of assignedRoles) {\r\n if (modalIsGlobal && ar.isGlobal) ids.add(ar.roleId);\r\n else if (!modalIsGlobal && ar.tenantId === modalTenantId) ids.add(ar.roleId);\r\n }\r\n return ids;\r\n }, [assignedRoles, modalIsGlobal, modalTenantId]);\r\n\r\n // Load tenant's accessible application IDs when a tenant is selected\r\n const [tenantAppIds, setTenantAppIds] = useState<Set<string> | null>(null);\r\n\r\n useEffect(() => {\r\n if (modalIsGlobal || !modalTenantId) {\r\n setTenantAppIds(null);\r\n return;\r\n }\r\n let cancelled = false;\r\n adminApi.tenants.getApplications(modalTenantId).then(apps => {\r\n if (!cancelled) {\r\n setTenantAppIds(new Set(apps.map(a => a.applicationId)));\r\n }\r\n }).catch(() => {\r\n if (!cancelled) setTenantAppIds(null);\r\n });\r\n return () => { cancelled = true; };\r\n }, [modalIsGlobal, modalTenantId]);\r\n\r\n // Roles available for the current scope (filtered by tenant's accessible apps)\r\n const scopedRoles = useMemo(() => {\r\n if (modalIsGlobal || !tenantAppIds) return roles;\r\n return roles.filter(r => !r.applicationId || tenantAppIds.has(r.applicationId));\r\n }, [roles, modalIsGlobal, tenantAppIds]);\r\n\r\n const categories = useMemo(() => {\r\n const cats = new Set(scopedRoles.map(r => r.category || 'Custom'));\r\n return ['all', ...Array.from(cats).sort((a, b) => a.localeCompare(b))];\r\n }, [scopedRoles]);\r\n\r\n const filteredRoles = useMemo(() => {\r\n let filtered = scopedRoles;\r\n\r\n // Application filter\r\n if (filterApplication !== 'all') {\r\n filtered = filtered.filter(r => r.applicationId === filterApplication);\r\n }\r\n\r\n // Category filter\r\n if (filterCategory !== 'all') {\r\n filtered = filtered.filter(r => (r.category || 'Custom') === filterCategory);\r\n }\r\n\r\n // Text search\r\n if (searchQuery.trim()) {\r\n const query = searchQuery.toLowerCase().trim();\r\n filtered = filtered.filter(r =>\r\n r.name.toLowerCase().includes(query) ||\r\n r.shortName?.toLowerCase().includes(query) ||\r\n r.description?.toLowerCase().includes(query)\r\n );\r\n }\r\n\r\n return filtered;\r\n }, [scopedRoles, filterApplication, filterCategory, searchQuery]);\r\n\r\n const handleAssignRole = useCallback(async (roleId: string) => {\r\n if (savingRef.current) return;\r\n savingRef.current = true;\r\n setSaving(roleId);\r\n setError(null);\r\n\r\n try {\r\n await groupsApi.assignRole(groupId, {\r\n roleId,\r\n isInheritable: true,\r\n tenantId: !modalIsGlobal && modalTenantId ? modalTenantId : undefined,\r\n });\r\n await onAssigned();\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('admin:userRoles.errors.assignFailed', 'Erreur lors de l\\'assignation du rôle'));\r\n } finally {\r\n setSaving(null);\r\n savingRef.current = false;\r\n }\r\n }, [groupId, modalIsGlobal, modalTenantId, onAssigned, t]);\r\n\r\n return (\r\n <div className=\"fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm\">\r\n <div className=\"relative w-full max-w-2xl h-[80vh] bg-[var(--bg-card)] rounded-[var(--radius-card)] shadow-2xl border border-[var(--border-color)] overflow-hidden flex flex-col animate-in fade-in zoom-in duration-200\">\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-[var(--border-color)]\">\r\n <div className=\"flex items-center gap-4\">\r\n <div>\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:userRoles.assignRole', 'Assigner un rôle')}\r\n </h2>\r\n </div>\r\n <TenantScopeSelector\r\n value={modalScope}\r\n onChange={setModalScope}\r\n adminTenants={modalTenants}\r\n />\r\n </div>\r\n <button\r\n onClick={onClose}\r\n className=\"p-1.5 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n\r\n {/* Error alert */}\r\n {error && (\r\n <div className=\"mx-6 mt-3 p-3 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] flex items-center gap-3\">\r\n <AlertCircle className=\"w-4 h-4 text-[var(--error-text)] flex-shrink-0\" />\r\n <p className=\"flex-1 text-sm text-[var(--error-text)]\">{error}</p>\r\n <button onClick={() => setError(null)}>\r\n <X className=\"w-3.5 h-3.5 text-[var(--error-text)]\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Filters */}\r\n <div className=\"px-6 py-3 border-b border-[var(--border-color)] flex flex-col gap-3\">\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]\" />\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n placeholder={t('admin:userRoles.search', 'Rechercher un rôle...')}\r\n className=\"w-full pl-10 pr-4 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] placeholder-[var(--text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n autoFocus\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-secondary)] shrink-0\" />\r\n <select\r\n value={filterApplication}\r\n onChange={(e) => setFilterApplication(e.target.value)}\r\n className=\"flex-1 min-w-0 px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:userRoles.filterByApplication', 'Toutes les applications')}</option>\r\n {applications.map(app => (\r\n <option key={app.id} value={app.id}>{app.name}</option>\r\n ))}\r\n </select>\r\n <select\r\n value={filterCategory}\r\n onChange={(e) => setFilterCategory(e.target.value)}\r\n className=\"flex-1 min-w-0 px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:userRoles.filterByCategory', 'Toutes les catégories')}</option>\r\n {categories.filter(c => c !== 'all').map(cat => (\r\n <option key={cat} value={cat}>{cat}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n\r\n {/* Role list */}\r\n <div className=\"flex-1 overflow-y-auto\">\r\n {rolesLoading ? (\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 <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-tertiary)] sticky top-0 z-10\">\r\n <tr>\r\n <th className=\"text-left px-6 py-2.5 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.name', 'Rôle')}\r\n </th>\r\n <th className=\"text-left px-4 py-2.5 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.category', 'Catégorie')}\r\n </th>\r\n <th className=\"text-right px-6 py-2.5 text-sm font-medium text-[var(--text-secondary)] w-32\">\r\n {t('admin:roles.actions', 'Actions')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredRoles.length === 0 ? (\r\n <tr>\r\n <td colSpan={3} className=\"px-6 py-12 text-center\">\r\n <Search className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-muted)]\">\r\n {t('admin:userRoles.noRoles', 'Aucun rôle trouvé')}\r\n </p>\r\n </td>\r\n </tr>\r\n ) : (\r\n filteredRoles.map((role) => {\r\n const isAlreadyAssigned = currentScopeRoleIds.has(role.id);\r\n const catStyle = CATEGORY_STYLES[role.category || 'Custom'] || DEFAULT_CATEGORY_STYLE;\r\n const customIcon = getCustomRoleIcon(role.code);\r\n const isAssigning = saving === role.id;\r\n\r\n return (\r\n <tr\r\n key={role.id}\r\n className={`transition-colors ${isAlreadyAssigned ? 'bg-[var(--accent-bg)] opacity-60' : 'hover:bg-[var(--bg-hover)]'}`}\r\n >\r\n <td className=\"px-6 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n {customIcon && <span>{customIcon}</span>}\r\n <div>\r\n <span className=\"font-medium text-[var(--text-primary)]\">{role.name}</span>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5 max-w-sm truncate\">{role.description}</p>\r\n )}\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-full ${catStyle.bg} ${catStyle.text}`}>\r\n {role.category || 'Custom'}\r\n </span>\r\n </td>\r\n <td className=\"px-6 py-3 text-right\">\r\n {isAlreadyAssigned ? (\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n {t('admin:userRoles.alreadyAssigned', 'Déjà assigné')}\r\n </span>\r\n ) : (\r\n <button\r\n onClick={() => handleAssignRole(role.id)}\r\n disabled={isAssigning}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white text-xs font-medium hover:bg-[var(--color-accent-700)] transition-colors disabled:opacity-50\"\r\n >\r\n {isAssigning ? (\r\n <Loader2 className=\"w-3.5 h-3.5 animate-spin\" />\r\n ) : (\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n )}\r\n {t('admin:userRoles.assign', 'Assigner')}\r\n </button>\r\n )}\r\n </td>\r\n </tr>\r\n );\r\n })\r\n )}\r\n </tbody>\r\n </table>\r\n )}\r\n </div>\r\n\r\n {/* Footer */}\r\n <div className=\"px-6 py-3 border-t border-[var(--border-color)] bg-[var(--bg-tertiary)] flex justify-end\">\r\n <button\r\n onClick={onClose}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors text-sm font-medium\"\r\n >\r\n {t('common:close', 'Fermer')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { Building2, Loader2, Plus, RefreshCw, Search, X, Trash2, AlertTriangle, CheckCircle, Check, LayoutGrid, LayoutList, GitBranch, Link as LinkIcon } from 'lucide-react';\r\nimport { Link } from 'react-router-dom';\r\nimport { groupsApi, type GroupTenantDto, type InheritedTenantDto } from '@/services/api/groupsApi';\r\nimport { adminApi, type TenantListDto } from '@/services/api/adminApi';\r\nimport { type ViewMode } from '@/components/ui/DataView';\r\nimport { useTenantTypeSettings } from '@/hooks/useTenantTypeSettings';\r\nimport { getLucideIcon, getColorClasses } from '@/utils/tenantIconMap';\r\n\r\ninterface GroupTenantsTabProps {\r\n readonly groupId: string;\r\n readonly groupName: string;\r\n}\r\n\r\nconst getSelectAllClass = (isAllSelected: boolean): string => {\r\n return isAllSelected\r\n ? 'bg-[var(--color-accent-600)] border-[var(--color-accent-600)]'\r\n : 'border-[var(--border-color)]';\r\n};\r\n\r\nconst getTenantItemClass = (isSelected: boolean): string => {\r\n return isSelected\r\n ? 'border-[var(--color-accent-500)] bg-[var(--color-accent-500)]/5'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)]';\r\n};\r\n\r\nconst getTenantCheckboxClass = (isSelected: boolean): string => {\r\n return isSelected\r\n ? 'bg-[var(--color-accent-600)] border-[var(--color-accent-600)]'\r\n : 'border-[var(--border-color)]';\r\n};\r\n\r\nconst filterAvailableTenants = (allTenants: any[] | null | undefined, assignedTenantIds: Set<string>, searchQuery: string): any[] => {\r\n if (!allTenants) return [];\r\n const query = searchQuery.toLowerCase().trim();\r\n return allTenants\r\n .filter(t => !assignedTenantIds.has(t.id))\r\n .filter(t => {\r\n if (!query) return true;\r\n return t.name.toLowerCase().includes(query) || t.slug.toLowerCase().includes(query) || t.type.toLowerCase().includes(query);\r\n });\r\n};\r\n\r\nconst filterAssignedTenants = (tenants: any[] | null, pageSearchQuery: string): any[] => {\r\n if (!tenants) return [];\r\n if (!pageSearchQuery.trim()) return tenants;\r\n const query = pageSearchQuery.toLowerCase().trim();\r\n return tenants.filter((t) =>\r\n t.tenantName.toLowerCase().includes(query) ||\r\n t.tenantSlug.toLowerCase().includes(query) ||\r\n t.tenantType.toLowerCase().includes(query)\r\n );\r\n};\r\n\r\nexport function GroupTenantsTab({ groupId, groupName }: GroupTenantsTabProps): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const navigate = useNavigate();\r\n const { getIconForType } = useTenantTypeSettings();\r\n\r\n const [tenants, setTenants] = useState<GroupTenantDto[] | null>(null);\r\n const [inheritedTenants, setInheritedTenants] = useState<InheritedTenantDto[]>([]);\r\n const [allTenants, setAllTenants] = useState<TenantListDto[] | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [showAddModal, setShowAddModal] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [removingTenantId, setRemovingTenantId] = useState<string | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n\r\n // Multi-select and view mode states\r\n const [selectedTenantIds, setSelectedTenantIds] = useState<string[]>([]);\r\n const [pageSearchQuery, setPageSearchQuery] = useState('');\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [adding, setAdding] = useState(false);\r\n\r\n const loadTenants = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const [data, inherited] = await Promise.all([\r\n groupsApi.getTenants(groupId),\r\n groupsApi.getInheritedTenants(groupId),\r\n ]);\r\n setTenants(data);\r\n setInheritedTenants(inherited);\r\n } catch (err) {\r\n console.error('Failed to load group tenants:', err);\r\n setError(t('groups:tenants.loadError', 'Erreur lors du chargement des tenants'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [groupId, t]);\r\n\r\n const loadAllTenants = async () => {\r\n try {\r\n const result = await adminApi.tenants.getAll();\r\n setAllTenants(result.items);\r\n } catch (err) {\r\n console.error('Failed to load all tenants:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadTenants();\r\n loadAllTenants();\r\n }, [loadTenants]);\r\n\r\n const handleRemoveTenant = async (tenantId: string) => {\r\n const tenant = tenants?.find((t) => t.tenantId === tenantId);\r\n if (!confirm(t('groups:tenants.confirmRemove', `Êtes-vous sûr de vouloir retirer le groupe \"${groupName}\" du tenant \"${tenant?.tenantName}\" ?`))) {\r\n return;\r\n }\r\n\r\n try {\r\n setRemovingTenantId(tenantId);\r\n setError(null);\r\n await groupsApi.removeFromTenant(groupId, tenantId);\r\n await loadTenants();\r\n setSuccess(t('groups:tenants.removeSuccess', 'Tenant retiré avec succès'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err: any) {\r\n console.error('Failed to remove tenant:', err);\r\n const errorMessage = err?.response?.data?.message || t('groups:tenants.removeError', 'Erreur lors du retrait du tenant');\r\n setError(errorMessage);\r\n } finally {\r\n setRemovingTenantId(null);\r\n }\r\n };\r\n\r\n const addTenantsAndTrackResults = async (): Promise<{ successCount: number; failedTenants: string[] }> => {\r\n let successCount = 0;\r\n const failedTenants: string[] = [];\r\n\r\n for (const tenantId of selectedTenantIds) {\r\n try {\r\n await groupsApi.addToTenant(groupId, { tenantId });\r\n successCount++;\r\n } catch {\r\n const tenantName = filteredAvailableTenants?.find((t) => t.id === tenantId)?.name;\r\n failedTenants.push(tenantName || tenantId);\r\n }\r\n }\r\n\r\n return { successCount, failedTenants };\r\n };\r\n\r\n const handleAddSelectedTenants = async () => {\r\n if (selectedTenantIds.length === 0) return;\r\n\r\n try {\r\n setAdding(true);\r\n setError(null);\r\n const { successCount, failedTenants } = await addTenantsAndTrackResults();\r\n\r\n await loadTenants();\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedTenantIds([]);\r\n\r\n if (failedTenants.length === 0) {\r\n setSuccess(t('groups:tenants.addSelectedSuccess', { count: successCount }));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } else if (successCount > 0) {\r\n setError(t('groups:tenants.addPartialError', {\r\n success: successCount,\r\n failed: failedTenants.join(', ')\r\n }));\r\n } else {\r\n setError(t('groups:tenants.addSelectedError', 'Erreur lors de l\\'ajout des tenants'));\r\n }\r\n } catch (err: any) {\r\n console.error('Failed to add tenants:', err);\r\n setError(t('groups:tenants.addSelectedError', 'Erreur lors de l\\'ajout des tenants'));\r\n } finally {\r\n setAdding(false);\r\n }\r\n };\r\n\r\n const toggleTenantSelection = (tenantId: string) => {\r\n setSelectedTenantIds((prev) =>\r\n prev.includes(tenantId)\r\n ? prev.filter((id) => id !== tenantId)\r\n : [...prev, tenantId]\r\n );\r\n };\r\n\r\n const toggleSelectAll = () => {\r\n if (!filteredAvailableTenants) return;\r\n const allIds = filteredAvailableTenants.map((t) => t.id);\r\n const allSelected = allIds.every((id) => selectedTenantIds.includes(id));\r\n setSelectedTenantIds(allSelected ? [] : allIds);\r\n };\r\n\r\n // Filter available tenants (not already assigned)\r\n const assignedTenantIds = useMemo(() => new Set(tenants?.map(t => t.tenantId) ?? []), [tenants]);\r\n const availableTenants = useMemo(() => filterAvailableTenants(allTenants, assignedTenantIds, searchQuery), [allTenants, assignedTenantIds, searchQuery]);\r\n\r\n // Filter by search query (modal)\r\n const filteredAvailableTenants = availableTenants;\r\n\r\n // Filter tenants on page by search query\r\n const filteredTenants = useMemo(() => filterAssignedTenants(tenants, pageSearchQuery), [tenants, pageSearchQuery]);\r\n\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\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)] flex items-center gap-2\">\r\n <Building2 className=\"w-5 h-5\" />\r\n {t('groups:tenants.title', 'Tenants du groupe')}\r\n {tenants && (\r\n <span className=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {tenants.length}\r\n </span>\r\n )}\r\n </h3>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:tenants.add', 'Ajouter')}\r\n </button>\r\n <button\r\n onClick={loadTenants}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Search and View Toggle */}\r\n {(tenants?.length ?? 0) > 0 && (\r\n <div className=\"flex flex-col sm:flex-row items-stretch sm:items-center gap-3\">\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('groups:tenants.searchPlaceholderPage', 'Rechercher un tenant...')}\r\n value={pageSearchQuery}\r\n onChange={(e) => setPageSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-lg 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 <div className=\"flex items-center gap-1 p-1 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setViewMode('cards')}\r\n className={`px-3 py-1.5 rounded-[var(--radius-button)] text-sm font-medium flex items-center gap-2 transition-all ${\r\n viewMode === 'cards'\r\n ? 'bg-[var(--color-accent-600)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('groups:tenants.viewCards', 'Cartes')}</span>\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`px-3 py-1.5 rounded-[var(--radius-button)] text-sm font-medium flex items-center gap-2 transition-all ${\r\n viewMode === 'table'\r\n ? 'bg-[var(--color-accent-600)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <LayoutList className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('groups:tenants.viewTable', 'Table')}</span>\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Alerts */}\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-red-500/10 border border-red-500/20 flex items-center gap-3\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-500 flex-shrink-0\" />\r\n <p className=\"text-red-500\">{error}</p>\r\n <button onClick={() => setError(null)} className=\"ml-auto\">\r\n <X className=\"w-4 h-4 text-red-500\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {success && (\r\n <div className=\"p-4 rounded-lg bg-green-500/10 border border-green-500/20 flex items-center gap-3\">\r\n <CheckCircle className=\"w-5 h-5 text-green-500 flex-shrink-0\" />\r\n <p className=\"text-green-500\">{success}</p>\r\n </div>\r\n )}\r\n\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-lg bg-blue-500/10 border border-blue-500/20\">\r\n <p className=\"text-sm text-blue-500\">\r\n {t('groups:tenants.info', 'Les utilisateurs de ce groupe auront automatiquement accès aux tenants listés ci-dessous via leur appartenance au groupe.')}\r\n </p>\r\n </div>\r\n\r\n {/* Content */}\r\n {loading && (\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 {!loading && (!tenants || tenants.length === 0) && (\r\n <div className=\"text-center py-12\">\r\n <Building2 className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)] mb-4\">\r\n {t('groups:tenants.noTenants', 'Ce groupe n\\'est associé à aucun tenant')}\r\n </p>\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:tenants.addFirst', 'Ajouter un premier tenant')}\r\n </button>\r\n </div>\r\n )}\r\n {!loading && (tenants?.length ?? 0) > 0 && (filteredTenants?.length ?? 0) === 0 && (\r\n <div className=\"text-center py-12\">\r\n <Search className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('groups:tenants.noResults', 'Aucun tenant ne correspond à votre recherche')}\r\n </p>\r\n </div>\r\n )}\r\n {!loading && (filteredTenants?.length ?? 0) > 0 && viewMode === 'cards' && (\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {filteredTenants?.map((tenant) => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={tenant.tenantId}\r\n onClick={() => navigate(`/administration/tenants/${tenant.tenantId}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/tenants/${tenant.tenantId}`); } }}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left\"\r\n >\r\n {(() => {\r\n const typeInfo = getIconForType(tenant.tenantType);\r\n const TenantIcon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return (\r\n <>\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2 rounded-lg ${colors.bg}`}>\r\n <TenantIcon className={`w-5 h-5 ${colors.text}`} />\r\n </div>\r\n <div className=\"min-w-0\">\r\n <h4 className=\"text-sm font-semibold text-[var(--color-accent-500)] hover:underline truncate\">\r\n {tenant.tenantName}\r\n </h4>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{tenant.tenantSlug}</p>\r\n </div>\r\n </div>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${colors.bg} ${colors.text}`}>\r\n {tenant.tenantType}\r\n </span>\r\n </div>\r\n\r\n <div className=\"mt-3 pt-3 border-t border-[var(--border-color)] space-y-1\">\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:tenants.addedAt', 'Ajouté le')}: {new Date(tenant.addedAt).toLocaleDateString()}\r\n </p>\r\n {tenant.addedBy && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:tenants.addedBy', 'Par')}: {tenant.addedBy}\r\n </p>\r\n )}\r\n </div>\r\n\r\n <div className=\"mt-3 flex justify-end\">\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleRemoveTenant(tenant.tenantId); }}\r\n disabled={removingTenantId === tenant.tenantId}\r\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingTenantId === tenant.tenantId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </div>\r\n </>\r\n );\r\n })()}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n {!loading && (filteredTenants?.length ?? 0) > 0 && viewMode !== 'cards' && (\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">\r\n {t('groups:tenants.tableHeaders.name', 'Nom')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">\r\n {t('groups:tenants.tableHeaders.slug', 'Slug')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">\r\n {t('groups:tenants.tableHeaders.type', 'Type')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">\r\n {t('groups:tenants.tableHeaders.addedAt', 'Ajouté le')}\r\n </th>\r\n <th className=\"w-24 px-4 py-3\"></th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredTenants?.map((tenant) => (\r\n <tr key={tenant.tenantId} onClick={() => navigate(`/administration/tenants/${tenant.tenantId}`)} className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer\">\r\n {(() => {\r\n const typeInfo = getIconForType(tenant.tenantType);\r\n const RowIcon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return (\r\n <>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={`p-1.5 rounded-lg ${colors.bg}`}>\r\n <RowIcon className={`w-4 h-4 ${colors.text}`} />\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)] hover:underline\">{tenant.tenantName}</span>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)] hidden md:table-cell\">\r\n {tenant.tenantSlug}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${colors.bg} ${colors.text}`}>\r\n {tenant.tenantType}\r\n </span>\r\n </td>\r\n </>\r\n );\r\n })()}\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-tertiary)] hidden lg:table-cell\">\r\n {new Date(tenant.addedAt).toLocaleDateString()}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleRemoveTenant(tenant.tenantId); }}\r\n disabled={removingTenantId === tenant.tenantId}\r\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingTenantId === tenant.tenantId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n\r\n {/* Inherited Tenants */}\r\n {!loading && inheritedTenants.length > 0 && (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <GitBranch className=\"w-5 h-5\" />\r\n {t('groups:tenants.inheritedTitle')}\r\n <span className=\"ml-1 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {inheritedTenants.length}\r\n </span>\r\n </h3>\r\n\r\n <div className=\"p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:tenants.inheritedInfo')}\r\n </p>\r\n </div>\r\n\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {inheritedTenants.map((tenant) => (\r\n <button\r\n type=\"button\"\r\n key={`inherited-${tenant.tenantId}-${tenant.inheritedFromGroupId}`}\r\n onClick={() => navigate(`/administration/tenants/${tenant.tenantId}`)}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-dashed border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left\"\r\n >\r\n {(() => {\r\n const typeInfo = getIconForType(tenant.tenantType);\r\n const InheritedIcon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return (\r\n <>\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2 rounded-lg ${colors.bg}`}>\r\n <InheritedIcon className={`w-5 h-5 ${colors.text}`} />\r\n </div>\r\n <div className=\"min-w-0\">\r\n <h4 className=\"text-sm font-semibold text-[var(--color-accent-500)] hover:underline truncate\">\r\n {tenant.tenantName}\r\n </h4>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{tenant.tenantSlug}</p>\r\n </div>\r\n </div>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${colors.bg} ${colors.text}`}>\r\n {tenant.tenantType}\r\n </span>\r\n </div>\r\n\r\n <div className=\"mt-3 pt-3 border-t border-[var(--border-color)]\">\r\n <Link\r\n to={`/administration/users/groups/${tenant.inheritedFromGroupId}`}\r\n onClick={(e) => e.stopPropagation()}\r\n className=\"flex items-center gap-1.5 text-xs text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <LinkIcon className=\"w-3 h-3\" />\r\n {t('groups:tenants.inheritedFrom')} <span className=\"font-medium\">{tenant.inheritedFromGroupName}</span>\r\n </Link>\r\n </div>\r\n </>\r\n );\r\n })()}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Add Tenant Modal */}\r\n {showAddModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-lg mx-4 bg-[var(--bg-primary)] rounded-[var(--radius-card)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('groups:tenants.addModalTitle', 'Ajouter le groupe à des tenants')}\r\n </h3>\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedTenantIds([]);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"p-4 space-y-4\">\r\n {/* Search */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('groups:tenants.searchPlaceholder', 'Rechercher un tenant...')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-lg 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 autoFocus\r\n />\r\n </div>\r\n\r\n {/* Select All */}\r\n {(filteredAvailableTenants?.length ?? 0) > 0 && (\r\n <div className=\"flex items-center justify-between px-1\">\r\n <button\r\n onClick={toggleSelectAll}\r\n className=\"flex items-center gap-2 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] transition-colors\"\r\n >\r\n <div className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${getSelectAllClass(filteredAvailableTenants.every((t) => selectedTenantIds.includes(t.id)))}`}>\r\n {filteredAvailableTenants.every((t) => selectedTenantIds.includes(t.id)) && (\r\n <Check className=\"w-3 h-3 text-white\" />\r\n )}\r\n </div>\r\n {filteredAvailableTenants.every((t) => selectedTenantIds.includes(t.id))\r\n ? t('groups:tenants.deselectAll', 'Tout désélectionner')\r\n : t('groups:tenants.selectAll', 'Tout sélectionner')}\r\n </button>\r\n {selectedTenantIds.length > 0 && (\r\n <span className=\"text-xs text-[var(--text-tertiary)]\">\r\n {selectedTenantIds.length} {t('common.selected', 'sélectionné(s)')}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Tenant List */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {!filteredAvailableTenants || filteredAvailableTenants.length === 0 ? (\r\n <div className=\"text-center py-8\">\r\n <Building2 className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('groups:tenants.noAvailableTenants', 'Aucun tenant disponible')}\r\n </p>\r\n </div>\r\n ) : (\r\n filteredAvailableTenants.map((tenant) => {\r\n const isSelected = selectedTenantIds.includes(tenant.id);\r\n const modalTypeInfo = getIconForType(tenant.type);\r\n const ModalIcon = getLucideIcon(modalTypeInfo.icon);\r\n const modalColors = getColorClasses(modalTypeInfo.color);\r\n return (\r\n <button\r\n type=\"button\"\r\n key={tenant.id}\r\n onClick={() => toggleTenantSelection(tenant.id)}\r\n className={`w-full flex items-center gap-3 p-3 rounded-lg border cursor-pointer transition-colors text-left ${getTenantItemClass(isSelected)}`}\r\n >\r\n <div className={`w-5 h-5 rounded border-2 flex items-center justify-center flex-shrink-0 transition-colors ${getTenantCheckboxClass(isSelected)}`}>\r\n {isSelected && <Check className=\"w-3 h-3 text-white\" />}\r\n </div>\r\n <div className={`p-2 rounded-lg ${modalColors.bg}`}>\r\n <ModalIcon className={`w-4 h-4 ${modalColors.text}`} />\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {tenant.name}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{tenant.slug}</p>\r\n </div>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${modalColors.bg} ${modalColors.text}`}>\r\n {tenant.type}\r\n </span>\r\n </button>\r\n );\r\n })\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex justify-end gap-2 p-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedTenantIds([]);\r\n }}\r\n className=\"px-4 py-2 rounded-lg bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel', 'Annuler')}\r\n </button>\r\n <button\r\n onClick={handleAddSelectedTenants}\r\n disabled={selectedTenantIds.length === 0 || adding}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n {adding ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Plus className=\"w-4 h-4\" />\r\n )}\r\n {t('groups:tenants.addSelected', { count: selectedTenantIds.length })}\r\n </button>\r\n </div>\r\n </div>\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 { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { Users, Loader2, Plus, RefreshCw, Search, X, Trash2, AlertTriangle, CheckCircle, Info, Table, LayoutGrid, Check } from 'lucide-react';\r\nimport { groupsApi, type GroupMemberDto } from '@/services/api/groupsApi';\r\nimport { adminApi, type UserListDto } from '@/services/api/adminApi';\r\n\r\ntype ViewMode = 'table' | 'card';\r\n\r\ninterface GroupMembersTabProps {\r\n readonly groupId: string;\r\n readonly groupName: string;\r\n readonly isSyncedFromEntra: boolean;\r\n}\r\n\r\nexport function GroupMembersTab({ groupId, groupName, isSyncedFromEntra }: GroupMembersTabProps): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const navigate = useNavigate();\r\n\r\n const [members, setMembers] = useState<GroupMemberDto[] | null>(null);\r\n const [allUsers, setAllUsers] = useState<UserListDto[] | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [showAddModal, setShowAddModal] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [removingUserId, setRemovingUserId] = useState<string | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('table');\r\n const [selectedUserIds, setSelectedUserIds] = useState<Set<string>>(new Set());\r\n const [isAddingMultiple, setIsAddingMultiple] = useState(false);\r\n\r\n const loadMembers = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const data = await groupsApi.getMembers(groupId);\r\n setMembers(data);\r\n } catch (err) {\r\n console.error('Failed to load group members:', err);\r\n setError(t('groups:members.loadError', 'Erreur lors du chargement des membres'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [groupId, t]);\r\n\r\n const loadAllUsers = async () => {\r\n try {\r\n // globalScope: true to get ALL users regardless of tenant context\r\n // Groups are system-level entities, so we need all users for member management\r\n const response = await adminApi.users.getAll({ isActive: true, globalScope: true });\r\n // Handle both array and paginated response\r\n const users = Array.isArray(response) ? response : response.items;\r\n setAllUsers(users);\r\n } catch (err) {\r\n console.error('Failed to load all users:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadMembers();\r\n loadAllUsers();\r\n }, [loadMembers]);\r\n\r\n const handleAddMultipleMembers = async () => {\r\n if (selectedUserIds.size === 0) return;\r\n\r\n try {\r\n setIsAddingMultiple(true);\r\n setError(null);\r\n\r\n const userIdsArray = Array.from(selectedUserIds);\r\n for (const userId of userIdsArray) {\r\n await groupsApi.addMember(groupId, { userId });\r\n }\r\n\r\n await loadMembers();\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedUserIds(new Set());\r\n setSuccess(t('groups:members.addMultipleSuccess', { count: userIdsArray.length }));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err: any) {\r\n console.error('Failed to add members:', err);\r\n const errorMessage = err?.response?.data?.message || t('groups:members.addError', 'Erreur lors de l\\'ajout des membres');\r\n setError(errorMessage);\r\n } finally {\r\n setIsAddingMultiple(false);\r\n }\r\n };\r\n\r\n const toggleUserSelection = (userId: string) => {\r\n setSelectedUserIds(prev => {\r\n const next = new Set(prev);\r\n if (next.has(userId)) {\r\n next.delete(userId);\r\n } else {\r\n next.add(userId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const handleRemoveMember = async (userId: string) => {\r\n const member = members?.find((m) => m.userId === userId);\r\n if (!confirm(t('groups:members.confirmRemove', { userName: member?.fullName, groupName }))) {\r\n return;\r\n }\r\n\r\n try {\r\n setRemovingUserId(userId);\r\n setError(null);\r\n await groupsApi.removeMember(groupId, userId);\r\n await loadMembers();\r\n setSuccess(t('groups:members.removeSuccess', 'Membre retiré avec succès'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err: any) {\r\n console.error('Failed to remove member:', err);\r\n const errorMessage = err?.response?.data?.message || t('groups:members.removeError', 'Erreur lors du retrait du membre');\r\n setError(errorMessage);\r\n } finally {\r\n setRemovingUserId(null);\r\n }\r\n };\r\n\r\n // Filter available users (not already members)\r\n const availableUsers = allUsers?.filter(\r\n (u) => !members?.some((m) => m.userId === u.id)\r\n );\r\n\r\n // Filter by search query\r\n const filteredAvailableUsers = availableUsers?.filter((u) => {\r\n if (!searchQuery.trim()) return true;\r\n const query = searchQuery.toLowerCase().trim();\r\n return (\r\n u.fullName.toLowerCase().includes(query) ||\r\n u.email.toLowerCase().includes(query)\r\n );\r\n });\r\n\r\n const getInitials = (name: string) => {\r\n return name\r\n .split(' ')\r\n .map((part) => part.charAt(0))\r\n .slice(0, 2)\r\n .join('')\r\n .toUpperCase();\r\n };\r\n\r\n const getViewModeButtonClass = (isActive: boolean): string => {\r\n return isActive\r\n ? 'p-2 transition-colors bg-[var(--color-accent-500)] text-white'\r\n : 'p-2 transition-colors bg-[var(--bg-primary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]';\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:members.title', 'Membres du groupe')}\r\n {members && (\r\n <span className=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {members.length}\r\n </span>\r\n )}\r\n </h3>\r\n <div className=\"flex items-center gap-2\">\r\n {/* View mode toggle */}\r\n <div className=\"flex items-center rounded-lg border border-[var(--border-color)] overflow-hidden\">\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={getViewModeButtonClass(viewMode === 'table')}\r\n title={t('common.tableView', 'Vue tableau')}\r\n >\r\n <Table className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('card')}\r\n className={getViewModeButtonClass(viewMode === 'card')}\r\n title={t('common.cardView', 'Vue cartes')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n\r\n {!isSyncedFromEntra && (\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:members.add', 'Ajouter des membres')}\r\n </button>\r\n )}\r\n <button\r\n onClick={loadMembers}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common.refresh', 'Actualiser')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Alerts */}\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-red-500/10 border border-red-500/20 flex items-center gap-3\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-500 flex-shrink-0\" />\r\n <p className=\"text-red-500\">{error}</p>\r\n <button onClick={() => setError(null)} className=\"ml-auto\">\r\n <X className=\"w-4 h-4 text-red-500\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {success && (\r\n <div className=\"p-4 rounded-lg bg-green-500/10 border border-green-500/20 flex items-center gap-3\">\r\n <CheckCircle className=\"w-5 h-5 text-green-500 flex-shrink-0\" />\r\n <p className=\"text-green-500\">{success}</p>\r\n </div>\r\n )}\r\n\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-lg bg-blue-500/10 border border-blue-500/20\">\r\n <p className=\"text-sm text-blue-500\">\r\n {t('groups:members.info', 'Les membres de ce groupe héritent automatiquement des rôles et permissions attribués au groupe.')}\r\n </p>\r\n </div>\r\n\r\n {/* Entra sync warning */}\r\n {isSyncedFromEntra && (\r\n <div className=\"p-4 rounded-lg bg-amber-500/10 border border-amber-500/20 flex items-start gap-3\">\r\n <Info className=\"w-5 h-5 text-amber-500 flex-shrink-0 mt-0.5\" />\r\n <p className=\"text-sm text-amber-500\">\r\n {t('groups:members.readOnlyEntra', 'Les membres de ce groupe sont synchronisés depuis Microsoft Entra ID et ne peuvent pas être modifiés ici.')}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Content */}\r\n {loading && (\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 {!loading && (!members || members.length === 0) && (\r\n <div className=\"text-center py-12\">\r\n <Users className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)] mb-4\">\r\n {t('groups:members.noMembers', 'Ce groupe n\\'a aucun membre')}\r\n </p>\r\n {!isSyncedFromEntra && (\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:members.addFirst', 'Ajouter un premier membre')}\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n {!loading && (members?.length ?? 0) > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"overflow-x-auto rounded-[var(--radius-card)] border border-[var(--border-color)]\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-secondary)]\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.member', 'Membre')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.email', 'Email')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.addedAt', 'Ajouté le')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.addedBy', 'Par')}\r\n </th>\r\n {!isSyncedFromEntra && (\r\n <th className=\"px-4 py-3 text-right text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('common.actions', 'Actions')}\r\n </th>\r\n )}\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {members?.map((member) => (\r\n <tr\r\n key={member.userId}\r\n className=\"bg-[var(--bg-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <button\r\n className=\"flex items-center gap-3 cursor-pointer text-left bg-transparent border-0 p-0 hover:opacity-80 transition-opacity\"\r\n onClick={() => navigate(`/administration/users/${member.userId}`)}\r\n >\r\n <div className=\"w-8 h-8 rounded-full bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-xs font-medium text-[var(--color-accent-500)]\">\r\n {getInitials(member.fullName)}\r\n </span>\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)] hover:text-[var(--color-accent-500)]\">\r\n {member.fullName}\r\n </span>\r\n </button>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {member.email}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {new Date(member.addedAt).toLocaleDateString()}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {member.addedBy || '-'}\r\n </td>\r\n {!isSyncedFromEntra && (\r\n <td className=\"px-4 py-3 text-right\">\r\n <button\r\n onClick={() => handleRemoveMember(member.userId)}\r\n disabled={removingUserId === member.userId}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingUserId === member.userId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </td>\r\n )}\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n {!loading && (members?.length ?? 0) > 0 && viewMode !== 'table' && (\r\n /* Card View */\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {members?.map((member) => (\r\n <div\r\n key={member.userId}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <button\r\n className=\"flex items-start gap-3 min-w-0 cursor-pointer text-left bg-transparent border-0 p-0 hover:opacity-80 transition-opacity\"\r\n onClick={() => navigate(`/administration/users/${member.userId}`)}\r\n >\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)]\">\r\n {getInitials(member.fullName)}\r\n </span>\r\n </div>\r\n <div className=\"min-w-0\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </h4>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{member.email}</p>\r\n </div>\r\n </button>\r\n </div>\r\n\r\n <div className=\"mt-3 pt-3 border-t border-[var(--border-color)] space-y-1\">\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:members.addedAt', 'Ajouté le')}: {new Date(member.addedAt).toLocaleDateString()}\r\n </p>\r\n {member.addedBy && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:members.addedBy', 'Par')}: {member.addedBy}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {!isSyncedFromEntra && (\r\n <div className=\"mt-3 flex justify-end\">\r\n <button\r\n onClick={() => handleRemoveMember(member.userId)}\r\n disabled={removingUserId === member.userId}\r\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingUserId === member.userId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Add Member Modal */}\r\n {showAddModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-lg mx-4 bg-[var(--bg-primary)] rounded-[var(--radius-card)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <div>\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('groups:members.addModalTitle', 'Ajouter des membres au groupe')}\r\n </h3>\r\n {selectedUserIds.size > 0 && (\r\n <p className=\"text-sm text-[var(--color-accent-500)] mt-1\">\r\n {t('groups:members.selectedCount', { count: selectedUserIds.size })}\r\n </p>\r\n )}\r\n </div>\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedUserIds(new Set());\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"p-4 space-y-4\">\r\n {/* Search */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('groups:members.searchPlaceholder', 'Rechercher un utilisateur...')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-lg 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 autoFocus\r\n />\r\n </div>\r\n\r\n {/* User List */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {!filteredAvailableUsers || filteredAvailableUsers.length === 0 ? (\r\n <div className=\"text-center py-8\">\r\n <Users className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('groups:members.noAvailableUsers', 'Aucun utilisateur disponible')}\r\n </p>\r\n </div>\r\n ) : (\r\n filteredAvailableUsers.map((user) => {\r\n const isSelected = selectedUserIds.has(user.id);\r\n return (\r\n <button\r\n key={user.id}\r\n onClick={() => toggleUserSelection(user.id)}\r\n disabled={isAddingMultiple}\r\n className={`w-full flex items-center gap-3 p-3 rounded-lg border transition-colors text-left disabled:opacity-50 ${\r\n isSelected\r\n ? 'border-[var(--color-accent-500)] bg-[var(--color-accent-500)]/10'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n {/* Checkbox indicator */}\r\n <div\r\n className={`w-5 h-5 rounded border-2 flex items-center justify-center flex-shrink-0 transition-colors ${\r\n isSelected\r\n ? 'border-[var(--color-accent-500)] bg-[var(--color-accent-500)]'\r\n : 'border-[var(--border-color)]'\r\n }`}\r\n >\r\n {isSelected && <Check className=\"w-3 h-3 text-white\" />}\r\n </div>\r\n\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)]\">\r\n {getInitials(user.fullName)}\r\n </span>\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {user.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{user.email}</p>\r\n </div>\r\n </button>\r\n );\r\n })\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex justify-between items-center gap-2 p-4 border-t border-[var(--border-color)]\">\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n {selectedUserIds.size > 0 && (\r\n <button\r\n onClick={() => setSelectedUserIds(new Set())}\r\n className=\"text-[var(--color-accent-500)] hover:underline\"\r\n >\r\n {t('common.clearSelection', 'Effacer la sélection')}\r\n </button>\r\n )}\r\n </div>\r\n <div className=\"flex gap-2\">\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedUserIds(new Set());\r\n }}\r\n className=\"px-4 py-2 rounded-lg bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel', 'Annuler')}\r\n </button>\r\n <button\r\n onClick={handleAddMultipleMembers}\r\n disabled={selectedUserIds.size === 0 || isAddingMultiple}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n {isAddingMultiple ? (\r\n <>\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n {t('common.adding', 'Ajout...')}\r\n </>\r\n ) : (\r\n <>\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:members.addSelected', { count: selectedUserIds.size })}\r\n </>\r\n )}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useCallback } from 'react';\r\nimport { adminApi } from '@/services/api/adminApi';\r\nimport { groupsApi } from '@/services/api/groupsApi';\r\nimport type { RoleDto } from '@/services/api/adminApi';\r\nimport type { GroupDetailDto } from '@/services/api/groupsApi';\r\nimport { useEntityPermissions } from './useEntityPermissions';\r\nimport type { PermissionInheritanceInfo } from '@/components/platform/administration/permissions/types';\r\n\r\n/**\r\n * Extended RoleDto with tenant scope information from GroupRoleDto.\r\n */\r\nexport interface GroupRoleWithScope extends RoleDto {\r\n /** The tenant this role assignment is scoped to (null = global) */\r\n tenantId: string | null;\r\n /** The tenant name for display */\r\n tenantName: string | null;\r\n /** Whether this is a global role assignment */\r\n isGlobal: boolean;\r\n}\r\n\r\nexport interface UseGroupPermissionsOptions {\r\n groupId: string;\r\n /** Optional tenant context - when provided, loads tenant-scoped roles */\r\n tenantId?: string;\r\n}\r\n\r\nexport interface UseGroupPermissionsResult {\r\n loading: boolean;\r\n error: string | null;\r\n group: GroupDetailDto | null;\r\n groupRoles: GroupRoleWithScope[];\r\n resources: ReturnType<typeof useEntityPermissions>['resources'];\r\n assignments: ReturnType<typeof useEntityPermissions>['assignments'];\r\n inheritanceMap: ReturnType<typeof useEntityPermissions>['inheritanceMap'];\r\n effectivePermissions: ReturnType<typeof useEntityPermissions>['effectivePermissions'];\r\n filters: ReturnType<typeof useEntityPermissions>['filters'];\r\n filteredResources: ReturnType<typeof useEntityPermissions>['filteredResources'];\r\n applications: ReturnType<typeof useEntityPermissions>['applications'];\r\n modules: ReturnType<typeof useEntityPermissions>['modules'];\r\n updateFilters: ReturnType<typeof useEntityPermissions>['updateFilters'];\r\n getPermissionInheritance: (roleId: string, permissionId: string) => PermissionInheritanceInfo;\r\n getPermissionSources: (permissionId: string) => GroupRoleWithScope[];\r\n reloadData: () => Promise<void>;\r\n /** Whether we're in tenant-scoped mode */\r\n isTenantMode: boolean;\r\n}\r\n\r\nexport function useGroupPermissions(options: UseGroupPermissionsOptions): UseGroupPermissionsResult {\r\n const { groupId, tenantId } = options;\r\n\r\n const loadGroup = useCallback(async (id: string) => {\r\n return groupsApi.getById(id);\r\n }, []);\r\n\r\n const loadGroupRoles = useCallback(async (id: string, tid?: string): Promise<GroupRoleWithScope[]> => {\r\n const [groupData, matrixData] = await Promise.all([\r\n groupsApi.getById(id),\r\n adminApi.permissions.getMatrix(),\r\n ]);\r\n\r\n const matrixRoleMap = new Map(matrixData.roles.map(r => [r.id, r]));\r\n\r\n const allRoles: GroupRoleWithScope[] = groupData.roles\r\n .map(gr => {\r\n const matrixRole = matrixRoleMap.get(gr.roleId);\r\n if (!matrixRole) return null;\r\n\r\n return {\r\n id: gr.roleId,\r\n name: matrixRole.name,\r\n shortName: matrixRole.shortName || matrixRole.name,\r\n category: matrixRole.category || ('Custom' as const),\r\n description: matrixRole.description ?? null,\r\n tenantId: gr.tenantId ?? null,\r\n tenantName: gr.tenantName ?? null,\r\n isGlobal: gr.isGlobal,\r\n } as GroupRoleWithScope;\r\n })\r\n .filter((r): r is GroupRoleWithScope => r !== null);\r\n\r\n const rolesToUse = tid\r\n ? allRoles.filter(role => role.isGlobal || role.tenantId === tid)\r\n : allRoles;\r\n\r\n return rolesToUse;\r\n }, []);\r\n\r\n const baseResult = useEntityPermissions<GroupRoleWithScope, GroupDetailDto>({\r\n entityId: groupId,\r\n tenantId,\r\n loadEntity: loadGroup,\r\n loadRoles: loadGroupRoles,\r\n });\r\n\r\n const group = baseResult.entity;\r\n const groupRoles = baseResult.roles;\r\n\r\n const getPermissionSources = useCallback((permissionId: string): GroupRoleWithScope[] => {\r\n const sources: GroupRoleWithScope[] = [];\r\n\r\n groupRoles.forEach(role => {\r\n const roleInheritance = baseResult.inheritanceMap[role.id];\r\n if (roleInheritance) {\r\n const info = roleInheritance.get(permissionId);\r\n if (info && (info.isDirect || info.isInherited)) {\r\n sources.push(role);\r\n }\r\n }\r\n });\r\n\r\n return sources;\r\n }, [groupRoles, baseResult.inheritanceMap]);\r\n\r\n return {\r\n loading: baseResult.loading,\r\n error: baseResult.error,\r\n group,\r\n groupRoles,\r\n resources: baseResult.resources,\r\n assignments: baseResult.assignments,\r\n inheritanceMap: baseResult.inheritanceMap,\r\n effectivePermissions: baseResult.effectivePermissions,\r\n filters: baseResult.filters,\r\n filteredResources: baseResult.filteredResources,\r\n applications: baseResult.applications,\r\n modules: baseResult.modules,\r\n updateFilters: baseResult.updateFilters,\r\n getPermissionInheritance: baseResult.getPermissionInheritance,\r\n getPermissionSources,\r\n reloadData: baseResult.reloadData,\r\n isTenantMode: baseResult.isTenantMode,\r\n };\r\n}\r\n","import type { ReactElement } from 'react';\r\nimport React, { useState, useMemo, useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Check,\r\n Star,\r\n Eye,\r\n Ban,\r\n ChevronRight,\r\n ChevronDown,\r\n FolderOpen,\r\n Box,\r\n FileText,\r\n Shield,\r\n Info,\r\n Loader2,\r\n AlertCircle,\r\n Plus,\r\n Edit,\r\n Trash2,\r\n UserPlus,\r\n Play,\r\n Database,\r\n UserCheck,\r\n User,\r\n} from 'lucide-react';\r\nimport { useGroupPermissions } from '@/hooks/useGroupPermissions';\r\nimport { useCollapsibleState } from '@/hooks/useCollapsibleState';\r\nimport { groupByApplicationWithSections, calculatePermissionStatus, calculateModuleWithSectionsStatus, getPermissionCellBackground } from '@/utils/permissionUtils';\r\nimport { PermissionStatusIndicator } from './PermissionStatusIndicator';\r\nimport { PermissionPopover } from '../PermissionPopover';\r\nimport type { ResourceNode, PermissionStatus, PermissionInheritanceInfo } from './types';\r\nimport type { MatrixRoleDto } from '@/services/api/adminApi';\r\nimport type { GroupRoleWithScope } from '@/hooks/useGroupPermissions';\r\nimport { Globe, Building2 } from 'lucide-react';\r\nimport { createAdminApi } from '@/services/api/adminApi';\r\nimport { createGroupsApi } from '@/services/api/groupsApi';\r\n\r\n/** Helper: Get unique tenant badges from source roles */\r\nfunction getTenantBadgesFromRoles(sourceRoles: GroupRoleWithScope[]): Array<{ key: string; isGlobal: boolean; displayName: string | null }> {\r\n const tenantMap = new Map<string, { isGlobal: boolean; displayName: string | null }>();\r\n sourceRoles.forEach(role => {\r\n const key = role.isGlobal ? '__global__' : (role.tenantId || '__unknown__');\r\n if (!tenantMap.has(key)) {\r\n tenantMap.set(key, { isGlobal: role.isGlobal, displayName: role.tenantName });\r\n }\r\n });\r\n return Array.from(tenantMap.entries()).map(([key, data]) => ({\r\n key,\r\n isGlobal: data.isGlobal,\r\n displayName: data.displayName,\r\n }));\r\n}\r\n\r\n/** Helper: Get unique source types from roles */\r\nfunction getSourceTypesFromRoles(\r\n sourceRoles: GroupRoleWithScope[],\r\n isCustomRoleFn: (name: string) => boolean\r\n): Array<{ type: 'Direct' | 'Custom' }> {\r\n const sources: Array<{ type: 'Direct' | 'Custom' }> = [];\r\n sourceRoles.forEach(role => {\r\n const type = isCustomRoleFn(role.name) ? 'Custom' : 'Direct';\r\n if (!sources.find(s => s.type === type)) {\r\n sources.push({ type });\r\n }\r\n });\r\n return sources;\r\n}\r\n\r\nconst ACTION_ICONS: Record<string, React.ReactNode> = {\r\n '*': <Shield className=\"h-3.5 w-3.5\" />,\r\n read: <Eye className=\"h-3.5 w-3.5\" />,\r\n create: <Plus className=\"h-3.5 w-3.5\" />,\r\n update: <Edit className=\"h-3.5 w-3.5\" />,\r\n delete: <Trash2 className=\"h-3.5 w-3.5\" />,\r\n assign: <UserPlus className=\"h-3.5 w-3.5\" />,\r\n execute: <Play className=\"h-3.5 w-3.5\" />,\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\ninterface GroupPermissionMatrixProps {\r\n readonly groupId: string;\r\n readonly compact?: boolean;\r\n readonly tenantId?: string;\r\n readonly tenantSlug?: string;\r\n}\r\n\r\nexport function GroupPermissionMatrix({ groupId, compact = false, tenantId, tenantSlug }: GroupPermissionMatrixProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const {\r\n loading,\r\n error,\r\n group,\r\n groupRoles,\r\n filteredResources,\r\n effectivePermissions,\r\n filters,\r\n applications,\r\n modules,\r\n updateFilters,\r\n getPermissionSources,\r\n reloadData,\r\n isTenantMode,\r\n } = useGroupPermissions({ groupId, tenantId });\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 const [customRoleId, setCustomRoleId] = useState<string | null>(null);\r\n const [customRolePermissions, setCustomRolePermissions] = useState<Set<string>>(new Set());\r\n const [togglingPermission, setTogglingPermission] = useState<string | null>(null);\r\n const [loadingCustomRole, setLoadingCustomRole] = useState(false);\r\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\r\n\r\n // Create tenant-aware API instances\r\n const adminApi = useMemo(() => createAdminApi(tenantSlug), [tenantSlug]);\r\n const groupsApi = useMemo(() => createGroupsApi(tenantSlug), [tenantSlug]);\r\n\r\n React.useEffect(() => {\r\n const loadCustomRole = async () => {\r\n try {\r\n setLoadingCustomRole(true);\r\n const role = await groupsApi.getCustomRole(groupId);\r\n if (role) {\r\n setCustomRoleId(role.id);\r\n setCustomRolePermissions(new Set((role.permissions ?? []).map(p => p.id)));\r\n } else {\r\n setCustomRoleId(null);\r\n setCustomRolePermissions(new Set());\r\n }\r\n } catch (err) {\r\n if (!(err instanceof Error && err.message.includes('404'))) {\r\n console.error('Failed to load custom role:', err);\r\n }\r\n setCustomRoleId(null);\r\n setCustomRolePermissions(new Set());\r\n } finally {\r\n setLoadingCustomRole(false);\r\n }\r\n };\r\n loadCustomRole();\r\n }, [groupId, groupsApi]);\r\n\r\n const handleTogglePermission = async (permissionId: string) => {\r\n // Prevent concurrent toggles (F5 fix)\r\n if (togglingPermission !== null) {\r\n return;\r\n }\r\n\r\n try {\r\n setTogglingPermission(permissionId);\r\n setErrorMessage(null);\r\n let roleId = customRoleId;\r\n let currentPermissions = new Set(customRolePermissions);\r\n\r\n if (!roleId) {\r\n const newRole = await groupsApi.createCustomRole(groupId);\r\n roleId = newRole.id;\r\n setCustomRoleId(roleId);\r\n currentPermissions = new Set();\r\n }\r\n\r\n const newPermissions = new Set(currentPermissions);\r\n if (newPermissions.has(permissionId)) {\r\n newPermissions.delete(permissionId);\r\n } else {\r\n newPermissions.add(permissionId);\r\n }\r\n\r\n const role = await adminApi.roles.getById(roleId);\r\n await adminApi.roles.update(roleId, {\r\n name: role.name,\r\n shortName: role.shortName || undefined,\r\n category: role.category || undefined,\r\n description: role.description || undefined,\r\n permissionIds: Array.from(newPermissions),\r\n });\r\n\r\n setCustomRolePermissions(newPermissions);\r\n await reloadData();\r\n } catch (err) {\r\n console.error('Failed to toggle permission:', err);\r\n // F7 fix: Show user-friendly error message\r\n setErrorMessage(t('groupPermissions.toggleError', 'Erreur lors de la modification de la permission. Veuillez réessayer.'));\r\n // Clear error after 5 seconds\r\n setTimeout(() => setErrorMessage(null), 5000);\r\n } finally {\r\n setTogglingPermission(null);\r\n }\r\n };\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 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 const getAllPermissionsForResource = useCallback((resource: ResourceNode) => {\r\n const allPermissions = [...resource.permissions];\r\n if (resource.childSections) {\r\n resource.childSections.forEach(section => {\r\n allPermissions.push(...section.permissions);\r\n });\r\n }\r\n return allPermissions;\r\n }, []);\r\n\r\n const getPermissionStatusForGroup = useCallback((resource: ResourceNode, isSection: boolean = false): { status: PermissionStatus; grantedCount: number } => {\r\n if (isSection) {\r\n return calculatePermissionStatus(resource, (permId) => effectivePermissions.has(permId));\r\n }\r\n\r\n const allPermissions = getAllPermissionsForResource(resource);\r\n const grantedCount = allPermissions.filter(p => effectivePermissions.has(p.id)).length;\r\n const totalCount = allPermissions.length;\r\n\r\n let status: PermissionStatus;\r\n if (grantedCount === 0) {\r\n status = 'none';\r\n } else if (grantedCount === totalCount) {\r\n status = 'all';\r\n } else {\r\n const hasOnlyRead = allPermissions.every(p =>\r\n !effectivePermissions.has(p.id) || p.action === 'read'\r\n ) && allPermissions.some(p => p.action === 'read' && effectivePermissions.has(p.id));\r\n status = hasOnlyRead ? 'read-only' : 'some';\r\n }\r\n\r\n return { status, grantedCount };\r\n }, [effectivePermissions, getAllPermissionsForResource]);\r\n\r\n type GroupedApp = ReturnType<typeof groupByApplicationWithSections>[0];\r\n\r\n const filterModulesByStatus = (modules: GroupedApp['modules']) => {\r\n return modules.filter((m: GroupedApp['modules'][0]) => {\r\n const { status } = calculateModuleWithSectionsStatus(m.module, m.sections, (permId) => effectivePermissions.has(permId));\r\n return statusFilters.has(status);\r\n });\r\n };\r\n\r\n const applyStatusFilters = (grouped: ReturnType<typeof groupByApplicationWithSections>) => {\r\n if (statusFilters.size === 0) return grouped;\r\n return grouped.map(appGroup => ({\r\n ...appGroup,\r\n modules: filterModulesByStatus(appGroup.modules)\r\n })).filter(g => g.modules.length > 0);\r\n };\r\n\r\n const groupedResources = useMemo(() => {\r\n let grouped = groupByApplicationWithSections(filteredResources);\r\n return applyStatusFilters(grouped);\r\n }, [filteredResources, statusFilters, effectivePermissions]);\r\n\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 addUniqueSourceRole = (sourceRoles: GroupRoleWithScope[], role: GroupRoleWithScope) => {\r\n if (!sourceRoles.find(r => r.id === role.id && r.tenantId === role.tenantId)) {\r\n sourceRoles.push(role);\r\n }\r\n };\r\n\r\n const getSourceRolesForResource = (resource: ResourceNode): GroupRoleWithScope[] => {\r\n const sourceRoles: GroupRoleWithScope[] = [];\r\n resource.permissions.forEach(perm => {\r\n if (effectivePermissions.has(perm.id)) {\r\n getPermissionSources(perm.id).forEach(role => {\r\n addUniqueSourceRole(sourceRoles, role);\r\n });\r\n }\r\n });\r\n return sourceRoles;\r\n };\r\n\r\n const isCustomRole = (roleName: string): boolean => {\r\n return roleName.startsWith('group_') && roleName.endsWith('_custom');\r\n };\r\n\r\n const getDisplayName = (role: GroupRoleWithScope): string => {\r\n return isCustomRole(role.name) ? t('groupPermissions.customBadge', 'Custom') : (role.shortName || role.name);\r\n };\r\n\r\n const groupAsRole: MatrixRoleDto | null = useMemo(() => {\r\n if (!group) return null;\r\n return {\r\n id: customRoleId || `group_${groupId}_custom`,\r\n name: group.name,\r\n shortName: group.name,\r\n category: 'Custom' as const,\r\n description: null,\r\n isSystem: false,\r\n permissions: [],\r\n permissionIds: [],\r\n };\r\n }, [group, customRoleId, groupId]);\r\n\r\n const getGroupPermissionInheritance = useCallback((_roleId: string, permissionId: string): PermissionInheritanceInfo => {\r\n const isGranted = effectivePermissions.has(permissionId);\r\n const isFromCustomRole = customRolePermissions.has(permissionId);\r\n const sourceRoles = isGranted ? getPermissionSources(permissionId) : [];\r\n const inheritedRole = sourceRoles.find(r => !isCustomRole(r.name));\r\n\r\n return {\r\n isDirect: isFromCustomRole,\r\n isInherited: isGranted && !isFromCustomRole && sourceRoles.length > 0,\r\n inheritedFromPath: inheritedRole ? inheritedRole.name : undefined,\r\n inheritedFromId: inheritedRole?.id,\r\n };\r\n }, [effectivePermissions, customRolePermissions, getPermissionSources]);\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <Loader2 className=\"h-8 w-8 animate-spin text-[var(--color-accent-500)]\" />\r\n <span className=\"ml-3 text-[var(--text-secondary)]\">{t('groupPermissions.loading', 'Chargement des permissions...')}</span>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--error-bg)] p-4 border border-[var(--error-border)]\">\r\n <div className=\"flex items-center\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <p className=\"ml-2 text-sm text-[var(--error-text)]\">{error}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!group) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n <Shield className=\"h-12 w-12 mx-auto mb-4 text-[var(--text-muted)]\" />\r\n <p>{t('groupPermissions.noGroup', 'Groupe non trouvé')}</p>\r\n </div>\r\n );\r\n }\r\n\r\n const getPaddingClass = (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 getResourceIcon = (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 getResourceLabelClass = (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 renderResourceRows = (resources: ResourceNode[], baseIndex: number) => {\r\n return resources.map((resource, idx) =>\r\n renderResourceRow(resource, baseIndex + idx, 'resource', false, false)\r\n );\r\n };\r\n\r\n const renderSectionRow = (\r\n sectionWithResources: ReturnType<typeof groupByApplicationWithSections>[0]['modules'][0]['sections'][0],\r\n moduleIndex: number,\r\n sectionIndex: number\r\n ) => {\r\n const { section, resources } = sectionWithResources;\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 {renderResourceRow(section, moduleIndex + sectionIndex + 1, 'section', hasResources, isSectionCollapsed)}\r\n {hasResources && !isSectionCollapsed && renderResourceRows(resources, moduleIndex + sectionIndex + 2)}\r\n </React.Fragment>\r\n );\r\n };\r\n\r\n const renderSectionRows = (\r\n sections: ReturnType<typeof groupByApplicationWithSections>[0]['modules'][0]['sections'],\r\n moduleIndex: number,\r\n hasSections: boolean,\r\n isModuleCollapsed: boolean\r\n ) => {\r\n if (!hasSections || isModuleCollapsed) return null;\r\n return sections.map((sectionWithResources, sectionIndex) =>\r\n renderSectionRow(sectionWithResources, moduleIndex, sectionIndex)\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 isSection = level === 'section';\r\n const { status, grantedCount } = getPermissionStatusForGroup(resource, isSection);\r\n const totalCount = isSection ? resource.permissions.length : getAllPermissionsForResource(resource).length;\r\n const cellBg = getPermissionCellBackground(status);\r\n const sourceRoles = getSourceRolesForResource(resource);\r\n const isPopoverOpen = openPopover === resource.id;\r\n const paddingLeft = getPaddingClass(level);\r\n\r\n return (\r\n <tr\r\n key={resource.id}\r\n className={`hover:bg-[var(--bg-hover)] ${rowIndex % 2 === 0 ? 'item-light' : 'item-medium'}`}\r\n >\r\n <td\r\n className={`sticky left-0 z-10 ${rowIndex % 2 === 0 ? 'item-light' : 'item-medium'} 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 {hasChildren && (\r\n <button\r\n onClick={() => level === 'module' ? toggleModule(resource.id) : toggleSection(resource.id)}\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 {getResourceIcon(level)}\r\n <span className={`text-sm ${getResourceLabelClass(level)}`}>\r\n {resource.label}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n ({totalCount})\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 type=\"button\"\r\n onClick={() => handleCellClick(resource.id)}\r\n className={`w-full h-full min-h-[36px] flex items-center justify-center rounded transition-colors hover:opacity-80 ${\r\n isPopoverOpen ? 'ring-2 ring-[var(--color-accent-500)]' : ''\r\n }`}\r\n title={`${resource.label}: ${grantedCount}/${totalCount}`}\r\n >\r\n <PermissionStatusIndicator\r\n status={status}\r\n grantedCount={grantedCount}\r\n totalCount={totalCount}\r\n />\r\n </button>\r\n {isPopoverOpen && group && groupAsRole && (\r\n <PermissionPopover\r\n mode=\"editable\"\r\n role={groupAsRole}\r\n resource={resource}\r\n onClose={() => setOpenPopover(null)}\r\n onTogglePermission={handleTogglePermission}\r\n getPermissionInheritance={getGroupPermissionInheritance}\r\n />\r\n )}\r\n </td>\r\n\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ width: '140px', minWidth: '140px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1\">\r\n {sourceRoles.length > 0 ? (\r\n sourceRoles.map(role => {\r\n const isCustom = isCustomRole(role.name);\r\n const displayName = getDisplayName(role);\r\n const scopeIcon = role.isGlobal ? (\r\n <Globe className=\"h-2.5 w-2.5 text-[var(--info-text)]\" />\r\n ) : (\r\n <Building2 className=\"h-2.5 w-2.5 text-[var(--warning-text)]\" />\r\n );\r\n const scopeTitle = role.isGlobal\r\n ? t('groupPermissions.globalScope', 'Global')\r\n : role.tenantName || t('groupPermissions.tenantScope', 'Tenant');\r\n return (\r\n <button\r\n key={`${role.id}-${role.tenantId || 'global'}`}\r\n onClick={() => !isCustom && navigate(`/administration/permissions/roles/${role.id}`)}\r\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full transition-all ${\r\n isCustom\r\n ? 'bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)] border border-[var(--color-accent-300)] dark:border-[var(--color-accent-700)] cursor-default'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)] border border-[var(--border-color)] cursor-pointer hover:ring-1 hover:ring-[var(--color-accent-500)] hover:shadow-sm'\r\n }`}\r\n title={`${isCustom ? t('groupPermissions.customRoleTooltip', 'Rôle personnalisé') : t('groupPermissions.clickToViewRole', 'Cliquer pour voir le rôle')} (${scopeTitle})`}\r\n >\r\n {scopeIcon}\r\n {displayName}\r\n {isCustom && <Star className=\"h-3 w-3\" />}\r\n </button>\r\n );\r\n })\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n </div>\r\n </td>\r\n\r\n {/* Tenant Column */}\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ width: '120px', minWidth: '120px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1\">\r\n {sourceRoles.length > 0 ? (\r\n getTenantBadgesFromRoles(sourceRoles).map(({ key, isGlobal, displayName }) => (\r\n <span\r\n key={key}\r\n className={`inline-flex items-center px-2 py-0.5 text-xs rounded-full ${\r\n isGlobal\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)] border border-[var(--border-color)]'\r\n }`}\r\n >\r\n {isGlobal\r\n ? t('groupPermissions.globalScope', 'Global')\r\n : (displayName || t('groupPermissions.tenantScope', 'Tenant'))}\r\n </span>\r\n ))\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n </div>\r\n </td>\r\n\r\n {/* Source Column */}\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ width: '100px', minWidth: '100px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1\">\r\n {sourceRoles.length > 0 ? (\r\n getSourceTypesFromRoles(sourceRoles, isCustomRole).map((source, idx) => (\r\n <span\r\n key={`source-${source.type}-${idx}`}\r\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full ${\r\n source.type === 'Direct'\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)]'\r\n : 'bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)] border border-[var(--color-accent-300)] dark:border-[var(--color-accent-700)]'\r\n }`}\r\n title={source.type === 'Custom'\r\n ? t('groupPermissions.customPermissions', 'Permissions personnalisées')\r\n : t('groupPermissions.directAssignmentTooltip', 'Rôle assigné directement au groupe')}\r\n >\r\n {source.type === 'Direct' && <UserCheck className=\"h-3 w-3\" />}\r\n {source.type === 'Custom' && <User className=\"h-3 w-3\" />}\r\n {source.type === 'Direct'\r\n ? t('groupPermissions.directAssignment', 'Direct')\r\n : t('groupPermissions.customSource', 'Custom')}\r\n </span>\r\n ))\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n </div>\r\n </td>\r\n\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ minWidth: '200px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1.5 items-center relative\">\r\n {resource.permissions\r\n .filter(perm => effectivePermissions.has(perm.id))\r\n .map(perm => {\r\n const isFromCustomRole = customRolePermissions.has(perm.id);\r\n const isToggling = togglingPermission === perm.id;\r\n const actionColor = ACTION_COLORS[perm.action] || 'bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)]';\r\n const icon = ACTION_ICONS[perm.action] || <Eye className=\"h-3.5 w-3.5\" />;\r\n\r\n return (\r\n <button\r\n key={perm.id}\r\n onClick={() => handleTogglePermission(perm.id)}\r\n disabled={isToggling || loadingCustomRole || !isFromCustomRole}\r\n className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-[var(--radius-badge)] border text-xs font-medium transition-all ${actionColor} ${\r\n isFromCustomRole ? 'ring-2 ring-[var(--color-accent-600)] dark:ring-[var(--color-accent-400)] hover:opacity-80 cursor-pointer' : 'opacity-60 cursor-not-allowed'\r\n } disabled:opacity-50`}\r\n title={isFromCustomRole ? t('groupPermissions.clickToRemove', 'Cliquer pour retirer') : t('groupPermissions.grantedByRole', 'Accordé par un rôle')}\r\n >\r\n {isToggling ? (\r\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\r\n ) : (\r\n icon\r\n )}\r\n <span className=\"capitalize\">\r\n {t(`assignments.actions.${perm.action === '*' ? 'all' : perm.action}.label`)}\r\n </span>\r\n {isFromCustomRole && <Star className=\"h-3 w-3\" />}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n };\r\n\r\n return (\r\n <div>\r\n {!compact && (\r\n <>\r\n {/* Flex container: sidebar filters + content aligned at top */}\r\n <div className=\"flex flex-col lg:flex-row lg:items-start lg:gap-6\">\r\n <div className=\"w-full lg:w-72 lg:flex-shrink-0 space-y-4 mb-4 lg:mb-0 lg:sticky lg:top-4\">\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)] mb-3\">\r\n {t('groupPermissions.filters.title', 'Filtres')}\r\n </h4>\r\n\r\n <div className=\"space-y-3\">\r\n <div className=\"space-y-1\">\r\n <label className=\"text-xs text-[var(--text-secondary)]\">\r\n {t('groupPermissions.filters.application', 'Application')}\r\n </label>\r\n <select\r\n value={filters.applicationFilter}\r\n onChange={(e) => updateFilters({ applicationFilter: e.target.value, moduleFilter: 'all' })}\r\n className=\"w-full px-3 py-1.5 text-sm bg-[var(--bg-primary)] 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('groupPermissions.filters.allApplications', 'Toutes les applications')}</option>\r\n {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=\"space-y-1\">\r\n <label className=\"text-xs text-[var(--text-secondary)]\">\r\n {t('groupPermissions.filters.module', 'Module')}\r\n </label>\r\n <select\r\n value={filters.moduleFilter}\r\n onChange={(e) => updateFilters({ moduleFilter: e.target.value })}\r\n className=\"w-full px-3 py-1.5 text-sm bg-[var(--bg-primary)] 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('groupPermissions.filters.allModules', 'Tous les modules')}</option>\r\n {modules\r\n .filter(mod =>\r\n (filters.applicationFilter === 'all' || mod.app === filters.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 <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <span className=\"text-xs font-medium text-[var(--text-secondary)] block mb-2\">\r\n {t('groupPermissions.filterByStatus', 'Filtrer par statut')}\r\n </span>\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n <button\r\n onClick={() => toggleStatusFilter('all')}\r\n className={`inline-flex items-center gap-1 px-2 py-1 text-xs 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 w-3 ${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 px-2 py-1 text-xs 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 w-3 ${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 px-2 py-1 text-xs 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 w-3 ${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 px-2 py-1 text-xs 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 w-3 ${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=\"mt-2 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 <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\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 </div>\r\n\r\n {/* Role badges */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)] mb-3\">\r\n {t('groupPermissions.assignedRoles', 'Rôles assignés')}\r\n </h4>\r\n {groupRoles.length > 0 ? (\r\n <div className=\"flex flex-wrap gap-2\">\r\n {groupRoles.map(role => {\r\n const isCustom = isCustomRole(role.name);\r\n const scopeIcon = role.isGlobal ? (\r\n <Globe className=\"h-3 w-3 text-[var(--info-text)]\" />\r\n ) : (\r\n <Building2 className=\"h-3 w-3 text-[var(--warning-text)]\" />\r\n );\r\n const scopeLabel = role.isGlobal\r\n ? t('groupPermissions.globalScope', 'Global')\r\n : role.tenantName || t('groupPermissions.tenantScope', 'Tenant');\r\n return (\r\n <div key={`${role.id}-${role.tenantId || 'global'}`} className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => !isCustom && navigate(`/administration/permissions/roles/${role.id}`)}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)] transition-all ${\r\n isCustom ? 'cursor-default' : 'cursor-pointer hover:ring-2 hover:ring-[var(--color-accent-500)] hover:shadow-md'\r\n }`}\r\n title={isCustom ? t('groupPermissions.customRoleTooltip', 'Rôle personnalisé') : t('groupPermissions.clickToViewRole', 'Cliquer pour voir le rôle')}\r\n >\r\n <Shield className=\"h-3.5 w-3.5\" />\r\n {role.shortName || role.name}\r\n </button>\r\n <span\r\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full ${\r\n role.isGlobal\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]'\r\n : 'bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]'\r\n }`}\r\n title={role.isGlobal\r\n ? t('groupPermissions.globalScopeTooltip', 'Ce rôle s\\'applique à tous les tenants')\r\n : t('groupPermissions.tenantScopeTooltip', 'Ce rôle s\\'applique uniquement à ce tenant: {{tenant}}', { tenant: role.tenantName })}\r\n >\r\n {scopeIcon}\r\n <span className=\"hidden sm:inline\">{scopeLabel}</span>\r\n </span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n ) : (\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--text-muted)]\">\r\n <Info className=\"h-4 w-4\" />\r\n <span>{t('groupPermissions.noRolesInfo', 'Ce groupe n\\'a aucun rôle.')}</span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Info messages */}\r\n {isTenantMode && (\r\n <div className=\"flex items-center gap-2 p-3 rounded-[var(--radius-card)] bg-[var(--accent-bg)] border border-[var(--accent-border)]\">\r\n <Shield className=\"h-4 w-4 text-[var(--accent-text)]\" />\r\n <span className=\"text-sm text-[var(--accent-text)]\">\r\n {t('groupPermissions.tenantModeInfo', 'Affichage des permissions dans le contexte du tenant.')}\r\n </span>\r\n </div>\r\n )}\r\n\r\n {errorMessage && (\r\n <div className=\"flex items-center gap-2 p-3 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <AlertCircle className=\"h-4 w-4 text-[var(--error-text)]\" />\r\n <span className=\"text-sm text-[var(--error-text)]\">{errorMessage}</span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Permissions table */}\r\n <div className=\"flex-1 min-w-0\">\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('groupPermissions.status', 'Statut')}\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={{ width: '140px', minWidth: '140px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('groupPermissions.sourceRoles', 'Rôles sources')}\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={{ width: '120px', minWidth: '120px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('groupPermissions.tenant', 'Tenant')}\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={{ width: '100px', minWidth: '100px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('groupPermissions.source', 'Source')}\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={{ minWidth: '200px', 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 <tr className=\"bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\">\r\n <td\r\n className=\"sticky left-0 z-10 px-3 py-3 bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\"\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-5 w-5 text-[var(--color-accent-400)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n )}\r\n <FolderOpen className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n <span className=\"text-sm font-bold text-[var(--color-accent-300)] uppercase tracking-wider\">\r\n {appGroup.application}\r\n </span>\r\n <span className=\"text-xs text-[var(--color-accent-400)] 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 colSpan={5} className=\"px-0 py-3\" />\r\n </tr>\r\n\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 {renderResourceRow(module, moduleIndex, 'module', hasSections, isModuleCollapsed)}\r\n {renderSectionRows(sections, moduleIndex, hasSections, isModuleCollapsed)}\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 </div>\r\n </>\r\n )}\r\n\r\n {compact && (\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 scope=\"col\" className=\"sticky left-0 z-20 item-medium px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '280px', minWidth: '280px', maxWidth: '280px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('assignments.resource')}\r\n </th>\r\n <th scope=\"col\" className=\"px-2 text-center text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '60px', minWidth: '60px', maxWidth: '60px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.status', 'Statut')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '140px', minWidth: '140px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.sourceRoles', 'Rôles sources')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '120px', minWidth: '120px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.tenant', 'Tenant')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '100px', minWidth: '100px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.source', 'Source')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ minWidth: '200px', height: '48px', verticalAlign: 'middle' }}>\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 <React.Fragment key={appGroup.application}>\r\n {appGroup.modules.map((moduleWithSections, moduleIndex) => (\r\n <React.Fragment key={moduleWithSections.module.id}>\r\n {renderResourceRow(moduleWithSections.module, moduleIndex, 'module', false, false)}\r\n </React.Fragment>\r\n ))}\r\n </React.Fragment>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport * as LucideIcons from 'lucide-react';\r\nimport {\r\n Boxes,\r\n Loader2,\r\n ChevronDown,\r\n ChevronRight,\r\n Shield,\r\n Key,\r\n Layers,\r\n RefreshCw,\r\n} from 'lucide-react';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport { groupsApi } from '@/services/api/groupsApi';\r\nimport type { UserApplicationAccessDto } from '@/services/api/adminApi';\r\n\r\ninterface GroupApplicationsTabProps {\r\n readonly groupId: string;\r\n readonly tenantId?: string;\r\n}\r\n\r\nexport function GroupApplicationsTab({ groupId, tenantId }: GroupApplicationsTabProps): ReactElement {\r\n const { t } = useTranslation(['groups', 'admin']);\r\n const [applications, setApplications] = useState<UserApplicationAccessDto[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [expandedApps, setExpandedApps] = useState<Set<string>>(new Set());\r\n\r\n const loadApplicationAccess = useCallback(async () => {\r\n setLoading(true);\r\n try {\r\n const data = await groupsApi.getApplicationAccess(groupId, tenantId);\r\n setApplications(data);\r\n } catch {\r\n setApplications([]);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [groupId, tenantId]);\r\n\r\n useEffect(() => {\r\n void loadApplicationAccess();\r\n }, [loadApplicationAccess]);\r\n\r\n const toggleExpand = (appId: string) => {\r\n setExpandedApps(prev => {\r\n const next = new Set(prev);\r\n if (next.has(appId)) next.delete(appId);\r\n else next.add(appId);\r\n return next;\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 <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 (applications.length === 0) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n <Boxes className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('groups:applications.noAccess')}</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\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('groups:applications.title')}\r\n </h3>\r\n <button\r\n onClick={() => void loadApplicationAccess()}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]\"\r\n title={t('admin:common.refresh', 'Refresh')}\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n {applications.map(app => (\r\n <ApplicationCard\r\n key={app.applicationId}\r\n app={app}\r\n isExpanded={expandedApps.has(app.applicationId)}\r\n onToggle={() => toggleExpand(app.applicationId)}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nfunction ApplicationCard({\r\n app,\r\n isExpanded,\r\n onToggle,\r\n}: {\r\n app: UserApplicationAccessDto;\r\n isExpanded: boolean;\r\n onToggle: () => void;\r\n}) {\r\n const { t } = useTranslation(['groups', 'admin']);\r\n const icons = LucideIcons as unknown as Record<string, LucideIcon>;\r\n const AppIcon = app.icon ? icons[app.icon] : null;\r\n\r\n const permissionsByModule = useMemo(() => {\r\n const groups: Record<string, { moduleName: string; permissions: typeof app.permissions }> = {};\r\n for (const perm of app.permissions) {\r\n const key = perm.moduleName || '_global';\r\n if (!groups[key]) {\r\n groups[key] = { moduleName: perm.moduleName || t('groups:applications.globalPermissions'), permissions: [] };\r\n }\r\n groups[key].permissions.push(perm);\r\n }\r\n return Object.values(groups);\r\n }, [app.permissions, t]);\r\n\r\n return (\r\n <div className=\"border border-[var(--border-color)] rounded-[var(--radius-card)] bg-[var(--bg-card)] overflow-hidden\">\r\n <button\r\n onClick={onToggle}\r\n className=\"w-full flex items-center gap-3 p-4 text-left hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {isExpanded ? (\r\n <ChevronDown className=\"w-4 h-4 text-[var(--text-muted)] flex-shrink-0\" />\r\n ) : (\r\n <ChevronRight className=\"w-4 h-4 text-[var(--text-muted)] flex-shrink-0\" />\r\n )}\r\n\r\n <div className=\"w-9 h-9 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n {AppIcon ? (\r\n <AppIcon className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n ) : (\r\n <Layers className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n )}\r\n </div>\r\n\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"font-medium text-[var(--text-primary)] truncate\">{app.applicationLabel}</p>\r\n <p className=\"text-xs text-[var(--text-muted)] truncate\">{app.applicationCode}</p>\r\n </div>\r\n\r\n {app.hasFullAccess ? (\r\n <span className=\"px-2.5 py-1 text-xs font-medium rounded-full bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)] flex-shrink-0\">\r\n {t('groups:applications.fullAccess')}\r\n </span>\r\n ) : (\r\n <span className=\"px-2.5 py-1 text-xs font-medium rounded-full bg-[var(--color-accent-500)]/10 text-[var(--color-accent-600)] border border-[var(--color-accent-500)]/20 flex-shrink-0\">\r\n {t('groups:applications.permissionCount', { count: app.permissions.length })}\r\n </span>\r\n )}\r\n\r\n <span className=\"text-xs text-[var(--text-muted)] flex items-center gap-1 flex-shrink-0\">\r\n <Shield className=\"w-3.5 h-3.5\" />\r\n {app.roles.length}\r\n </span>\r\n </button>\r\n\r\n {isExpanded && (\r\n <div className=\"border-t border-[var(--border-color)] p-4 space-y-4 bg-[var(--bg-secondary)]\">\r\n <div>\r\n <h5 className=\"text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider mb-2\">\r\n {t('groups:applications.rolesGrantingAccess')}\r\n </h5>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {app.roles.map(role => (\r\n <span\r\n key={role.roleId}\r\n className=\"inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full bg-[var(--bg-card)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n >\r\n <Shield className=\"w-3 h-3 text-[var(--color-accent-500)]\" />\r\n {role.roleName}\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {!app.hasFullAccess && app.permissions.length > 0 && (\r\n <div>\r\n <h5 className=\"text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider mb-2\">\r\n {t('groups:applications.permissionsDetail')}\r\n </h5>\r\n <div className=\"space-y-3\">\r\n {permissionsByModule.map(group => (\r\n <div key={group.moduleName}>\r\n <p className=\"text-xs font-medium text-[var(--text-secondary)] mb-1\">{group.moduleName}</p>\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {group.permissions.map(perm => (\r\n <span\r\n key={perm.path}\r\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded bg-[var(--bg-card)] border border-[var(--border-color)] text-[var(--text-secondary)]\"\r\n >\r\n <Key className=\"w-2.5 h-2.5 text-[var(--text-tertiary)]\" />\r\n {perm.action || extractActionFromPath(perm.path)}\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {app.hasFullAccess && (\r\n <p className=\"text-xs text-[var(--success-text)] italic\">\r\n {t('groups:applications.fullAccessDescription')}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction extractActionFromPath(path: string): string {\r\n const parts = path.split('.');\r\n return parts.at(-1)!;\r\n}\r\n","import type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Building2, User, ArrowRightLeft, Globe } from 'lucide-react';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\n\r\ninterface ScopeBannerProps {\r\n /** Additional CSS classes */\r\n readonly className?: string;\r\n /** Show switch scope button */\r\n readonly showSwitch?: boolean;\r\n /** Callback when switch is clicked (opens tenant selector) */\r\n readonly onSwitchClick?: () => void;\r\n}\r\n\r\n/**\r\n * Banner component displaying current tenant context.\r\n * Shows the current workspace name to help users understand\r\n * what scope their actions will affect.\r\n */\r\nexport function ScopeBanner({ className = '', showSwitch = true, onSwitchClick }: ScopeBannerProps): ReactElement | null {\r\n const { t } = useTranslation('admin');\r\n const { currentTenant, hasMultipleTenants, isGlobalView } = useTenant();\r\n\r\n // Show banner in global view or when user has multiple tenants with a current tenant\r\n if (!isGlobalView && (!hasMultipleTenants || !currentTenant)) {\r\n return null;\r\n }\r\n\r\n // Global view mode\r\n if (isGlobalView) {\r\n return (\r\n <div\r\n className={`flex items-center justify-between gap-4 px-4 py-2.5 border bg-emerald-500/5 border-emerald-500/20 ${className}`}\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n {/* Global Icon */}\r\n <div\r\n className=\"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-emerald-500/10\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <Globe className=\"w-4 h-4 text-emerald-600\" />\r\n </div>\r\n\r\n {/* Scope Info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"font-medium text-emerald-700\">\r\n {t('scope.banner.globalMode', 'Vue globale')}\r\n </span>\r\n <p className=\"text-xs text-emerald-600/70 mt-0.5\">\r\n {t('scope.banner.globalModeDesc', 'Vous voyez les données de tous les tenants')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Switch Button */}\r\n {showSwitch && onSwitchClick && (\r\n <button\r\n onClick={onSwitchClick}\r\n className=\"flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-emerald-700 hover:text-emerald-800 hover:bg-emerald-500/10 transition-colors\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <ArrowRightLeft className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('scope.banner.selectTenant', 'Sélectionner un tenant')}</span>\r\n </button>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n // Tenant view mode\r\n const isB2B = currentTenant?.type === 'Business';\r\n\r\n return (\r\n <div\r\n className={`flex items-center justify-between gap-4 px-4 py-2.5 border bg-[var(--color-accent-500)]/5 border-[var(--color-accent-500)]/20 ${className}`}\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n {/* Scope Icon */}\r\n <div\r\n className={`flex-shrink-0 w-8 h-8 flex items-center justify-center ${\r\n isB2B ? 'bg-blue-500/10' : 'bg-violet-500/10'\r\n }`}\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n {isB2B ? (\r\n <Building2 className=\"w-4 h-4 text-blue-500\" />\r\n ) : (\r\n <User className=\"w-4 h-4 text-violet-500\" />\r\n )}\r\n </div>\r\n\r\n {/* Scope Info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"font-medium text-[var(--text-primary)]\">\r\n {t('scope.banner.tenantMode', 'Espace de travail: {{tenantName}}', { tenantName: currentTenant?.name })}\r\n </span>\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">\r\n {t('scope.banner.tenantModeDesc', 'Les modifications s\\'appliquent uniquement à ce tenant')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Switch Button */}\r\n {showSwitch && onSwitchClick && (\r\n <button\r\n onClick={onSwitchClick}\r\n className=\"flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <ArrowRightLeft className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('scope.banner.switchScope', 'Changer de scope')}</span>\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useRef, useMemo } 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 {\r\n ArrowLeft,\r\n Users,\r\n Shield,\r\n Building2,\r\n Key,\r\n Loader2,\r\n Save,\r\n Trash2,\r\n Edit3,\r\n Mail,\r\n AlertTriangle,\r\n AlertCircle,\r\n CheckCircle,\r\n Cloud,\r\n X,\r\n AppWindow,\r\n GitBranch,\r\n CornerDownRight,\r\n Unlink,\r\n Plus,\r\n Search,\r\n} from 'lucide-react';\r\nimport {\r\n groupsApi,\r\n type GroupDetailDto,\r\n type GroupListDto,\r\n type InheritedMemberDto,\r\n} from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\nimport { GroupRoleAssignment } from '@/components/platform/administration/GroupRoleAssignment';\r\nimport { GroupTenantsTab } from '@/components/platform/administration/GroupTenantsTab';\r\nimport { GroupMembersTab } from '@/components/platform/administration/GroupMembersTab';\r\nimport { GroupPermissionMatrix } from '@/components/platform/administration/permissions/GroupPermissionMatrix';\r\nimport { GroupApplicationsTab } from '@/components/platform/administration/GroupApplicationsTab';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useAdminTenants } from '@/hooks/useAdminTenants';\r\nimport { ScopeBanner } from '@/components/ui/ScopeBanner';\r\nimport { useTabNavigation } from '@/hooks/useTabNavigation';\r\n\r\ntype TabId = 'info' | 'hierarchy' | 'members' | 'roles' | 'tenants' | 'applications' | 'permissions';\r\n\r\nconst VALID_TABS: TabId[] = ['info', 'hierarchy', 'members', 'roles', 'tenants', 'applications', 'permissions'];\r\n\r\nconst isValidGuid = (value: string | undefined): boolean => {\r\n if (!value) return false;\r\n const guidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\r\n return guidRegex.test(value);\r\n};\r\n\r\nconst useGroupDetailState = () => {\r\n const [group, setGroup] = useState<GroupDetailDto | null>(null);\r\n const [roles, setRoles] = useState<RoleListDto[] | null>(null);\r\n const [rolesLoading, setRolesLoading] = useState(false);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [formData, setFormData] = useState({ name: '', description: '' });\r\n\r\n return {\r\n group, setGroup, roles, setRoles, rolesLoading, setRolesLoading,\r\n loading, setLoading, saving, setSaving, error, setError, success, setSuccess,\r\n isEditing, setIsEditing, formData, setFormData,\r\n };\r\n};\r\n\r\nfunction HierarchyTab({\r\n groupId,\r\n group,\r\n onRefresh,\r\n onSuccess,\r\n onError,\r\n}: {\r\n groupId: string;\r\n group: GroupDetailDto;\r\n onRefresh: () => Promise<void>;\r\n onSuccess: (msg: string) => void;\r\n onError: (msg: string) => void;\r\n}) {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const [allGroups, setAllGroups] = useState<GroupListDto[]>([]);\r\n const [loadingGroups, setLoadingGroups] = useState(false);\r\n const [showParentSelector, setShowParentSelector] = useState(false);\r\n const [showChildSelector, setShowChildSelector] = useState(false);\r\n const [showCreateChild, setShowCreateChild] = useState(false);\r\n const [parentSearch, setParentSearch] = useState('');\r\n const [childSearch, setChildSearch] = useState('');\r\n const [saving, setSaving] = useState(false);\r\n const [newChildName, setNewChildName] = useState('');\r\n const [newChildDescription, setNewChildDescription] = useState('');\r\n const [newChildIsSecurityGroup, setNewChildIsSecurityGroup] = useState(false);\r\n const [inheritedMembers, setInheritedMembers] = useState<InheritedMemberDto[]>([]);\r\n const [loadingInheritedMembers, setLoadingInheritedMembers] = useState(false);\r\n\r\n const loadAllGroups = useCallback(async () => {\r\n try {\r\n setLoadingGroups(true);\r\n const groups = await groupsApi.getAll();\r\n setAllGroups(groups);\r\n } catch {\r\n // silently fail — selector just won't have options\r\n } finally {\r\n setLoadingGroups(false);\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (showParentSelector || showChildSelector) {\r\n loadAllGroups();\r\n }\r\n }, [showParentSelector, showChildSelector, loadAllGroups]);\r\n\r\n useEffect(() => {\r\n if (!group.parentGroupId) return;\r\n const loadInheritedMembers = async () => {\r\n try {\r\n setLoadingInheritedMembers(true);\r\n const members = await groupsApi.getInheritedMembers(groupId);\r\n setInheritedMembers(members);\r\n } catch {\r\n // silently fail\r\n } finally {\r\n setLoadingInheritedMembers(false);\r\n }\r\n };\r\n loadInheritedMembers();\r\n }, [groupId, group.parentGroupId]);\r\n\r\n const membersByAncestor = useMemo(() => {\r\n const grouped = new Map<string, { groupId: string; groupName: string; level: number; members: InheritedMemberDto[] }>();\r\n for (const m of inheritedMembers) {\r\n const key = m.inheritedFromGroupId;\r\n if (!grouped.has(key)) {\r\n grouped.set(key, { groupId: m.inheritedFromGroupId, groupName: m.inheritedFromGroupName, level: m.level, members: [] });\r\n }\r\n grouped.get(key)!.members.push(m);\r\n }\r\n return Array.from(grouped.values()).sort((a, b) => a.level - b.level);\r\n }, [inheritedMembers]);\r\n\r\n // Exclude current group + its descendants from parent candidates\r\n const getDescendantIds = (id: string, groups: GroupListDto[]): Set<string> => {\r\n const ids = new Set<string>();\r\n const queue = [id];\r\n while (queue.length > 0) {\r\n const current = queue.shift()!;\r\n ids.add(current);\r\n groups.filter(g => g.parentGroupId === current).forEach(g => queue.push(g.id));\r\n }\r\n return ids;\r\n };\r\n\r\n const excludedForParent = getDescendantIds(groupId, allGroups);\r\n const parentCandidates = allGroups\r\n .filter(g => !excludedForParent.has(g.id) && g.isActive)\r\n .filter(g => !parentSearch || g.name.toLowerCase().includes(parentSearch.toLowerCase()));\r\n\r\n // Child candidates: groups that are NOT already children, NOT the current group, NOT an ancestor\r\n const existingChildIds = new Set(group.childGroups?.map(c => c.id) || []);\r\n const childCandidates = allGroups\r\n .filter(g => g.id !== groupId && !existingChildIds.has(g.id) && g.isActive)\r\n .filter(g => g.parentGroupId !== groupId) // not already a child\r\n .filter(g => !childSearch || g.name.toLowerCase().includes(childSearch.toLowerCase()));\r\n\r\n const handleSetParent = async (parentId: string) => {\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(groupId, { parentGroupId: parentId });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.parentSet'));\r\n setShowParentSelector(false);\r\n setParentSearch('');\r\n } catch {\r\n onError(t('groups:hierarchy.errors.setParentFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleClearParent = async () => {\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(groupId, { parentGroupId: null });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.parentCleared'));\r\n } catch {\r\n onError(t('groups:hierarchy.errors.clearParentFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleAddChild = async (childId: string) => {\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(childId, { parentGroupId: groupId });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.childAdded'));\r\n setShowChildSelector(false);\r\n setChildSearch('');\r\n } catch {\r\n onError(t('groups:hierarchy.errors.addChildFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleRemoveChild = async (childId: string, childName: string) => {\r\n if (!confirm(t('groups:hierarchy.confirmRemoveChild', { name: childName }))) return;\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(childId, { parentGroupId: null });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.childRemoved'));\r\n } catch {\r\n onError(t('groups:hierarchy.errors.removeChildFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleCreateChild = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!newChildName.trim()) return;\r\n try {\r\n setSaving(true);\r\n await groupsApi.create({\r\n name: newChildName.trim(),\r\n description: newChildDescription.trim() || undefined,\r\n isSecurityGroup: newChildIsSecurityGroup,\r\n parentGroupId: groupId,\r\n });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.childCreated'));\r\n setShowCreateChild(false);\r\n setNewChildName('');\r\n setNewChildDescription('');\r\n setNewChildIsSecurityGroup(false);\r\n } catch {\r\n onError(t('groups:hierarchy.errors.createChildFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:hierarchy.info')}\r\n </p>\r\n </div>\r\n\r\n {/* Parent Group Section */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <CornerDownRight className=\"w-5 h-5\" />\r\n {t('groups:hierarchy.parentGroup')}\r\n </h3>\r\n {!group.parentGroupId && !showParentSelector && (\r\n <button\r\n onClick={() => setShowParentSelector(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.setParent')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {group.parentGroupId ? (\r\n <div className=\"flex items-center justify-between p-4 rounded-lg bg-[var(--bg-secondary)]\">\r\n <Link\r\n to={`/administration/users/groups/${group.parentGroupId}`}\r\n className=\"flex items-center gap-3 text-sm font-medium text-[var(--color-accent-500)] hover:underline\"\r\n >\r\n <div className=\"p-2 rounded-lg bg-[var(--accent-bg)]\">\r\n <GitBranch className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n </div>\r\n {group.parentGroupName || group.parentGroupId}\r\n </Link>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => { setShowParentSelector(true); }}\r\n className=\"flex items-center gap-1 px-2 py-1 text-xs rounded-[var(--radius-button)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Edit3 className=\"w-3 h-3\" />\r\n {t('common:edit', 'Modifier')}\r\n </button>\r\n <button\r\n onClick={handleClearParent}\r\n disabled={saving}\r\n className=\"flex items-center gap-1 px-2 py-1 text-xs rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Unlink className=\"w-3 h-3\" />\r\n {t('groups:hierarchy.clearParent')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : !showParentSelector ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('groups:hierarchy.noParent')}\r\n </p>\r\n ) : null}\r\n\r\n {/* Parent Selector */}\r\n {showParentSelector && (\r\n <div className=\"mt-4 p-4 rounded-lg border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <div className=\"relative flex-1\">\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={parentSearch}\r\n onChange={(e) => setParentSearch(e.target.value)}\r\n placeholder={t('groups:hierarchy.searchGroups')}\r\n className=\"w-full pl-9 pr-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n autoFocus\r\n />\r\n </div>\r\n <button\r\n onClick={() => { setShowParentSelector(false); setParentSearch(''); }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <div className=\"max-h-48 overflow-y-auto space-y-1\">\r\n {loadingGroups && (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-tertiary)]\" />\r\n </div>\r\n )}\r\n {!loadingGroups && parentCandidates.length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('groups:hierarchy.noGroupsAvailable')}\r\n </p>\r\n )}\r\n {!loadingGroups && parentCandidates.length > 0 && (\r\n parentCandidates.map((g) => (\r\n <button\r\n key={g.id}\r\n onClick={() => handleSetParent(g.id)}\r\n disabled={saving}\r\n className=\"w-full flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <GitBranch className=\"w-4 h-4 text-[var(--text-tertiary)] flex-shrink-0\" />\r\n <div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{g.name}</span>\r\n {g.parentGroupName && (\r\n <span className=\"ml-2 text-xs text-[var(--text-tertiary)]\">\r\n ({t('groups:hierarchy.childOf')} {g.parentGroupName})\r\n </span>\r\n )}\r\n </div>\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Inherited Members Section */}\r\n {group.parentGroupId && (\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2 mb-4\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:hierarchy.inheritedMembers')}\r\n {!loadingInheritedMembers && (\r\n <span className=\"ml-1 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {inheritedMembers.length}\r\n </span>\r\n )}\r\n </h3>\r\n\r\n <div className=\"p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] mb-4\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:hierarchy.inheritedMembersInfo')}\r\n </p>\r\n </div>\r\n\r\n {loadingInheritedMembers && (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-tertiary)]\" />\r\n </div>\r\n )}\r\n\r\n {!loadingInheritedMembers && inheritedMembers.length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('groups:hierarchy.noInheritedMembers')}\r\n </p>\r\n )}\r\n\r\n {!loadingInheritedMembers && membersByAncestor.length > 0 && (\r\n <div className=\"space-y-4\">\r\n {membersByAncestor.map((ancestorGroup) => (\r\n <div\r\n key={ancestorGroup.groupId}\r\n className=\"p-4 rounded-lg border border-dashed border-[var(--border-color)]\"\r\n >\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <Link\r\n to={`/administration/users/groups/${ancestorGroup.groupId}`}\r\n className=\"text-sm font-medium text-[var(--color-accent-500)] hover:underline flex items-center gap-1.5\"\r\n >\r\n <GitBranch className=\"w-4 h-4\" />\r\n {ancestorGroup.groupName}\r\n </Link>\r\n <span className=\"px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {t('groups:hierarchy.level', { level: ancestorGroup.level })}\r\n </span>\r\n </div>\r\n <div className=\"space-y-1\">\r\n {ancestorGroup.members.map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"p-1.5 rounded-full bg-[var(--bg-secondary)]\">\r\n <Users className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{member.fullName}</span>\r\n <span className=\"ml-2 text-xs text-[var(--text-tertiary)]\">{member.email}</span>\r\n </div>\r\n </Link>\r\n ))}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Child Groups Section */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <GitBranch className=\"w-5 h-5\" />\r\n {t('groups:hierarchy.childGroups')}\r\n <span className=\"ml-1 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {group.childGroups?.length || 0}\r\n </span>\r\n </h3>\r\n {!showChildSelector && !showCreateChild && (\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => setShowCreateChild(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.createChild')}\r\n </button>\r\n <button\r\n onClick={() => setShowChildSelector(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <GitBranch className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.addExisting')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Child Selector */}\r\n {showChildSelector && (\r\n <div className=\"mb-4 p-4 rounded-lg border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <div className=\"relative flex-1\">\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={childSearch}\r\n onChange={(e) => setChildSearch(e.target.value)}\r\n placeholder={t('groups:hierarchy.searchGroups')}\r\n className=\"w-full pl-9 pr-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n autoFocus\r\n />\r\n </div>\r\n <button\r\n onClick={() => { setShowChildSelector(false); setChildSearch(''); }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <div className=\"max-h-48 overflow-y-auto space-y-1\">\r\n {loadingGroups && (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-tertiary)]\" />\r\n </div>\r\n )}\r\n {!loadingGroups && childCandidates.length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('groups:hierarchy.noGroupsAvailable')}\r\n </p>\r\n )}\r\n {!loadingGroups && childCandidates.length > 0 && (\r\n childCandidates.map((g) => (\r\n <button\r\n key={g.id}\r\n onClick={() => handleAddChild(g.id)}\r\n disabled={saving}\r\n className=\"w-full flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <Plus className=\"w-4 h-4 text-[var(--color-accent-500)] flex-shrink-0\" />\r\n <div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{g.name}</span>\r\n {g.parentGroupName && (\r\n <span className=\"ml-2 text-xs text-[var(--text-tertiary)]\">\r\n ({t('groups:hierarchy.childOf')} {g.parentGroupName})\r\n </span>\r\n )}\r\n </div>\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Create Child Form */}\r\n {showCreateChild && (\r\n <form onSubmit={handleCreateChild} className=\"mb-4 p-4 rounded-lg border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)]\">\r\n {t('groups:hierarchy.createChild')}\r\n </h4>\r\n <button\r\n type=\"button\"\r\n onClick={() => { setShowCreateChild(false); setNewChildName(''); setNewChildDescription(''); setNewChildIsSecurityGroup(false); }}\r\n className=\"p-1 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('admin:groups.groupName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newChildName}\r\n onChange={(e) => setNewChildName(e.target.value)}\r\n placeholder={t('admin:groups.groupNamePlaceholder')}\r\n className=\"w-full px-3 py-2 text-sm 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 required\r\n autoFocus\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('groups:detail.info.description')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newChildDescription}\r\n onChange={(e) => setNewChildDescription(e.target.value)}\r\n placeholder={t('admin:groups.descriptionPlaceholder')}\r\n className=\"w-full px-3 py-2 text-sm 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 <label className=\"flex items-center gap-2 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={newChildIsSecurityGroup}\r\n onChange={(e) => setNewChildIsSecurityGroup(e.target.checked)}\r\n className=\"rounded border-[var(--border-color)]\"\r\n />\r\n <span className=\"text-sm text-[var(--text-primary)]\">\r\n {t('admin:groups.isSecurityGroup')}\r\n </span>\r\n </label>\r\n <div className=\"flex items-center gap-2 pt-1\">\r\n <button\r\n type=\"button\"\r\n onClick={() => { setShowCreateChild(false); setNewChildName(''); setNewChildDescription(''); setNewChildIsSecurityGroup(false); }}\r\n className=\"px-3 py-1.5 text-sm rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common:cancel', 'Annuler')}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n disabled={!newChildName.trim() || saving}\r\n className=\"inline-flex items-center gap-1 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 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Plus className=\"w-4 h-4\" />}\r\n {t('common:create', 'Créer')}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n )}\r\n\r\n {/* Existing Children List */}\r\n {(group.childGroups?.length ?? 0) > 0 ? (\r\n <div className=\"space-y-2\">\r\n {group.childGroups.map((child) => (\r\n <div\r\n key={child.id}\r\n className=\"flex items-center justify-between p-3 rounded-lg bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Link\r\n to={`/administration/users/groups/${child.id}`}\r\n className=\"flex items-center gap-3\"\r\n >\r\n <div className=\"p-1.5 rounded-lg bg-[var(--accent-bg)]\">\r\n <GitBranch className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{child.name}</span>\r\n {!child.isActive && (\r\n <span className=\"px-1.5 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)]\">\r\n {t('common.inactive', 'Inactive')}\r\n </span>\r\n )}\r\n </Link>\r\n <button\r\n onClick={() => handleRemoveChild(child.id, child.name)}\r\n disabled={saving}\r\n className=\"flex items-center gap-1 px-2 py-1 text-xs rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Unlink className=\"w-3 h-3\" />\r\n {t('groups:hierarchy.removeChild')}\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n ) : !showChildSelector && !showCreateChild ? (\r\n <div className=\"text-center py-8\">\r\n <GitBranch className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('groups:hierarchy.noChildren')}\r\n </p>\r\n <div className=\"mt-3 flex items-center justify-center gap-2\">\r\n <button\r\n onClick={() => setShowCreateChild(true)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.createChild')}\r\n </button>\r\n <button\r\n onClick={() => setShowChildSelector(true)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <GitBranch className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.addExisting')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : null}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport function GroupDetailPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const { id: groupId } = useParams<{ id: string }>();\r\n const navigate = useNavigate();\r\n\r\n const { currentTenant, hasMultipleTenants } = useTenant();\r\n const { tenants: adminTenantsList } = useAdminTenants();\r\n const { activeTab, setActiveTab } = useTabNavigation<TabId>('info', VALID_TABS);\r\n const visitedTabsRef = useRef<Set<TabId>>(new Set(['info']));\r\n const { group, setGroup, roles, setRoles, rolesLoading, setRolesLoading, loading, setLoading, saving, setSaving, error, setError, success, setSuccess, isEditing, setIsEditing, formData, setFormData } = useGroupDetailState();\r\n\r\n const loadGroup = useCallback(async (silent = false) => {\r\n if (!groupId || !isValidGuid(groupId)) return;\r\n try {\r\n if (!silent) setLoading(true);\r\n const data = await groupsApi.getById(groupId);\r\n setGroup(data);\r\n setFormData({\r\n name: data.name,\r\n description: data.description || ''\r\n });\r\n } catch (err) {\r\n console.error('Failed to load group:', err);\r\n setError(t('groups:detail.errors.loadFailed', 'Erreur lors du chargement du groupe'));\r\n } finally {\r\n if (!silent) setLoading(false);\r\n }\r\n }, [groupId, t]);\r\n\r\n const loadRoles = useCallback(async () => {\r\n try {\r\n setRolesLoading(true);\r\n const result = await adminApi.roles.getAssignable();\r\n setRoles(Array.isArray(result) ? result : []);\r\n } catch (err) {\r\n console.error('Failed to load roles:', err);\r\n setRoles([]);\r\n } finally {\r\n setRolesLoading(false);\r\n }\r\n }, []);\r\n\r\n // Load group data on mount\r\n useEffect(() => {\r\n if (groupId && isValidGuid(groupId)) {\r\n loadGroup();\r\n }\r\n }, [groupId, loadGroup]);\r\n\r\n // Lazy load tab data when tab is first visited\r\n useEffect(() => {\r\n if (!visitedTabsRef.current.has(activeTab)) {\r\n visitedTabsRef.current.add(activeTab);\r\n }\r\n\r\n // Load roles only when roles or permissions tab is first visited\r\n if ((activeTab === 'roles' || activeTab === 'permissions') && roles === null && !rolesLoading) {\r\n loadRoles();\r\n }\r\n }, [activeTab, roles, rolesLoading]);\r\n\r\n const handleSave = useCallback(async () => {\r\n if (!groupId || !group) return;\r\n\r\n try {\r\n setSaving(true);\r\n setError(null);\r\n await groupsApi.update(groupId, {\r\n name: formData.name,\r\n description: formData.description || undefined\r\n });\r\n await loadGroup();\r\n setSuccess(t('groups:detail.saveSuccess', 'Groupe mis à jour avec succès'));\r\n setIsEditing(false);\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err) {\r\n console.error('Failed to save group:', err);\r\n setError(t('groups:detail.errors.saveFailed', 'Erreur lors de l\\'enregistrement'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [groupId, group, formData, loadGroup, t]);\r\n\r\n const handleActivate = useCallback(async () => {\r\n if (!groupId) return;\r\n try {\r\n await groupsApi.activate(groupId);\r\n await loadGroup();\r\n setSuccess(t('groups:detail.activateSuccess', 'Groupe activé'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err) {\r\n console.error('Failed to activate group:', err);\r\n setError(t('groups:detail.errors.activateFailed', 'Erreur lors de l\\'activation'));\r\n }\r\n }, [groupId, loadGroup, t]);\r\n\r\n const handleDeactivate = useCallback(async () => {\r\n if (!groupId) return;\r\n try {\r\n await groupsApi.deactivate(groupId);\r\n await loadGroup();\r\n setSuccess(t('groups:detail.deactivateSuccess', 'Groupe désactivé'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err) {\r\n console.error('Failed to deactivate group:', err);\r\n setError(t('groups:detail.errors.deactivateFailed', 'Erreur lors de la désactivation'));\r\n }\r\n }, [groupId, loadGroup, t]);\r\n\r\n const handleDelete = useCallback(async () => {\r\n if (!groupId || !group) return;\r\n\r\n const confirmMessage = group.isSyncedFromEntra\r\n ? t('groups:detail.confirmDeleteEntra', { name: group.name, defaultValue: `Le groupe \"${group.name}\" est synchronisé depuis Entra ID. Il sera recréé lors de la prochaine synchronisation.\\n\\nÊtes-vous sûr de vouloir le supprimer ?` })\r\n : t('groups:detail.confirmDelete', { name: group.name, defaultValue: `Êtes-vous sûr de vouloir supprimer le groupe \"${group.name}\" ?` });\r\n\r\n if (!confirm(confirmMessage)) {\r\n return;\r\n }\r\n try {\r\n await groupsApi.delete(groupId);\r\n navigate('/administration/users/groups');\r\n } catch (err) {\r\n console.error('Failed to delete group:', err);\r\n setError(t('groups:detail.errors.deleteFailed', 'Erreur lors de la suppression'));\r\n }\r\n }, [groupId, group, navigate, t]);\r\n\r\n const tabs: { id: TabId; label: string; icon: React.ElementType }[] = [\r\n { id: 'info', label: t('groups:detail.tabs.info', 'Informations'), icon: Users },\r\n { id: 'hierarchy', label: t('groups:detail.tabs.hierarchy', 'Hiérarchie'), icon: GitBranch },\r\n { id: 'members', label: t('groups:detail.tabs.members', 'Membres'), icon: Users },\r\n { id: 'roles', label: t('groups:detail.tabs.roles', 'Rôles'), icon: Shield },\r\n { id: 'tenants', label: t('groups:detail.tabs.tenants', 'Tenants'), icon: Building2 },\r\n { id: 'applications', label: t('groups:detail.tabs.applications', 'Applications'), icon: AppWindow },\r\n { id: 'permissions', label: t('groups:detail.tabs.permissions', 'Permissions'), icon: Key }\r\n ];\r\n\r\n if (!groupId || !isValidGuid(groupId)) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <div className=\"text-center\">\r\n <AlertTriangle className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('groups:detail.invalidId', 'ID de groupe invalide')}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (!group) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <div className=\"text-center\">\r\n <AlertTriangle className=\"w-12 h-12 mx-auto mb-4 text-[var(--warning-text)]\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('groups:detail.notFound', 'Groupe non trouvé')}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('admin:nav.administration', 'Administration'), href: '/administration' },\r\n { label: t('admin:nav.groups', 'Groupes'), href: '/administration/users/groups' },\r\n { label: group.name }\r\n ]}\r\n />\r\n\r\n {/* Scope Banner */}\r\n {hasMultipleTenants && currentTenant && (\r\n <ScopeBanner />\r\n )}\r\n\r\n {/* Header */}\r\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4\">\r\n <div className=\"flex items-center gap-4\">\r\n <button\r\n onClick={() => navigate(-1)}\r\n className=\"p-2 rounded-lg bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <ArrowLeft className=\"w-5 h-5\" />\r\n </button>\r\n <div className=\"flex items-center gap-3\">\r\n <div className={`p-3 rounded-xl ${\r\n group.isSecurityGroup\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)]'\r\n : 'bg-[var(--accent-bg)] text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? <Shield className=\"w-6 h-6\" /> : <Users className=\"w-6 h-6\" />}\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {group.name}\r\n </h1>\r\n <div className=\"flex items-center gap-2 mt-1\">\r\n {group.isActive ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-[var(--success-bg)] text-[var(--success-text)]\">\r\n <CheckCircle className=\"w-3 h-3\" />\r\n {t('common.active', 'Actif')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-[var(--error-bg)] text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-3 h-3\" />\r\n {t('common.inactive', 'Inactif')}\r\n </span>\r\n )}\r\n {group.isSyncedFromEntra && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n <Cloud className=\"w-3 h-3\" />\r\n Entra ID\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n {group.isActive ? (\r\n <button\r\n onClick={handleDeactivate}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--warning-dot)] text-white hover:opacity-90 transition-colors\"\r\n >\r\n <AlertTriangle className=\"w-4 h-4\" />\r\n {t('common.deactivate', 'Désactiver')}\r\n </button>\r\n ) : (\r\n <button\r\n onClick={handleActivate}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--success-dot)] text-white hover:opacity-90 transition-colors\"\r\n >\r\n <CheckCircle className=\"w-4 h-4\" />\r\n {t('common.activate', 'Activer')}\r\n </button>\r\n )}\r\n <button\r\n onClick={handleDelete}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--error-dot)] text-white hover:opacity-90 transition-colors\"\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n {t('common.delete', 'Supprimer')}\r\n </button>\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)] flex items-center gap-3\">\r\n <AlertCircle className=\"w-5 h-5 text-[var(--error-text)] flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-[var(--error-text)]\">{error}</p>\r\n <button\r\n onClick={() => loadGroup()}\r\n className=\"mt-1 text-sm text-[var(--error-text)] hover:opacity-80 underline\"\r\n >\r\n {t('common:actions.retry', 'Réessayer')}\r\n </button>\r\n </div>\r\n <button onClick={() => setError(null)} className=\"ml-auto self-start\">\r\n <X className=\"w-4 h-4 text-[var(--error-text)]\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {success && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)] flex items-center gap-3\">\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)] flex-shrink-0\" />\r\n <p className=\"text-[var(--success-text)]\">{success}</p>\r\n </div>\r\n )}\r\n\r\n {/* Tabs */}\r\n <div className=\"border-b border-[var(--border-color)]\">\r\n <nav className=\"flex gap-1 overflow-x-auto pb-px\">\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-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\r\n activeTab === tab.id\r\n ? 'border-[var(--color-accent-500)] text-[var(--color-accent-500)]'\r\n : 'border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:border-[var(--border-color)]'\r\n }`}\r\n >\r\n <tab.icon className=\"w-4 h-4\" />\r\n {tab.label}\r\n </button>\r\n ))}\r\n </nav>\r\n </div>\r\n\r\n {/* Tab Content */}\r\n\r\n {/* Info Tab */}\r\n {activeTab === 'info' && (\r\n <div className=\"space-y-6\">\r\n {/* Basic Information */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:detail.info.basicInfo', 'Informations de base')}\r\n </h3>\r\n {!group.isSyncedFromEntra && !isEditing && (\r\n <button\r\n onClick={() => setIsEditing(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Edit3 className=\"w-4 h-4\" />\r\n {t('common.edit', 'Modifier')}\r\n </button>\r\n )}\r\n {isEditing && (\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => {\r\n setIsEditing(false);\r\n setFormData({ name: group.name, description: group.description || '' });\r\n }}\r\n className=\"px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel', 'Annuler')}\r\n </button>\r\n <button\r\n onClick={handleSave}\r\n disabled={saving}\r\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] 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', 'Enregistrer')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {isEditing ? (\r\n <div className=\"grid grid-cols-1 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('groups:detail.info.name', 'Nom')}\r\n </label>\r\n <input\r\n type=\"text\"\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 <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('groups:detail.info.description', '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)]\"\r\n />\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.name', 'Nom')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] font-medium\">{group.name}</p>\r\n </div>\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.type', 'Type')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] font-medium\">\r\n {group.isSecurityGroup\r\n ? t('groups:detail.info.securityGroup', 'Groupe de sécurité')\r\n : t('groups:detail.info.distributionGroup', 'Groupe de distribution')}\r\n </p>\r\n </div>\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)] sm:col-span-2\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.description', 'Description')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">{group.description || '-'}</p>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Entra Information (if synced) */}\r\n {group.isSyncedFromEntra && (\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2 mb-4\">\r\n <Cloud className=\"w-5 h-5\" />\r\n {t('groups:detail.info.entraInfo', 'Microsoft Entra ID')}\r\n </h3>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.entraObjectId', 'Object ID')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] font-mono\">{group.entraObjectId}</p>\r\n </div>\r\n {group.mail && (\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.mail', 'Email')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] flex items-center gap-2\">\r\n <Mail className=\"w-4 h-4\" />\r\n {group.mail}\r\n </p>\r\n </div>\r\n )}\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.lastSync', 'Dernière synchronisation')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {group.lastEntraSyncAt\r\n ? new Date(group.lastEntraSyncAt).toLocaleString()\r\n : '-'}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"mt-4 p-3 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:detail.info.entraNote', 'Ce groupe est synchronisé depuis Microsoft Entra ID. Les informations de base ne peuvent pas être modifiées ici.')}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Members Summary */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2 mb-4\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:detail.info.members', 'Membres')}\r\n <span className=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {group.members?.length || 0}\r\n </span>\r\n </h3>\r\n {(group.members?.length ?? 0) > 0 ? (\r\n <div className=\"space-y-2\">\r\n {group.members.slice(0, 5).map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full bg-[var(--accent-bg)] flex items-center justify-center\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0)}\r\n </span>\r\n </div>\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">{member.fullName}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{member.email}</p>\r\n </div>\r\n </Link>\r\n ))}\r\n {group.members.length > 5 && (\r\n <p className=\"text-sm text-[var(--text-secondary)] text-center py-2\">\r\n {t('groups:detail.info.moreMembers', '+ {{count}} autres membres', { count: group.members.length - 5 })}\r\n </p>\r\n )}\r\n </div>\r\n ) : (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('groups:detail.info.noMembers', 'Aucun membre dans ce groupe')}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* Metadata */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] mb-4\">\r\n {t('groups:detail.info.metadata', 'Métadonnées')}\r\n </h3>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('common.createdAt', 'Créé le')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(group.createdAt).toLocaleString()}\r\n </p>\r\n </div>\r\n {group.updatedAt && (\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('common.updatedAt', 'Modifié le')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(group.updatedAt).toLocaleString()}\r\n </p>\r\n </div>\r\n )}\r\n {group.createdBy && (\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('common.createdBy', 'Créé par')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">{group.createdBy}</p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Hierarchy Tab */}\r\n {activeTab === 'hierarchy' && groupId && (\r\n <HierarchyTab\r\n groupId={groupId}\r\n group={group}\r\n onRefresh={loadGroup}\r\n onSuccess={(msg) => { setSuccess(msg); setTimeout(() => setSuccess(null), 3000); }}\r\n onError={setError}\r\n />\r\n )}\r\n\r\n {/* Members Tab */}\r\n {activeTab === 'members' && groupId && (\r\n <GroupMembersTab\r\n groupId={groupId}\r\n groupName={group.name}\r\n isSyncedFromEntra={group.isSyncedFromEntra}\r\n />\r\n )}\r\n\r\n {/* Roles Tab */}\r\n {activeTab === 'roles' && groupId && (\r\n <GroupRoleAssignment\r\n groupId={groupId}\r\n assignedRoles={group.roles || []}\r\n onSave={async () => {\r\n await loadGroup(true);\r\n }}\r\n roles={roles ?? []}\r\n loading={rolesLoading}\r\n isGlobalScope={true}\r\n adminTenants={adminTenantsList.map(at => ({\r\n tenantId: at.id,\r\n tenantSlug: at.slug,\r\n tenantName: at.name,\r\n tenantType: at.type,\r\n }))}\r\n />\r\n )}\r\n\r\n {/* Tenants Tab */}\r\n {activeTab === 'tenants' && groupId && (\r\n <GroupTenantsTab groupId={groupId} groupName={group.name} />\r\n )}\r\n\r\n {/* Applications Tab */}\r\n {activeTab === 'applications' && groupId && (\r\n <GroupApplicationsTab groupId={groupId} />\r\n )}\r\n\r\n {/* Permissions Tab */}\r\n {activeTab === 'permissions' && groupId && (\r\n <GroupPermissionMatrix\r\n groupId={groupId}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["CATEGORY_STYLES","DEFAULT_CATEGORY_STYLE","GroupRoleAssignment","groupId","assignedRoles","onSave","rolesProp","loading","tenantId","isGlobalScope","adminTenants","t","useTranslation","roles","searchQuery","setSearchQuery","useState","scopeFilter","setScopeFilter","removing","setRemoving","modalOpen","setModalOpen","error","setError","removingRef","useRef","groupTenants","setGroupTenants","useEffect","cancelled","groupsApi","tenants","inheritedRoles","setInheritedRoles","inheritedLoading","setInheritedLoading","tenantOptions","useMemo","a","b","filteredAssignedRoles","scoped","ar","query","roleMap","map","r","handleRemoveRole","useCallback","roleId","roleTenantId","isGlobal","err","handleOpenModal","handleCloseModal","handleAssigned","jsxs","jsx","AlertCircle","X","Search","e","to","ChevronDown","Plus","Loader2","roleDetail","category","catStyle","customIcon","getCustomRoleIcon","removingKey","isRemoving","Globe","Building2","Trash2","AssignRoleModal","GitMerge","ir","initialTenantId","initialIsGlobalScope","onAssigned","onClose","filterCategory","setFilterCategory","filterApplication","setFilterApplication","saving","setSaving","savingRef","setRoles","rolesLoading","setRolesLoading","adminApi","result","groupTenantIds","setGroupTenantIds","applications","setApplications","tenantIds","tid","results","appMap","apps","app","id","name","modalTenants","at","modalScope","setModalScope","tenant","modalIsGlobal","modalTenantId","currentScopeRoleIds","ids","tenantAppIds","setTenantAppIds","scopedRoles","categories","cats","filteredRoles","filtered","handleAssignRole","TenantScopeSelector","Filter","c","cat","role","isAlreadyAssigned","isAssigning","getSelectAllClass","isAllSelected","getTenantItemClass","isSelected","getTenantCheckboxClass","filterAvailableTenants","allTenants","assignedTenantIds","filterAssignedTenants","pageSearchQuery","GroupTenantsTab","groupName","navigate","useNavigate","getIconForType","useTenantTypeSettings","setTenants","inheritedTenants","setInheritedTenants","setAllTenants","setLoading","showAddModal","setShowAddModal","removingTenantId","setRemovingTenantId","success","setSuccess","selectedTenantIds","setSelectedTenantIds","setPageSearchQuery","viewMode","setViewMode","adding","setAdding","loadTenants","data","inherited","loadAllTenants","handleRemoveTenant","errorMessage","addTenantsAndTrackResults","successCount","failedTenants","tenantName","filteredAvailableTenants","handleAddSelectedTenants","toggleTenantSelection","prev","toggleSelectAll","allIds","allSelected","filteredTenants","RefreshCw","LayoutGrid","LayoutList","AlertTriangle","CheckCircle","typeInfo","TenantIcon","getLucideIcon","colors","getColorClasses","Fragment","RowIcon","GitBranch","InheritedIcon","Link","LinkIcon","Check","modalTypeInfo","ModalIcon","modalColors","GroupMembersTab","isSyncedFromEntra","members","setMembers","allUsers","setAllUsers","removingUserId","setRemovingUserId","selectedUserIds","setSelectedUserIds","isAddingMultiple","setIsAddingMultiple","loadMembers","loadAllUsers","response","users","handleAddMultipleMembers","userIdsArray","userId","toggleUserSelection","next","handleRemoveMember","member","m","filteredAvailableUsers","u","getInitials","part","getViewModeButtonClass","isActive","Users","Table","Info","user","useGroupPermissions","options","loadGroup","loadGroupRoles","groupData","matrixData","matrixRoleMap","allRoles","gr","matrixRole","baseResult","useEntityPermissions","group","groupRoles","getPermissionSources","permissionId","sources","roleInheritance","info","getTenantBadgesFromRoles","sourceRoles","tenantMap","key","getSourceTypesFromRoles","isCustomRoleFn","type","s","ACTION_ICONS","Shield","Eye","Edit","UserPlus","Play","ACTION_COLORS","GroupPermissionMatrix","compact","tenantSlug","filteredResources","effectivePermissions","filters","modules","updateFilters","reloadData","isTenantMode","collapsedApps","toggleApp","useCollapsibleState","collapsedModules","setCollapsedModules","collapsedSections","setCollapsedSections","statusFilters","setStatusFilters","openPopover","setOpenPopover","customRoleId","setCustomRoleId","customRolePermissions","setCustomRolePermissions","togglingPermission","setTogglingPermission","loadingCustomRole","setLoadingCustomRole","setErrorMessage","createAdminApi","createGroupsApi","React","p","handleTogglePermission","currentPermissions","newPermissions","handleCellClick","resourceId","toggleStatusFilter","status","toggleModule","moduleId","toggleSection","sectionId","getAllPermissionsForResource","resource","allPermissions","section","getPermissionStatusForGroup","isSection","calculatePermissionStatus","permId","grantedCount","totalCount","filterModulesByStatus","calculateModuleWithSectionsStatus","applyStatusFilters","grouped","appGroup","groupedResources","groupByApplicationWithSections","totalModuleCount","sum","addUniqueSourceRole","getSourceRolesForResource","perm","isCustomRole","roleName","getDisplayName","groupAsRole","getGroupPermissionInheritance","_roleId","isGranted","isFromCustomRole","inheritedRole","getPaddingClass","level","getResourceIcon","Database","FileText","Box","getResourceLabelClass","renderResourceRows","resources","baseIndex","idx","renderResourceRow","renderSectionRow","sectionWithResources","moduleIndex","sectionIndex","hasResources","isSectionCollapsed","renderSectionRows","sections","hasSections","isModuleCollapsed","rowIndex","hasChildren","isCollapsed","cellBg","getPermissionCellBackground","isPopoverOpen","paddingLeft","ChevronRight","PermissionStatusIndicator","PermissionPopover","isCustom","displayName","scopeIcon","scopeTitle","Star","source","UserCheck","User","isToggling","actionColor","icon","mod","Ban","scopeLabel","appKey","isAppCollapsed","FolderOpen","moduleWithSections","module","GroupApplicationsTab","expandedApps","setExpandedApps","loadApplicationAccess","toggleExpand","appId","Boxes","ApplicationCard","isExpanded","onToggle","icons","LucideIcons","AppIcon","permissionsByModule","groups","Layers","Key","extractActionFromPath","path","ScopeBanner","className","showSwitch","onSwitchClick","currentTenant","hasMultipleTenants","isGlobalView","useTenant","ArrowRightLeft","isB2B","VALID_TABS","isValidGuid","value","useGroupDetailState","setGroup","isEditing","setIsEditing","formData","setFormData","HierarchyTab","onRefresh","onSuccess","onError","allGroups","setAllGroups","loadingGroups","setLoadingGroups","showParentSelector","setShowParentSelector","showChildSelector","setShowChildSelector","showCreateChild","setShowCreateChild","parentSearch","setParentSearch","childSearch","setChildSearch","newChildName","setNewChildName","newChildDescription","setNewChildDescription","newChildIsSecurityGroup","setNewChildIsSecurityGroup","inheritedMembers","setInheritedMembers","loadingInheritedMembers","setLoadingInheritedMembers","loadAllGroups","membersByAncestor","excludedForParent","queue","current","g","parentCandidates","existingChildIds","childCandidates","handleSetParent","parentId","handleClearParent","handleAddChild","childId","handleRemoveChild","childName","handleCreateChild","CornerDownRight","Edit3","Unlink","ancestorGroup","child","GroupDetailPage","useParams","adminTenantsList","useAdminTenants","activeTab","setActiveTab","useTabNavigation","visitedTabsRef","silent","loadRoles","handleSave","handleActivate","handleDeactivate","handleDelete","confirmMessage","tabs","AppWindow","Breadcrumb","ArrowLeft","Cloud","tab","Save","Mail","msg"],"mappings":"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"}
1
+ {"version":3,"file":"GroupDetailPage-R-hf3rJ7.js","sources":["../../src/components/platform/administration/GroupRoleAssignment.tsx","../../src/components/platform/administration/GroupTenantsTab.tsx","../../src/components/platform/administration/GroupMembersTab.tsx","../../src/hooks/useGroupPermissions.ts","../../src/components/platform/administration/permissions/GroupPermissionMatrix.tsx","../../src/components/platform/administration/GroupApplicationsTab.tsx","../../src/components/ui/ScopeBanner.tsx","../../src/pages/platform/administration/users/GroupDetailPage.tsx"],"sourcesContent":["import { useState, useMemo, useRef, useCallback, useEffect } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Plus, Trash2, Loader2, Search, Building2, Globe, X, ChevronDown, Filter, AlertCircle, GitMerge } from 'lucide-react';\r\nimport { groupsApi, type GroupRoleDto, type InheritedGroupRoleDto } from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\nimport { getCustomRoleIcon } from '@/utils/roleUtils';\r\nimport { TenantScopeSelector, type ScopeValue } from '@/components/ui/TenantScopeSelector';\r\n\r\ninterface AdminTenantInfo {\r\n tenantId: string;\r\n tenantSlug: string;\r\n tenantName: string;\r\n tenantType: string;\r\n}\r\n\r\ninterface GroupRoleAssignmentProps {\r\n readonly groupId: string;\r\n readonly assignedRoles?: GroupRoleDto[];\r\n readonly onSave: (roleIds: string[]) => Promise<void>;\r\n readonly roles: RoleListDto[];\r\n readonly loading?: boolean;\r\n readonly tenantId?: string;\r\n readonly isGlobalScope?: boolean;\r\n readonly adminTenants?: AdminTenantInfo[];\r\n}\r\n\r\nconst CATEGORY_STYLES: Record<string, { bg: string; text: string }> = {\r\n Global: { bg: 'bg-[var(--accent-bg)]', text: 'text-[var(--color-accent-500)]' },\r\n Admin: { bg: 'bg-[var(--error-bg)]', text: 'text-[var(--error-text)]' },\r\n Manager: { bg: 'bg-[var(--warning-bg)]', text: 'text-[var(--warning-text)]' },\r\n Contributor: { bg: 'bg-[var(--success-bg)]', text: 'text-[var(--success-text)]' },\r\n Viewer: { bg: 'bg-[var(--info-bg)]', text: 'text-[var(--info-text)]' },\r\n Custom: { bg: 'bg-[var(--accent-bg)]', text: 'text-[var(--color-accent-700)]' },\r\n};\r\n\r\nconst DEFAULT_CATEGORY_STYLE = { bg: 'bg-[var(--bg-secondary)]', text: 'text-[var(--text-secondary)]' };\r\n\r\nexport function GroupRoleAssignment({\r\n groupId,\r\n assignedRoles = [],\r\n onSave,\r\n roles: rolesProp,\r\n loading = false,\r\n tenantId,\r\n isGlobalScope = true,\r\n adminTenants = [],\r\n}: GroupRoleAssignmentProps): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const roles = Array.isArray(rolesProp) ? rolesProp : [];\r\n\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [scopeFilter, setScopeFilter] = useState<string>('all');\r\n const [removing, setRemoving] = useState<string | null>(null);\r\n const [modalOpen, setModalOpen] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const removingRef = useRef(false);\r\n\r\n // Load group's tenants to restrict the overview filter\r\n const [groupTenants, setGroupTenants] = useState<Array<{ id: string; name: string }>>([]);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n groupsApi.getTenants(groupId).then(tenants => {\r\n if (!cancelled) {\r\n setGroupTenants(tenants.map(t => ({ id: t.tenantId, name: t.tenantName })));\r\n }\r\n }).catch(() => {\r\n if (!cancelled) setGroupTenants([]);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupId]);\r\n\r\n const [inheritedRoles, setInheritedRoles] = useState<InheritedGroupRoleDto[]>([]);\r\n const [inheritedLoading, setInheritedLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n setInheritedLoading(true);\r\n groupsApi.getInheritedRoles(groupId).then(roles => {\r\n if (!cancelled) setInheritedRoles(roles);\r\n }).catch(() => {\r\n if (!cancelled) setInheritedRoles([]);\r\n }).finally(() => {\r\n if (!cancelled) setInheritedLoading(false);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupId]);\r\n\r\n // Only show tenants the group belongs to\r\n const tenantOptions = useMemo(() => {\r\n return [...groupTenants].sort((a, b) => a.name.localeCompare(b.name));\r\n }, [groupTenants]);\r\n\r\n // --- Overview table: filtered by scope + search ---\r\n\r\n const filteredAssignedRoles = useMemo(() => {\r\n // First: scope filter\r\n let scoped = assignedRoles;\r\n if (scopeFilter === 'global') {\r\n scoped = scoped.filter(ar => ar.isGlobal);\r\n } else if (scopeFilter !== 'all') {\r\n scoped = scoped.filter(ar => ar.isGlobal || ar.tenantId === scopeFilter);\r\n }\r\n\r\n // Then: text search\r\n if (!searchQuery.trim()) return scoped;\r\n const query = searchQuery.toLowerCase().trim();\r\n return scoped.filter(ar =>\r\n ar.roleName.toLowerCase().includes(query) ||\r\n ar.tenantName?.toLowerCase().includes(query)\r\n );\r\n }, [assignedRoles, searchQuery, scopeFilter]);\r\n\r\n // Build a map of roleId -> RoleListDto for category lookup\r\n const roleMap = useMemo(() => {\r\n const map = new Map<string, RoleListDto>();\r\n for (const r of roles) map.set(r.id, r);\r\n return map;\r\n }, [roles]);\r\n\r\n const handleRemoveRole = useCallback(async (roleId: string, roleTenantId: string | null, isGlobal: boolean) => {\r\n if (removingRef.current) return;\r\n removingRef.current = true;\r\n setRemoving(roleId + (roleTenantId || 'global'));\r\n setError(null);\r\n\r\n try {\r\n await groupsApi.removeRole(groupId, roleId, isGlobal ? undefined : (roleTenantId ?? undefined));\r\n await onSave([]);\r\n } catch (err) {\r\n console.error('Failed to remove role assignment:', err);\r\n setError(t('admin:userRoles.errors.removeFailed', 'Erreur lors du retrait du rôle'));\r\n } finally {\r\n setRemoving(null);\r\n removingRef.current = false;\r\n }\r\n }, [groupId, onSave, t]);\r\n\r\n const handleOpenModal = useCallback(() => setModalOpen(true), []);\r\n const handleCloseModal = useCallback(() => setModalOpen(false), []);\r\n\r\n const handleAssigned = useCallback(async () => {\r\n await onSave([]);\r\n }, [onSave]);\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Error alert */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] flex items-center gap-3\">\r\n <AlertCircle className=\"w-5 h-5 text-[var(--error-text)] flex-shrink-0\" />\r\n <p className=\"flex-1 text-[var(--error-text)]\">{error}</p>\r\n <button onClick={() => setError(null)} className=\"ml-auto\">\r\n <X className=\"w-4 h-4 text-[var(--error-text)]\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Header: search + scope filter + assign button */}\r\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3\">\r\n <div className=\"flex items-center gap-3 flex-1\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]\" />\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n placeholder={t('admin:userRoles.search', 'Rechercher un rôle...')}\r\n className=\"w-full pl-10 pr-4 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] placeholder-[var(--text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n <div className=\"relative\">\r\n <select\r\n value={scopeFilter}\r\n onChange={(e) => setScopeFilter(e.target.value)}\r\n className=\"px-3 py-2 pr-8 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] appearance-none focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:userRoles.scopeAll', 'Tous les tenants')}</option>\r\n <option value=\"global\">{t('admin:roles.global', 'Global')}</option>\r\n {tenantOptions.map(to => (\r\n <option key={to.id} value={to.id}>{to.name}</option>\r\n ))}\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 pointer-events-none text-[var(--text-tertiary)]\" />\r\n </div>\r\n </div>\r\n <button\r\n onClick={handleOpenModal}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors text-sm font-medium\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:userRoles.assignRole', 'Assigner un rôle')}\r\n </button>\r\n </div>\r\n\r\n {/* Overview table */}\r\n {loading ? (\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 <div className=\"overflow-x-auto\">\r\n <table className=\"w-full border border-[var(--border-color)] rounded-[var(--radius-card)] overflow-hidden\">\r\n <thead className=\"bg-[var(--bg-tertiary)]\">\r\n <tr>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.name', 'Rôle')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.category', 'Catégorie')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.tenant', 'Tenant')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)] w-24\">\r\n {t('admin:roles.actions', 'Actions')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredAssignedRoles.length === 0 ? (\r\n <tr>\r\n <td colSpan={4} className=\"px-4 py-8 text-center text-[var(--text-muted)]\">\r\n {assignedRoles.length === 0\r\n ? t('admin:userRoles.noAssignedRoles', 'Aucun rôle assigné à ce groupe')\r\n : t('admin:userRoles.noRoles', 'Aucun rôle trouvé')}\r\n </td>\r\n </tr>\r\n ) : (\r\n filteredAssignedRoles.map((ar) => {\r\n const roleDetail = roleMap.get(ar.roleId);\r\n const category = roleDetail?.category || 'Custom';\r\n const catStyle = CATEGORY_STYLES[category] || DEFAULT_CATEGORY_STYLE;\r\n const customIcon = roleDetail ? getCustomRoleIcon(roleDetail.code) : null;\r\n const removingKey = ar.roleId + (ar.tenantId || 'global');\r\n const isRemoving = removing === removingKey;\r\n\r\n return (\r\n <tr key={removingKey} className=\"hover:bg-[var(--bg-hover)] transition-colors\">\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n {customIcon && <span>{customIcon}</span>}\r\n <span className=\"font-medium text-[var(--text-primary)]\">{ar.roleName}</span>\r\n </div>\r\n {ar.roleDescription && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5 max-w-xs truncate\">{ar.roleDescription}</p>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-full ${catStyle.bg} ${catStyle.text}`}>\r\n {category}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {ar.isGlobal ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--info-bg)] text-[var(--info-text)]\">\r\n <Globe className=\"w-3 h-3\" />\r\n {t('admin:roles.global', 'Global')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--accent-bg)] text-[var(--color-accent-700)]\">\r\n <Building2 className=\"w-3 h-3\" />\r\n {ar.tenantName || t('admin:roles.unknownTenant', 'Tenant')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <button\r\n onClick={() => handleRemoveRole(ar.roleId, ar.tenantId, ar.isGlobal)}\r\n disabled={isRemoving}\r\n className=\"p-1.5 rounded-[var(--radius-button)] text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors disabled:opacity-50\"\r\n title={t('admin:userRoles.removeRole', 'Retirer le rôle')}\r\n >\r\n {isRemoving ? (\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 </td>\r\n </tr>\r\n );\r\n })\r\n )}\r\n </tbody>\r\n </table>\r\n {assignedRoles.length > 0 && (\r\n <div className=\"px-4 py-2 text-xs text-[var(--text-muted)] bg-[var(--bg-tertiary)] border-t border-[var(--border-color)]\">\r\n {filteredAssignedRoles.length !== assignedRoles.length\r\n ? t('admin:userRoles.totalFiltered', '{{filtered}} / {{count}} rôle(s) affiché(s)', { filtered: filteredAssignedRoles.length, count: assignedRoles.length })\r\n : t('admin:userRoles.totalAssigned', '{{count}} rôle(s) assigné(s)', { count: assignedRoles.length })}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {modalOpen && (\r\n <AssignRoleModal\r\n groupId={groupId}\r\n assignedRoles={assignedRoles}\r\n initialTenantId={tenantId}\r\n initialIsGlobalScope={isGlobalScope}\r\n adminTenants={adminTenants}\r\n onAssigned={handleAssigned}\r\n onClose={handleCloseModal}\r\n />\r\n )}\r\n\r\n {/* Inherited Roles */}\r\n {inheritedLoading ? (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n ) : inheritedRoles.length > 0 && (\r\n <div className=\"space-y-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <GitMerge className=\"w-4 h-4 text-[var(--text-secondary)]\" />\r\n <h3 className=\"text-sm font-semibold text-[var(--text-primary)]\">\r\n {t('groups:hierarchy.inheritedRoles', 'Rôles hérités')}\r\n </h3>\r\n <span className=\"text-xs text-[var(--text-muted)]\">({inheritedRoles.length})</span>\r\n </div>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('groups:hierarchy.inheritedRolesInfo', 'Ces rôles sont hérités des groupes ancêtres. Ils ne peuvent pas être retirés directement — modifiez le groupe ancêtre pour les gérer.')}\r\n </p>\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full border border-[var(--border-color)] rounded-[var(--radius-card)] overflow-hidden\">\r\n <thead className=\"bg-[var(--bg-tertiary)]\">\r\n <tr>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.name', 'Rôle')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.tenant', 'Tenant')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('groups:hierarchy.inheritedFrom', 'Hérité de')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {inheritedRoles.map((ir) => {\r\n const roleDetail = roleMap.get(ir.roleId);\r\n const category = roleDetail?.category || 'Custom';\r\n const catStyle = CATEGORY_STYLES[category] || DEFAULT_CATEGORY_STYLE;\r\n return (\r\n <tr key={ir.roleId + (ir.tenantId || 'global')} className=\"bg-[var(--bg-secondary)] opacity-80\">\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)]\">{ir.roleName}</span>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${catStyle.bg} ${catStyle.text}`}>\r\n {category}\r\n </span>\r\n </div>\r\n {ir.roleDescription && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5 max-w-xs truncate\">{ir.roleDescription}</p>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {ir.isGlobal ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--info-bg)] text-[var(--info-text)]\">\r\n <Globe className=\"w-3 h-3\" />\r\n {t('admin:roles.global', 'Global')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--accent-bg)] text-[var(--color-accent-700)]\">\r\n <Building2 className=\"w-3 h-3\" />\r\n {ir.tenantName || t('admin:roles.unknownTenant', 'Tenant')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className=\"inline-flex items-center gap-1 text-xs text-[var(--text-secondary)]\">\r\n <GitMerge className=\"w-3 h-3\" />\r\n {ir.inheritedFromGroupName}\r\n <span className=\"text-[var(--text-muted)]\">\r\n ({t('groups:hierarchy.level', 'Niveau {{level}}', { level: ir.level })})\r\n </span>\r\n </span>\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// --- Assign Role Modal ---\r\n\r\ninterface AssignRoleModalProps {\r\n readonly groupId: string;\r\n readonly assignedRoles: GroupRoleDto[];\r\n readonly initialTenantId?: string;\r\n readonly initialIsGlobalScope: boolean;\r\n readonly adminTenants: AdminTenantInfo[];\r\n readonly onAssigned: () => Promise<void>;\r\n readonly onClose: () => void;\r\n}\r\n\r\nfunction AssignRoleModal({\r\n groupId,\r\n assignedRoles,\r\n initialTenantId,\r\n initialIsGlobalScope,\r\n adminTenants,\r\n onAssigned,\r\n onClose,\r\n}: AssignRoleModalProps) {\r\n const { t } = useTranslation(['admin', 'groups', 'common']);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [filterCategory, setFilterCategory] = useState<string>('all');\r\n const [filterApplication, setFilterApplication] = useState<string>('all');\r\n const [saving, setSaving] = useState<string | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n const savingRef = useRef(false);\r\n\r\n // Load roles fresh from API when modal opens\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [rolesLoading, setRolesLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n setRolesLoading(true);\r\n adminApi.roles.getAssignable().then(result => {\r\n if (!cancelled) setRoles(Array.isArray(result) ? result : []);\r\n }).catch(() => {\r\n if (!cancelled) setRoles([]);\r\n }).finally(() => {\r\n if (!cancelled) setRolesLoading(false);\r\n });\r\n return () => { cancelled = true; };\r\n }, []);\r\n\r\n // Load group's tenants to restrict the scope selector\r\n const [groupTenantIds, setGroupTenantIds] = useState<Set<string> | null>(null);\r\n\r\n useEffect(() => {\r\n let cancelled = false;\r\n groupsApi.getTenants(groupId).then(tenants => {\r\n if (!cancelled) {\r\n setGroupTenantIds(new Set(tenants.map(t => t.tenantId)));\r\n }\r\n }).catch(() => {\r\n if (!cancelled) setGroupTenantIds(null);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupId]);\r\n\r\n // Load applications from the group's tenants (union of all tenant applications)\r\n const [applications, setApplications] = useState<Array<{ id: string; name: string }>>([]);\r\n\r\n useEffect(() => {\r\n if (!groupTenantIds || groupTenantIds.size === 0) {\r\n setApplications([]);\r\n return;\r\n }\r\n let cancelled = false;\r\n const tenantIds = Array.from(groupTenantIds);\r\n Promise.all(tenantIds.map(tid => adminApi.tenants.getApplications(tid)))\r\n .then(results => {\r\n if (cancelled) return;\r\n const appMap = new Map<string, string>();\r\n for (const apps of results) {\r\n for (const app of apps) {\r\n if (!appMap.has(app.applicationId)) {\r\n appMap.set(app.applicationId, app.label);\r\n }\r\n }\r\n }\r\n setApplications(\r\n Array.from(appMap.entries())\r\n .map(([id, name]) => ({ id, name }))\r\n .sort((a, b) => a.name.localeCompare(b.name))\r\n );\r\n })\r\n .catch(() => {\r\n if (!cancelled) setApplications([]);\r\n });\r\n return () => { cancelled = true; };\r\n }, [groupTenantIds]);\r\n\r\n // Only show tenants that the group belongs to\r\n const modalTenants = useMemo(() => {\r\n if (!groupTenantIds) return adminTenants;\r\n return adminTenants.filter(at => groupTenantIds.has(at.tenantId));\r\n }, [adminTenants, groupTenantIds]);\r\n\r\n // Local scope state for the modal (initialized from parent)\r\n const [modalScope, setModalScope] = useState<ScopeValue>(() => {\r\n if (initialIsGlobalScope || !initialTenantId) return 'global';\r\n const tenant = adminTenants.find(at => at.tenantId === initialTenantId);\r\n if (!tenant) return 'global';\r\n return {\r\n tenantId: tenant.tenantId,\r\n tenantSlug: tenant.tenantSlug,\r\n tenantUserId: '',\r\n tenantName: tenant.tenantName,\r\n };\r\n });\r\n\r\n const modalIsGlobal = modalScope === 'global';\r\n const modalTenantId = !modalIsGlobal ? modalScope.tenantId : undefined;\r\n\r\n // Roles already assigned for the modal's current scope\r\n const currentScopeRoleIds = useMemo(() => {\r\n const ids = new Set<string>();\r\n for (const ar of assignedRoles) {\r\n if (modalIsGlobal && ar.isGlobal) ids.add(ar.roleId);\r\n else if (!modalIsGlobal && ar.tenantId === modalTenantId) ids.add(ar.roleId);\r\n }\r\n return ids;\r\n }, [assignedRoles, modalIsGlobal, modalTenantId]);\r\n\r\n // Load tenant's accessible application IDs when a tenant is selected\r\n const [tenantAppIds, setTenantAppIds] = useState<Set<string> | null>(null);\r\n\r\n useEffect(() => {\r\n if (modalIsGlobal || !modalTenantId) {\r\n setTenantAppIds(null);\r\n return;\r\n }\r\n let cancelled = false;\r\n adminApi.tenants.getApplications(modalTenantId).then(apps => {\r\n if (!cancelled) {\r\n setTenantAppIds(new Set(apps.map(a => a.applicationId)));\r\n }\r\n }).catch(() => {\r\n if (!cancelled) setTenantAppIds(null);\r\n });\r\n return () => { cancelled = true; };\r\n }, [modalIsGlobal, modalTenantId]);\r\n\r\n // Roles available for the current scope (filtered by tenant's accessible apps)\r\n const scopedRoles = useMemo(() => {\r\n if (modalIsGlobal || !tenantAppIds) return roles;\r\n return roles.filter(r => !r.applicationId || tenantAppIds.has(r.applicationId));\r\n }, [roles, modalIsGlobal, tenantAppIds]);\r\n\r\n const categories = useMemo(() => {\r\n const cats = new Set(scopedRoles.map(r => r.category || 'Custom'));\r\n return ['all', ...Array.from(cats).sort((a, b) => a.localeCompare(b))];\r\n }, [scopedRoles]);\r\n\r\n const filteredRoles = useMemo(() => {\r\n let filtered = scopedRoles;\r\n\r\n // Application filter\r\n if (filterApplication !== 'all') {\r\n filtered = filtered.filter(r => r.applicationId === filterApplication);\r\n }\r\n\r\n // Category filter\r\n if (filterCategory !== 'all') {\r\n filtered = filtered.filter(r => (r.category || 'Custom') === filterCategory);\r\n }\r\n\r\n // Text search\r\n if (searchQuery.trim()) {\r\n const query = searchQuery.toLowerCase().trim();\r\n filtered = filtered.filter(r =>\r\n r.name.toLowerCase().includes(query) ||\r\n r.shortName?.toLowerCase().includes(query) ||\r\n r.description?.toLowerCase().includes(query)\r\n );\r\n }\r\n\r\n return filtered;\r\n }, [scopedRoles, filterApplication, filterCategory, searchQuery]);\r\n\r\n const handleAssignRole = useCallback(async (roleId: string) => {\r\n if (savingRef.current) return;\r\n savingRef.current = true;\r\n setSaving(roleId);\r\n setError(null);\r\n\r\n try {\r\n await groupsApi.assignRole(groupId, {\r\n roleId,\r\n isInheritable: true,\r\n tenantId: !modalIsGlobal && modalTenantId ? modalTenantId : undefined,\r\n });\r\n await onAssigned();\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('admin:userRoles.errors.assignFailed', 'Erreur lors de l\\'assignation du rôle'));\r\n } finally {\r\n setSaving(null);\r\n savingRef.current = false;\r\n }\r\n }, [groupId, modalIsGlobal, modalTenantId, onAssigned, t]);\r\n\r\n return (\r\n <div className=\"fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm\">\r\n <div className=\"relative w-full max-w-2xl h-[80vh] bg-[var(--bg-card)] rounded-[var(--radius-card)] shadow-2xl border border-[var(--border-color)] overflow-hidden flex flex-col animate-in fade-in zoom-in duration-200\">\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-[var(--border-color)]\">\r\n <div className=\"flex items-center gap-4\">\r\n <div>\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:userRoles.assignRole', 'Assigner un rôle')}\r\n </h2>\r\n </div>\r\n <TenantScopeSelector\r\n value={modalScope}\r\n onChange={setModalScope}\r\n adminTenants={modalTenants}\r\n />\r\n </div>\r\n <button\r\n onClick={onClose}\r\n className=\"p-1.5 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n\r\n {/* Error alert */}\r\n {error && (\r\n <div className=\"mx-6 mt-3 p-3 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] flex items-center gap-3\">\r\n <AlertCircle className=\"w-4 h-4 text-[var(--error-text)] flex-shrink-0\" />\r\n <p className=\"flex-1 text-sm text-[var(--error-text)]\">{error}</p>\r\n <button onClick={() => setError(null)}>\r\n <X className=\"w-3.5 h-3.5 text-[var(--error-text)]\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Filters */}\r\n <div className=\"px-6 py-3 border-b border-[var(--border-color)] flex flex-col gap-3\">\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]\" />\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n placeholder={t('admin:userRoles.search', 'Rechercher un rôle...')}\r\n className=\"w-full pl-10 pr-4 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] placeholder-[var(--text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n autoFocus\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-secondary)] shrink-0\" />\r\n <select\r\n value={filterApplication}\r\n onChange={(e) => setFilterApplication(e.target.value)}\r\n className=\"flex-1 min-w-0 px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:userRoles.filterByApplication', 'Toutes les applications')}</option>\r\n {applications.map(app => (\r\n <option key={app.id} value={app.id}>{app.name}</option>\r\n ))}\r\n </select>\r\n <select\r\n value={filterCategory}\r\n onChange={(e) => setFilterCategory(e.target.value)}\r\n className=\"flex-1 min-w-0 px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-[var(--radius-input)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:userRoles.filterByCategory', 'Toutes les catégories')}</option>\r\n {categories.filter(c => c !== 'all').map(cat => (\r\n <option key={cat} value={cat}>{cat}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n\r\n {/* Role list */}\r\n <div className=\"flex-1 overflow-y-auto\">\r\n {rolesLoading ? (\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 <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-tertiary)] sticky top-0 z-10\">\r\n <tr>\r\n <th className=\"text-left px-6 py-2.5 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.name', 'Rôle')}\r\n </th>\r\n <th className=\"text-left px-4 py-2.5 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:roles.category', 'Catégorie')}\r\n </th>\r\n <th className=\"text-right px-6 py-2.5 text-sm font-medium text-[var(--text-secondary)] w-32\">\r\n {t('admin:roles.actions', 'Actions')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredRoles.length === 0 ? (\r\n <tr>\r\n <td colSpan={3} className=\"px-6 py-12 text-center\">\r\n <Search className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-muted)]\">\r\n {t('admin:userRoles.noRoles', 'Aucun rôle trouvé')}\r\n </p>\r\n </td>\r\n </tr>\r\n ) : (\r\n filteredRoles.map((role) => {\r\n const isAlreadyAssigned = currentScopeRoleIds.has(role.id);\r\n const catStyle = CATEGORY_STYLES[role.category || 'Custom'] || DEFAULT_CATEGORY_STYLE;\r\n const customIcon = getCustomRoleIcon(role.code);\r\n const isAssigning = saving === role.id;\r\n\r\n return (\r\n <tr\r\n key={role.id}\r\n className={`transition-colors ${isAlreadyAssigned ? 'bg-[var(--accent-bg)] opacity-60' : 'hover:bg-[var(--bg-hover)]'}`}\r\n >\r\n <td className=\"px-6 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n {customIcon && <span>{customIcon}</span>}\r\n <div>\r\n <span className=\"font-medium text-[var(--text-primary)]\">{role.name}</span>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5 max-w-sm truncate\">{role.description}</p>\r\n )}\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-full ${catStyle.bg} ${catStyle.text}`}>\r\n {role.category || 'Custom'}\r\n </span>\r\n </td>\r\n <td className=\"px-6 py-3 text-right\">\r\n {isAlreadyAssigned ? (\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n {t('admin:userRoles.alreadyAssigned', 'Déjà assigné')}\r\n </span>\r\n ) : (\r\n <button\r\n onClick={() => handleAssignRole(role.id)}\r\n disabled={isAssigning}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white text-xs font-medium hover:bg-[var(--color-accent-700)] transition-colors disabled:opacity-50\"\r\n >\r\n {isAssigning ? (\r\n <Loader2 className=\"w-3.5 h-3.5 animate-spin\" />\r\n ) : (\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n )}\r\n {t('admin:userRoles.assign', 'Assigner')}\r\n </button>\r\n )}\r\n </td>\r\n </tr>\r\n );\r\n })\r\n )}\r\n </tbody>\r\n </table>\r\n )}\r\n </div>\r\n\r\n {/* Footer */}\r\n <div className=\"px-6 py-3 border-t border-[var(--border-color)] bg-[var(--bg-tertiary)] flex justify-end\">\r\n <button\r\n onClick={onClose}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors text-sm font-medium\"\r\n >\r\n {t('common:close', 'Fermer')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { Building2, Loader2, Plus, RefreshCw, Search, X, Trash2, AlertTriangle, CheckCircle, Check, LayoutGrid, LayoutList, GitBranch, Link as LinkIcon } from 'lucide-react';\r\nimport { Link } from 'react-router-dom';\r\nimport { groupsApi, type GroupTenantDto, type InheritedTenantDto } from '@/services/api/groupsApi';\r\nimport { adminApi, type TenantListDto } from '@/services/api/adminApi';\r\nimport { type ViewMode } from '@/components/ui/DataView';\r\nimport { useTenantTypeSettings } from '@/hooks/useTenantTypeSettings';\r\nimport { getLucideIcon, getColorClasses } from '@/utils/tenantIconMap';\r\n\r\ninterface GroupTenantsTabProps {\r\n readonly groupId: string;\r\n readonly groupName: string;\r\n}\r\n\r\nconst getSelectAllClass = (isAllSelected: boolean): string => {\r\n return isAllSelected\r\n ? 'bg-[var(--color-accent-600)] border-[var(--color-accent-600)]'\r\n : 'border-[var(--border-color)]';\r\n};\r\n\r\nconst getTenantItemClass = (isSelected: boolean): string => {\r\n return isSelected\r\n ? 'border-[var(--color-accent-500)] bg-[var(--color-accent-500)]/5'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)]';\r\n};\r\n\r\nconst getTenantCheckboxClass = (isSelected: boolean): string => {\r\n return isSelected\r\n ? 'bg-[var(--color-accent-600)] border-[var(--color-accent-600)]'\r\n : 'border-[var(--border-color)]';\r\n};\r\n\r\nconst filterAvailableTenants = (allTenants: any[] | null | undefined, assignedTenantIds: Set<string>, searchQuery: string): any[] => {\r\n if (!allTenants) return [];\r\n const query = searchQuery.toLowerCase().trim();\r\n return allTenants\r\n .filter(t => !assignedTenantIds.has(t.id))\r\n .filter(t => {\r\n if (!query) return true;\r\n return t.name.toLowerCase().includes(query) || t.slug.toLowerCase().includes(query) || t.type.toLowerCase().includes(query);\r\n });\r\n};\r\n\r\nconst filterAssignedTenants = (tenants: any[] | null, pageSearchQuery: string): any[] => {\r\n if (!tenants) return [];\r\n if (!pageSearchQuery.trim()) return tenants;\r\n const query = pageSearchQuery.toLowerCase().trim();\r\n return tenants.filter((t) =>\r\n t.tenantName.toLowerCase().includes(query) ||\r\n t.tenantSlug.toLowerCase().includes(query) ||\r\n t.tenantType.toLowerCase().includes(query)\r\n );\r\n};\r\n\r\nexport function GroupTenantsTab({ groupId, groupName }: GroupTenantsTabProps): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const navigate = useNavigate();\r\n const { getIconForType } = useTenantTypeSettings();\r\n\r\n const [tenants, setTenants] = useState<GroupTenantDto[] | null>(null);\r\n const [inheritedTenants, setInheritedTenants] = useState<InheritedTenantDto[]>([]);\r\n const [allTenants, setAllTenants] = useState<TenantListDto[] | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [showAddModal, setShowAddModal] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [removingTenantId, setRemovingTenantId] = useState<string | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n\r\n // Multi-select and view mode states\r\n const [selectedTenantIds, setSelectedTenantIds] = useState<string[]>([]);\r\n const [pageSearchQuery, setPageSearchQuery] = useState('');\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [adding, setAdding] = useState(false);\r\n\r\n const loadTenants = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const [data, inherited] = await Promise.all([\r\n groupsApi.getTenants(groupId),\r\n groupsApi.getInheritedTenants(groupId),\r\n ]);\r\n setTenants(data);\r\n setInheritedTenants(inherited);\r\n } catch (err) {\r\n console.error('Failed to load group tenants:', err);\r\n setError(t('groups:tenants.loadError', 'Erreur lors du chargement des tenants'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [groupId, t]);\r\n\r\n const loadAllTenants = async () => {\r\n try {\r\n const result = await adminApi.tenants.getAll();\r\n setAllTenants(result.items);\r\n } catch (err) {\r\n console.error('Failed to load all tenants:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadTenants();\r\n loadAllTenants();\r\n }, [loadTenants]);\r\n\r\n const handleRemoveTenant = async (tenantId: string) => {\r\n const tenant = tenants?.find((t) => t.tenantId === tenantId);\r\n if (!confirm(t('groups:tenants.confirmRemove', `Êtes-vous sûr de vouloir retirer le groupe \"${groupName}\" du tenant \"${tenant?.tenantName}\" ?`))) {\r\n return;\r\n }\r\n\r\n try {\r\n setRemovingTenantId(tenantId);\r\n setError(null);\r\n await groupsApi.removeFromTenant(groupId, tenantId);\r\n await loadTenants();\r\n setSuccess(t('groups:tenants.removeSuccess', 'Tenant retiré avec succès'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err: any) {\r\n console.error('Failed to remove tenant:', err);\r\n const errorMessage = err?.response?.data?.message || t('groups:tenants.removeError', 'Erreur lors du retrait du tenant');\r\n setError(errorMessage);\r\n } finally {\r\n setRemovingTenantId(null);\r\n }\r\n };\r\n\r\n const addTenantsAndTrackResults = async (): Promise<{ successCount: number; failedTenants: string[] }> => {\r\n let successCount = 0;\r\n const failedTenants: string[] = [];\r\n\r\n for (const tenantId of selectedTenantIds) {\r\n try {\r\n await groupsApi.addToTenant(groupId, { tenantId });\r\n successCount++;\r\n } catch {\r\n const tenantName = filteredAvailableTenants?.find((t) => t.id === tenantId)?.name;\r\n failedTenants.push(tenantName || tenantId);\r\n }\r\n }\r\n\r\n return { successCount, failedTenants };\r\n };\r\n\r\n const handleAddSelectedTenants = async () => {\r\n if (selectedTenantIds.length === 0) return;\r\n\r\n try {\r\n setAdding(true);\r\n setError(null);\r\n const { successCount, failedTenants } = await addTenantsAndTrackResults();\r\n\r\n await loadTenants();\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedTenantIds([]);\r\n\r\n if (failedTenants.length === 0) {\r\n setSuccess(t('groups:tenants.addSelectedSuccess', { count: successCount }));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } else if (successCount > 0) {\r\n setError(t('groups:tenants.addPartialError', {\r\n success: successCount,\r\n failed: failedTenants.join(', ')\r\n }));\r\n } else {\r\n setError(t('groups:tenants.addSelectedError', 'Erreur lors de l\\'ajout des tenants'));\r\n }\r\n } catch (err: any) {\r\n console.error('Failed to add tenants:', err);\r\n setError(t('groups:tenants.addSelectedError', 'Erreur lors de l\\'ajout des tenants'));\r\n } finally {\r\n setAdding(false);\r\n }\r\n };\r\n\r\n const toggleTenantSelection = (tenantId: string) => {\r\n setSelectedTenantIds((prev) =>\r\n prev.includes(tenantId)\r\n ? prev.filter((id) => id !== tenantId)\r\n : [...prev, tenantId]\r\n );\r\n };\r\n\r\n const toggleSelectAll = () => {\r\n if (!filteredAvailableTenants) return;\r\n const allIds = filteredAvailableTenants.map((t) => t.id);\r\n const allSelected = allIds.every((id) => selectedTenantIds.includes(id));\r\n setSelectedTenantIds(allSelected ? [] : allIds);\r\n };\r\n\r\n // Filter available tenants (not already assigned)\r\n const assignedTenantIds = useMemo(() => new Set(tenants?.map(t => t.tenantId) ?? []), [tenants]);\r\n const availableTenants = useMemo(() => filterAvailableTenants(allTenants, assignedTenantIds, searchQuery), [allTenants, assignedTenantIds, searchQuery]);\r\n\r\n // Filter by search query (modal)\r\n const filteredAvailableTenants = availableTenants;\r\n\r\n // Filter tenants on page by search query\r\n const filteredTenants = useMemo(() => filterAssignedTenants(tenants, pageSearchQuery), [tenants, pageSearchQuery]);\r\n\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\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)] flex items-center gap-2\">\r\n <Building2 className=\"w-5 h-5\" />\r\n {t('groups:tenants.title', 'Tenants du groupe')}\r\n {tenants && (\r\n <span className=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {tenants.length}\r\n </span>\r\n )}\r\n </h3>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:tenants.add', 'Ajouter')}\r\n </button>\r\n <button\r\n onClick={loadTenants}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Search and View Toggle */}\r\n {(tenants?.length ?? 0) > 0 && (\r\n <div className=\"flex flex-col sm:flex-row items-stretch sm:items-center gap-3\">\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('groups:tenants.searchPlaceholderPage', 'Rechercher un tenant...')}\r\n value={pageSearchQuery}\r\n onChange={(e) => setPageSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-lg 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 <div className=\"flex items-center gap-1 p-1 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setViewMode('cards')}\r\n className={`px-3 py-1.5 rounded-[var(--radius-button)] text-sm font-medium flex items-center gap-2 transition-all ${\r\n viewMode === 'cards'\r\n ? 'bg-[var(--color-accent-600)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('groups:tenants.viewCards', 'Cartes')}</span>\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`px-3 py-1.5 rounded-[var(--radius-button)] text-sm font-medium flex items-center gap-2 transition-all ${\r\n viewMode === 'table'\r\n ? 'bg-[var(--color-accent-600)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <LayoutList className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('groups:tenants.viewTable', 'Table')}</span>\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Alerts */}\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-red-500/10 border border-red-500/20 flex items-center gap-3\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-500 flex-shrink-0\" />\r\n <p className=\"text-red-500\">{error}</p>\r\n <button onClick={() => setError(null)} className=\"ml-auto\">\r\n <X className=\"w-4 h-4 text-red-500\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {success && (\r\n <div className=\"p-4 rounded-lg bg-green-500/10 border border-green-500/20 flex items-center gap-3\">\r\n <CheckCircle className=\"w-5 h-5 text-green-500 flex-shrink-0\" />\r\n <p className=\"text-green-500\">{success}</p>\r\n </div>\r\n )}\r\n\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-lg bg-blue-500/10 border border-blue-500/20\">\r\n <p className=\"text-sm text-blue-500\">\r\n {t('groups:tenants.info', 'Les utilisateurs de ce groupe auront automatiquement accès aux tenants listés ci-dessous via leur appartenance au groupe.')}\r\n </p>\r\n </div>\r\n\r\n {/* Content */}\r\n {loading && (\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 {!loading && (!tenants || tenants.length === 0) && (\r\n <div className=\"text-center py-12\">\r\n <Building2 className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)] mb-4\">\r\n {t('groups:tenants.noTenants', 'Ce groupe n\\'est associé à aucun tenant')}\r\n </p>\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:tenants.addFirst', 'Ajouter un premier tenant')}\r\n </button>\r\n </div>\r\n )}\r\n {!loading && (tenants?.length ?? 0) > 0 && (filteredTenants?.length ?? 0) === 0 && (\r\n <div className=\"text-center py-12\">\r\n <Search className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('groups:tenants.noResults', 'Aucun tenant ne correspond à votre recherche')}\r\n </p>\r\n </div>\r\n )}\r\n {!loading && (filteredTenants?.length ?? 0) > 0 && viewMode === 'cards' && (\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {filteredTenants?.map((tenant) => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={tenant.tenantId}\r\n onClick={() => navigate(`/administration/tenants/${tenant.tenantId}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/tenants/${tenant.tenantId}`); } }}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left\"\r\n >\r\n {(() => {\r\n const typeInfo = getIconForType(tenant.tenantType);\r\n const TenantIcon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return (\r\n <>\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2 rounded-lg ${colors.bg}`}>\r\n <TenantIcon className={`w-5 h-5 ${colors.text}`} />\r\n </div>\r\n <div className=\"min-w-0\">\r\n <h4 className=\"text-sm font-semibold text-[var(--color-accent-500)] hover:underline truncate\">\r\n {tenant.tenantName}\r\n </h4>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{tenant.tenantSlug}</p>\r\n </div>\r\n </div>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${colors.bg} ${colors.text}`}>\r\n {tenant.tenantType}\r\n </span>\r\n </div>\r\n\r\n <div className=\"mt-3 pt-3 border-t border-[var(--border-color)] space-y-1\">\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:tenants.addedAt', 'Ajouté le')}: {new Date(tenant.addedAt).toLocaleDateString()}\r\n </p>\r\n {tenant.addedBy && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:tenants.addedBy', 'Par')}: {tenant.addedBy}\r\n </p>\r\n )}\r\n </div>\r\n\r\n <div className=\"mt-3 flex justify-end\">\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleRemoveTenant(tenant.tenantId); }}\r\n disabled={removingTenantId === tenant.tenantId}\r\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingTenantId === tenant.tenantId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </div>\r\n </>\r\n );\r\n })()}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n {!loading && (filteredTenants?.length ?? 0) > 0 && viewMode !== 'cards' && (\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">\r\n {t('groups:tenants.tableHeaders.name', 'Nom')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">\r\n {t('groups:tenants.tableHeaders.slug', 'Slug')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">\r\n {t('groups:tenants.tableHeaders.type', 'Type')}\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">\r\n {t('groups:tenants.tableHeaders.addedAt', 'Ajouté le')}\r\n </th>\r\n <th className=\"w-24 px-4 py-3\"></th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredTenants?.map((tenant) => (\r\n <tr key={tenant.tenantId} onClick={() => navigate(`/administration/tenants/${tenant.tenantId}`)} className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer\">\r\n {(() => {\r\n const typeInfo = getIconForType(tenant.tenantType);\r\n const RowIcon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return (\r\n <>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={`p-1.5 rounded-lg ${colors.bg}`}>\r\n <RowIcon className={`w-4 h-4 ${colors.text}`} />\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)] hover:underline\">{tenant.tenantName}</span>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)] hidden md:table-cell\">\r\n {tenant.tenantSlug}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${colors.bg} ${colors.text}`}>\r\n {tenant.tenantType}\r\n </span>\r\n </td>\r\n </>\r\n );\r\n })()}\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-tertiary)] hidden lg:table-cell\">\r\n {new Date(tenant.addedAt).toLocaleDateString()}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleRemoveTenant(tenant.tenantId); }}\r\n disabled={removingTenantId === tenant.tenantId}\r\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingTenantId === tenant.tenantId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n\r\n {/* Inherited Tenants */}\r\n {!loading && inheritedTenants.length > 0 && (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <GitBranch className=\"w-5 h-5\" />\r\n {t('groups:tenants.inheritedTitle')}\r\n <span className=\"ml-1 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {inheritedTenants.length}\r\n </span>\r\n </h3>\r\n\r\n <div className=\"p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:tenants.inheritedInfo')}\r\n </p>\r\n </div>\r\n\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {inheritedTenants.map((tenant) => (\r\n <button\r\n type=\"button\"\r\n key={`inherited-${tenant.tenantId}-${tenant.inheritedFromGroupId}`}\r\n onClick={() => navigate(`/administration/tenants/${tenant.tenantId}`)}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-dashed border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left\"\r\n >\r\n {(() => {\r\n const typeInfo = getIconForType(tenant.tenantType);\r\n const InheritedIcon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return (\r\n <>\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2 rounded-lg ${colors.bg}`}>\r\n <InheritedIcon className={`w-5 h-5 ${colors.text}`} />\r\n </div>\r\n <div className=\"min-w-0\">\r\n <h4 className=\"text-sm font-semibold text-[var(--color-accent-500)] hover:underline truncate\">\r\n {tenant.tenantName}\r\n </h4>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{tenant.tenantSlug}</p>\r\n </div>\r\n </div>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${colors.bg} ${colors.text}`}>\r\n {tenant.tenantType}\r\n </span>\r\n </div>\r\n\r\n <div className=\"mt-3 pt-3 border-t border-[var(--border-color)]\">\r\n <Link\r\n to={`/administration/users/groups/${tenant.inheritedFromGroupId}`}\r\n onClick={(e) => e.stopPropagation()}\r\n className=\"flex items-center gap-1.5 text-xs text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <LinkIcon className=\"w-3 h-3\" />\r\n {t('groups:tenants.inheritedFrom')} <span className=\"font-medium\">{tenant.inheritedFromGroupName}</span>\r\n </Link>\r\n </div>\r\n </>\r\n );\r\n })()}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Add Tenant Modal */}\r\n {showAddModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-lg mx-4 bg-[var(--bg-primary)] rounded-[var(--radius-card)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('groups:tenants.addModalTitle', 'Ajouter le groupe à des tenants')}\r\n </h3>\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedTenantIds([]);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"p-4 space-y-4\">\r\n {/* Search */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('groups:tenants.searchPlaceholder', 'Rechercher un tenant...')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-lg 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 autoFocus\r\n />\r\n </div>\r\n\r\n {/* Select All */}\r\n {(filteredAvailableTenants?.length ?? 0) > 0 && (\r\n <div className=\"flex items-center justify-between px-1\">\r\n <button\r\n onClick={toggleSelectAll}\r\n className=\"flex items-center gap-2 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] transition-colors\"\r\n >\r\n <div className={`w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${getSelectAllClass(filteredAvailableTenants.every((t) => selectedTenantIds.includes(t.id)))}`}>\r\n {filteredAvailableTenants.every((t) => selectedTenantIds.includes(t.id)) && (\r\n <Check className=\"w-3 h-3 text-white\" />\r\n )}\r\n </div>\r\n {filteredAvailableTenants.every((t) => selectedTenantIds.includes(t.id))\r\n ? t('groups:tenants.deselectAll', 'Tout désélectionner')\r\n : t('groups:tenants.selectAll', 'Tout sélectionner')}\r\n </button>\r\n {selectedTenantIds.length > 0 && (\r\n <span className=\"text-xs text-[var(--text-tertiary)]\">\r\n {selectedTenantIds.length} {t('common.selected', 'sélectionné(s)')}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Tenant List */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {!filteredAvailableTenants || filteredAvailableTenants.length === 0 ? (\r\n <div className=\"text-center py-8\">\r\n <Building2 className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('groups:tenants.noAvailableTenants', 'Aucun tenant disponible')}\r\n </p>\r\n </div>\r\n ) : (\r\n filteredAvailableTenants.map((tenant) => {\r\n const isSelected = selectedTenantIds.includes(tenant.id);\r\n const modalTypeInfo = getIconForType(tenant.type);\r\n const ModalIcon = getLucideIcon(modalTypeInfo.icon);\r\n const modalColors = getColorClasses(modalTypeInfo.color);\r\n return (\r\n <button\r\n type=\"button\"\r\n key={tenant.id}\r\n onClick={() => toggleTenantSelection(tenant.id)}\r\n className={`w-full flex items-center gap-3 p-3 rounded-lg border cursor-pointer transition-colors text-left ${getTenantItemClass(isSelected)}`}\r\n >\r\n <div className={`w-5 h-5 rounded border-2 flex items-center justify-center flex-shrink-0 transition-colors ${getTenantCheckboxClass(isSelected)}`}>\r\n {isSelected && <Check className=\"w-3 h-3 text-white\" />}\r\n </div>\r\n <div className={`p-2 rounded-lg ${modalColors.bg}`}>\r\n <ModalIcon className={`w-4 h-4 ${modalColors.text}`} />\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {tenant.name}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{tenant.slug}</p>\r\n </div>\r\n <span className={`px-2 py-0.5 text-xs rounded-full ${modalColors.bg} ${modalColors.text}`}>\r\n {tenant.type}\r\n </span>\r\n </button>\r\n );\r\n })\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex justify-end gap-2 p-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedTenantIds([]);\r\n }}\r\n className=\"px-4 py-2 rounded-lg bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel', 'Annuler')}\r\n </button>\r\n <button\r\n onClick={handleAddSelectedTenants}\r\n disabled={selectedTenantIds.length === 0 || adding}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n {adding ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Plus className=\"w-4 h-4\" />\r\n )}\r\n {t('groups:tenants.addSelected', { count: selectedTenantIds.length })}\r\n </button>\r\n </div>\r\n </div>\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 { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport { Users, Loader2, Plus, RefreshCw, Search, X, Trash2, AlertTriangle, CheckCircle, Info, Table, LayoutGrid, Check } from 'lucide-react';\r\nimport { groupsApi, type GroupMemberDto } from '@/services/api/groupsApi';\r\nimport { adminApi, type UserListDto } from '@/services/api/adminApi';\r\n\r\ntype ViewMode = 'table' | 'card';\r\n\r\ninterface GroupMembersTabProps {\r\n readonly groupId: string;\r\n readonly groupName: string;\r\n readonly isSyncedFromEntra: boolean;\r\n}\r\n\r\nexport function GroupMembersTab({ groupId, groupName, isSyncedFromEntra }: GroupMembersTabProps): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const navigate = useNavigate();\r\n\r\n const [members, setMembers] = useState<GroupMemberDto[] | null>(null);\r\n const [allUsers, setAllUsers] = useState<UserListDto[] | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [showAddModal, setShowAddModal] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [removingUserId, setRemovingUserId] = useState<string | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('table');\r\n const [selectedUserIds, setSelectedUserIds] = useState<Set<string>>(new Set());\r\n const [isAddingMultiple, setIsAddingMultiple] = useState(false);\r\n\r\n const loadMembers = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const data = await groupsApi.getMembers(groupId);\r\n setMembers(data);\r\n } catch (err) {\r\n console.error('Failed to load group members:', err);\r\n setError(t('groups:members.loadError', 'Erreur lors du chargement des membres'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [groupId, t]);\r\n\r\n const loadAllUsers = async () => {\r\n try {\r\n // globalScope: true to get ALL users regardless of tenant context\r\n // Groups are system-level entities, so we need all users for member management\r\n const response = await adminApi.users.getAll({ isActive: true, globalScope: true });\r\n // Handle both array and paginated response\r\n const users = Array.isArray(response) ? response : response.items;\r\n setAllUsers(users);\r\n } catch (err) {\r\n console.error('Failed to load all users:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadMembers();\r\n loadAllUsers();\r\n }, [loadMembers]);\r\n\r\n const handleAddMultipleMembers = async () => {\r\n if (selectedUserIds.size === 0) return;\r\n\r\n try {\r\n setIsAddingMultiple(true);\r\n setError(null);\r\n\r\n const userIdsArray = Array.from(selectedUserIds);\r\n for (const userId of userIdsArray) {\r\n await groupsApi.addMember(groupId, { userId });\r\n }\r\n\r\n await loadMembers();\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedUserIds(new Set());\r\n setSuccess(t('groups:members.addMultipleSuccess', { count: userIdsArray.length }));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err: any) {\r\n console.error('Failed to add members:', err);\r\n const errorMessage = err?.response?.data?.message || t('groups:members.addError', 'Erreur lors de l\\'ajout des membres');\r\n setError(errorMessage);\r\n } finally {\r\n setIsAddingMultiple(false);\r\n }\r\n };\r\n\r\n const toggleUserSelection = (userId: string) => {\r\n setSelectedUserIds(prev => {\r\n const next = new Set(prev);\r\n if (next.has(userId)) {\r\n next.delete(userId);\r\n } else {\r\n next.add(userId);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const handleRemoveMember = async (userId: string) => {\r\n const member = members?.find((m) => m.userId === userId);\r\n if (!confirm(t('groups:members.confirmRemove', { userName: member?.fullName, groupName }))) {\r\n return;\r\n }\r\n\r\n try {\r\n setRemovingUserId(userId);\r\n setError(null);\r\n await groupsApi.removeMember(groupId, userId);\r\n await loadMembers();\r\n setSuccess(t('groups:members.removeSuccess', 'Membre retiré avec succès'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err: any) {\r\n console.error('Failed to remove member:', err);\r\n const errorMessage = err?.response?.data?.message || t('groups:members.removeError', 'Erreur lors du retrait du membre');\r\n setError(errorMessage);\r\n } finally {\r\n setRemovingUserId(null);\r\n }\r\n };\r\n\r\n // Filter available users (not already members)\r\n const availableUsers = allUsers?.filter(\r\n (u) => !members?.some((m) => m.userId === u.id)\r\n );\r\n\r\n // Filter by search query\r\n const filteredAvailableUsers = availableUsers?.filter((u) => {\r\n if (!searchQuery.trim()) return true;\r\n const query = searchQuery.toLowerCase().trim();\r\n return (\r\n u.fullName.toLowerCase().includes(query) ||\r\n u.email.toLowerCase().includes(query)\r\n );\r\n });\r\n\r\n const getInitials = (name: string) => {\r\n return name\r\n .split(' ')\r\n .map((part) => part.charAt(0))\r\n .slice(0, 2)\r\n .join('')\r\n .toUpperCase();\r\n };\r\n\r\n const getViewModeButtonClass = (isActive: boolean): string => {\r\n return isActive\r\n ? 'p-2 transition-colors bg-[var(--color-accent-500)] text-white'\r\n : 'p-2 transition-colors bg-[var(--bg-primary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]';\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:members.title', 'Membres du groupe')}\r\n {members && (\r\n <span className=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {members.length}\r\n </span>\r\n )}\r\n </h3>\r\n <div className=\"flex items-center gap-2\">\r\n {/* View mode toggle */}\r\n <div className=\"flex items-center rounded-lg border border-[var(--border-color)] overflow-hidden\">\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={getViewModeButtonClass(viewMode === 'table')}\r\n title={t('common.tableView', 'Vue tableau')}\r\n >\r\n <Table className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('card')}\r\n className={getViewModeButtonClass(viewMode === 'card')}\r\n title={t('common.cardView', 'Vue cartes')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n\r\n {!isSyncedFromEntra && (\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:members.add', 'Ajouter des membres')}\r\n </button>\r\n )}\r\n <button\r\n onClick={loadMembers}\r\n className=\"flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common.refresh', 'Actualiser')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Alerts */}\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-red-500/10 border border-red-500/20 flex items-center gap-3\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-500 flex-shrink-0\" />\r\n <p className=\"text-red-500\">{error}</p>\r\n <button onClick={() => setError(null)} className=\"ml-auto\">\r\n <X className=\"w-4 h-4 text-red-500\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {success && (\r\n <div className=\"p-4 rounded-lg bg-green-500/10 border border-green-500/20 flex items-center gap-3\">\r\n <CheckCircle className=\"w-5 h-5 text-green-500 flex-shrink-0\" />\r\n <p className=\"text-green-500\">{success}</p>\r\n </div>\r\n )}\r\n\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-lg bg-blue-500/10 border border-blue-500/20\">\r\n <p className=\"text-sm text-blue-500\">\r\n {t('groups:members.info', 'Les membres de ce groupe héritent automatiquement des rôles et permissions attribués au groupe.')}\r\n </p>\r\n </div>\r\n\r\n {/* Entra sync warning */}\r\n {isSyncedFromEntra && (\r\n <div className=\"p-4 rounded-lg bg-amber-500/10 border border-amber-500/20 flex items-start gap-3\">\r\n <Info className=\"w-5 h-5 text-amber-500 flex-shrink-0 mt-0.5\" />\r\n <p className=\"text-sm text-amber-500\">\r\n {t('groups:members.readOnlyEntra', 'Les membres de ce groupe sont synchronisés depuis Microsoft Entra ID et ne peuvent pas être modifiés ici.')}\r\n </p>\r\n </div>\r\n )}\r\n\r\n {/* Content */}\r\n {loading && (\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 {!loading && (!members || members.length === 0) && (\r\n <div className=\"text-center py-12\">\r\n <Users className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)] mb-4\">\r\n {t('groups:members.noMembers', 'Ce groupe n\\'a aucun membre')}\r\n </p>\r\n {!isSyncedFromEntra && (\r\n <button\r\n onClick={() => setShowAddModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:members.addFirst', 'Ajouter un premier membre')}\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n {!loading && (members?.length ?? 0) > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"overflow-x-auto rounded-[var(--radius-card)] border border-[var(--border-color)]\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-secondary)]\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.member', 'Membre')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.email', 'Email')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.addedAt', 'Ajouté le')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('groups:members.table.addedBy', 'Par')}\r\n </th>\r\n {!isSyncedFromEntra && (\r\n <th className=\"px-4 py-3 text-right text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wider\">\r\n {t('common.actions', 'Actions')}\r\n </th>\r\n )}\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {members?.map((member) => (\r\n <tr\r\n key={member.userId}\r\n className=\"bg-[var(--bg-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <button\r\n className=\"flex items-center gap-3 cursor-pointer text-left bg-transparent border-0 p-0 hover:opacity-80 transition-opacity\"\r\n onClick={() => navigate(`/administration/users/${member.userId}`)}\r\n >\r\n <div className=\"w-8 h-8 rounded-full bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-xs font-medium text-[var(--color-accent-500)]\">\r\n {getInitials(member.fullName)}\r\n </span>\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)] hover:text-[var(--color-accent-500)]\">\r\n {member.fullName}\r\n </span>\r\n </button>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {member.email}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {new Date(member.addedAt).toLocaleDateString()}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {member.addedBy || '-'}\r\n </td>\r\n {!isSyncedFromEntra && (\r\n <td className=\"px-4 py-3 text-right\">\r\n <button\r\n onClick={() => handleRemoveMember(member.userId)}\r\n disabled={removingUserId === member.userId}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingUserId === member.userId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </td>\r\n )}\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n {!loading && (members?.length ?? 0) > 0 && viewMode !== 'table' && (\r\n /* Card View */\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\r\n {members?.map((member) => (\r\n <div\r\n key={member.userId}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <div className=\"flex items-start justify-between gap-3\">\r\n <button\r\n className=\"flex items-start gap-3 min-w-0 cursor-pointer text-left bg-transparent border-0 p-0 hover:opacity-80 transition-opacity\"\r\n onClick={() => navigate(`/administration/users/${member.userId}`)}\r\n >\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)]\">\r\n {getInitials(member.fullName)}\r\n </span>\r\n </div>\r\n <div className=\"min-w-0\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </h4>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{member.email}</p>\r\n </div>\r\n </button>\r\n </div>\r\n\r\n <div className=\"mt-3 pt-3 border-t border-[var(--border-color)] space-y-1\">\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:members.addedAt', 'Ajouté le')}: {new Date(member.addedAt).toLocaleDateString()}\r\n </p>\r\n {member.addedBy && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">\r\n {t('groups:members.addedBy', 'Par')}: {member.addedBy}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {!isSyncedFromEntra && (\r\n <div className=\"mt-3 flex justify-end\">\r\n <button\r\n onClick={() => handleRemoveMember(member.userId)}\r\n disabled={removingUserId === member.userId}\r\n className=\"flex items-center gap-1 px-2 py-1 rounded text-xs text-red-500 hover:bg-red-500/10 transition-colors disabled:opacity-50\"\r\n >\r\n {removingUserId === member.userId ? (\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n ) : (\r\n <Trash2 className=\"w-3 h-3\" />\r\n )}\r\n {t('common.remove', 'Retirer')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Add Member Modal */}\r\n {showAddModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-lg mx-4 bg-[var(--bg-primary)] rounded-[var(--radius-card)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <div>\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('groups:members.addModalTitle', 'Ajouter des membres au groupe')}\r\n </h3>\r\n {selectedUserIds.size > 0 && (\r\n <p className=\"text-sm text-[var(--color-accent-500)] mt-1\">\r\n {t('groups:members.selectedCount', { count: selectedUserIds.size })}\r\n </p>\r\n )}\r\n </div>\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedUserIds(new Set());\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"p-4 space-y-4\">\r\n {/* Search */}\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('groups:members.searchPlaceholder', 'Rechercher un utilisateur...')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-lg 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 autoFocus\r\n />\r\n </div>\r\n\r\n {/* User List */}\r\n <div className=\"max-h-[300px] overflow-y-auto space-y-2\">\r\n {!filteredAvailableUsers || filteredAvailableUsers.length === 0 ? (\r\n <div className=\"text-center py-8\">\r\n <Users className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('groups:members.noAvailableUsers', 'Aucun utilisateur disponible')}\r\n </p>\r\n </div>\r\n ) : (\r\n filteredAvailableUsers.map((user) => {\r\n const isSelected = selectedUserIds.has(user.id);\r\n return (\r\n <button\r\n key={user.id}\r\n onClick={() => toggleUserSelection(user.id)}\r\n disabled={isAddingMultiple}\r\n className={`w-full flex items-center gap-3 p-3 rounded-lg border transition-colors text-left disabled:opacity-50 ${\r\n isSelected\r\n ? 'border-[var(--color-accent-500)] bg-[var(--color-accent-500)]/10'\r\n : 'border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n {/* Checkbox indicator */}\r\n <div\r\n className={`w-5 h-5 rounded border-2 flex items-center justify-center flex-shrink-0 transition-colors ${\r\n isSelected\r\n ? 'border-[var(--color-accent-500)] bg-[var(--color-accent-500)]'\r\n : 'border-[var(--border-color)]'\r\n }`}\r\n >\r\n {isSelected && <Check className=\"w-3 h-3 text-white\" />}\r\n </div>\r\n\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)]\">\r\n {getInitials(user.fullName)}\r\n </span>\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {user.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{user.email}</p>\r\n </div>\r\n </button>\r\n );\r\n })\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex justify-between items-center gap-2 p-4 border-t border-[var(--border-color)]\">\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n {selectedUserIds.size > 0 && (\r\n <button\r\n onClick={() => setSelectedUserIds(new Set())}\r\n className=\"text-[var(--color-accent-500)] hover:underline\"\r\n >\r\n {t('common.clearSelection', 'Effacer la sélection')}\r\n </button>\r\n )}\r\n </div>\r\n <div className=\"flex gap-2\">\r\n <button\r\n onClick={() => {\r\n setShowAddModal(false);\r\n setSearchQuery('');\r\n setSelectedUserIds(new Set());\r\n }}\r\n className=\"px-4 py-2 rounded-lg bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel', 'Annuler')}\r\n </button>\r\n <button\r\n onClick={handleAddMultipleMembers}\r\n disabled={selectedUserIds.size === 0 || isAddingMultiple}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-lg bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n {isAddingMultiple ? (\r\n <>\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n {t('common.adding', 'Ajout...')}\r\n </>\r\n ) : (\r\n <>\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:members.addSelected', { count: selectedUserIds.size })}\r\n </>\r\n )}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useCallback } from 'react';\r\nimport { adminApi } from '@/services/api/adminApi';\r\nimport { groupsApi } from '@/services/api/groupsApi';\r\nimport type { RoleDto } from '@/services/api/adminApi';\r\nimport type { GroupDetailDto } from '@/services/api/groupsApi';\r\nimport { useEntityPermissions } from './useEntityPermissions';\r\nimport type { PermissionInheritanceInfo } from '@/components/platform/administration/permissions/types';\r\n\r\n/**\r\n * Extended RoleDto with tenant scope information from GroupRoleDto.\r\n */\r\nexport interface GroupRoleWithScope extends RoleDto {\r\n /** The tenant this role assignment is scoped to (null = global) */\r\n tenantId: string | null;\r\n /** The tenant name for display */\r\n tenantName: string | null;\r\n /** Whether this is a global role assignment */\r\n isGlobal: boolean;\r\n}\r\n\r\nexport interface UseGroupPermissionsOptions {\r\n groupId: string;\r\n /** Optional tenant context - when provided, loads tenant-scoped roles */\r\n tenantId?: string;\r\n}\r\n\r\nexport interface UseGroupPermissionsResult {\r\n loading: boolean;\r\n error: string | null;\r\n group: GroupDetailDto | null;\r\n groupRoles: GroupRoleWithScope[];\r\n resources: ReturnType<typeof useEntityPermissions>['resources'];\r\n assignments: ReturnType<typeof useEntityPermissions>['assignments'];\r\n inheritanceMap: ReturnType<typeof useEntityPermissions>['inheritanceMap'];\r\n effectivePermissions: ReturnType<typeof useEntityPermissions>['effectivePermissions'];\r\n filters: ReturnType<typeof useEntityPermissions>['filters'];\r\n filteredResources: ReturnType<typeof useEntityPermissions>['filteredResources'];\r\n applications: ReturnType<typeof useEntityPermissions>['applications'];\r\n modules: ReturnType<typeof useEntityPermissions>['modules'];\r\n updateFilters: ReturnType<typeof useEntityPermissions>['updateFilters'];\r\n getPermissionInheritance: (roleId: string, permissionId: string) => PermissionInheritanceInfo;\r\n getPermissionSources: (permissionId: string) => GroupRoleWithScope[];\r\n reloadData: () => Promise<void>;\r\n /** Whether we're in tenant-scoped mode */\r\n isTenantMode: boolean;\r\n}\r\n\r\nexport function useGroupPermissions(options: UseGroupPermissionsOptions): UseGroupPermissionsResult {\r\n const { groupId, tenantId } = options;\r\n\r\n const loadGroup = useCallback(async (id: string) => {\r\n return groupsApi.getById(id);\r\n }, []);\r\n\r\n const loadGroupRoles = useCallback(async (id: string, tid?: string): Promise<GroupRoleWithScope[]> => {\r\n const [groupData, matrixData] = await Promise.all([\r\n groupsApi.getById(id),\r\n adminApi.permissions.getMatrix(),\r\n ]);\r\n\r\n const matrixRoleMap = new Map(matrixData.roles.map(r => [r.id, r]));\r\n\r\n const allRoles: GroupRoleWithScope[] = groupData.roles\r\n .map(gr => {\r\n const matrixRole = matrixRoleMap.get(gr.roleId);\r\n if (!matrixRole) return null;\r\n\r\n return {\r\n id: gr.roleId,\r\n name: matrixRole.name,\r\n shortName: matrixRole.shortName || matrixRole.name,\r\n category: matrixRole.category || ('Custom' as const),\r\n description: matrixRole.description ?? null,\r\n tenantId: gr.tenantId ?? null,\r\n tenantName: gr.tenantName ?? null,\r\n isGlobal: gr.isGlobal,\r\n } as GroupRoleWithScope;\r\n })\r\n .filter((r): r is GroupRoleWithScope => r !== null);\r\n\r\n const rolesToUse = tid\r\n ? allRoles.filter(role => role.isGlobal || role.tenantId === tid)\r\n : allRoles;\r\n\r\n return rolesToUse;\r\n }, []);\r\n\r\n const baseResult = useEntityPermissions<GroupRoleWithScope, GroupDetailDto>({\r\n entityId: groupId,\r\n tenantId,\r\n loadEntity: loadGroup,\r\n loadRoles: loadGroupRoles,\r\n });\r\n\r\n const group = baseResult.entity;\r\n const groupRoles = baseResult.roles;\r\n\r\n const getPermissionSources = useCallback((permissionId: string): GroupRoleWithScope[] => {\r\n const sources: GroupRoleWithScope[] = [];\r\n\r\n groupRoles.forEach(role => {\r\n const roleInheritance = baseResult.inheritanceMap[role.id];\r\n if (roleInheritance) {\r\n const info = roleInheritance.get(permissionId);\r\n if (info && (info.isDirect || info.isInherited)) {\r\n sources.push(role);\r\n }\r\n }\r\n });\r\n\r\n return sources;\r\n }, [groupRoles, baseResult.inheritanceMap]);\r\n\r\n return {\r\n loading: baseResult.loading,\r\n error: baseResult.error,\r\n group,\r\n groupRoles,\r\n resources: baseResult.resources,\r\n assignments: baseResult.assignments,\r\n inheritanceMap: baseResult.inheritanceMap,\r\n effectivePermissions: baseResult.effectivePermissions,\r\n filters: baseResult.filters,\r\n filteredResources: baseResult.filteredResources,\r\n applications: baseResult.applications,\r\n modules: baseResult.modules,\r\n updateFilters: baseResult.updateFilters,\r\n getPermissionInheritance: baseResult.getPermissionInheritance,\r\n getPermissionSources,\r\n reloadData: baseResult.reloadData,\r\n isTenantMode: baseResult.isTenantMode,\r\n };\r\n}\r\n","import type { ReactElement } from 'react';\r\nimport React, { useState, useMemo, useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Check,\r\n Star,\r\n Eye,\r\n Ban,\r\n ChevronRight,\r\n ChevronDown,\r\n FolderOpen,\r\n Box,\r\n FileText,\r\n Shield,\r\n Info,\r\n Loader2,\r\n AlertCircle,\r\n Plus,\r\n Edit,\r\n Trash2,\r\n UserPlus,\r\n Play,\r\n Database,\r\n UserCheck,\r\n User,\r\n} from 'lucide-react';\r\nimport { useGroupPermissions } from '@/hooks/useGroupPermissions';\r\nimport { useCollapsibleState } from '@/hooks/useCollapsibleState';\r\nimport { groupByApplicationWithSections, calculatePermissionStatus, calculateModuleWithSectionsStatus, getPermissionCellBackground } from '@/utils/permissionUtils';\r\nimport { PermissionStatusIndicator } from './PermissionStatusIndicator';\r\nimport { PermissionPopover } from '../PermissionPopover';\r\nimport type { ResourceNode, PermissionStatus, PermissionInheritanceInfo } from './types';\r\nimport type { MatrixRoleDto } from '@/services/api/adminApi';\r\nimport type { GroupRoleWithScope } from '@/hooks/useGroupPermissions';\r\nimport { Globe, Building2 } from 'lucide-react';\r\nimport { createAdminApi } from '@/services/api/adminApi';\r\nimport { createGroupsApi } from '@/services/api/groupsApi';\r\n\r\n/** Helper: Get unique tenant badges from source roles */\r\nfunction getTenantBadgesFromRoles(sourceRoles: GroupRoleWithScope[]): Array<{ key: string; isGlobal: boolean; displayName: string | null }> {\r\n const tenantMap = new Map<string, { isGlobal: boolean; displayName: string | null }>();\r\n sourceRoles.forEach(role => {\r\n const key = role.isGlobal ? '__global__' : (role.tenantId || '__unknown__');\r\n if (!tenantMap.has(key)) {\r\n tenantMap.set(key, { isGlobal: role.isGlobal, displayName: role.tenantName });\r\n }\r\n });\r\n return Array.from(tenantMap.entries()).map(([key, data]) => ({\r\n key,\r\n isGlobal: data.isGlobal,\r\n displayName: data.displayName,\r\n }));\r\n}\r\n\r\n/** Helper: Get unique source types from roles */\r\nfunction getSourceTypesFromRoles(\r\n sourceRoles: GroupRoleWithScope[],\r\n isCustomRoleFn: (name: string) => boolean\r\n): Array<{ type: 'Direct' | 'Custom' }> {\r\n const sources: Array<{ type: 'Direct' | 'Custom' }> = [];\r\n sourceRoles.forEach(role => {\r\n const type = isCustomRoleFn(role.name) ? 'Custom' : 'Direct';\r\n if (!sources.find(s => s.type === type)) {\r\n sources.push({ type });\r\n }\r\n });\r\n return sources;\r\n}\r\n\r\nconst ACTION_ICONS: Record<string, React.ReactNode> = {\r\n '*': <Shield className=\"h-3.5 w-3.5\" />,\r\n read: <Eye className=\"h-3.5 w-3.5\" />,\r\n create: <Plus className=\"h-3.5 w-3.5\" />,\r\n update: <Edit className=\"h-3.5 w-3.5\" />,\r\n delete: <Trash2 className=\"h-3.5 w-3.5\" />,\r\n assign: <UserPlus className=\"h-3.5 w-3.5\" />,\r\n execute: <Play className=\"h-3.5 w-3.5\" />,\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\ninterface GroupPermissionMatrixProps {\r\n readonly groupId: string;\r\n readonly compact?: boolean;\r\n readonly tenantId?: string;\r\n readonly tenantSlug?: string;\r\n}\r\n\r\nexport function GroupPermissionMatrix({ groupId, compact = false, tenantId, tenantSlug }: GroupPermissionMatrixProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const {\r\n loading,\r\n error,\r\n group,\r\n groupRoles,\r\n filteredResources,\r\n effectivePermissions,\r\n filters,\r\n applications,\r\n modules,\r\n updateFilters,\r\n getPermissionSources,\r\n reloadData,\r\n isTenantMode,\r\n } = useGroupPermissions({ groupId, tenantId });\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 const [customRoleId, setCustomRoleId] = useState<string | null>(null);\r\n const [customRolePermissions, setCustomRolePermissions] = useState<Set<string>>(new Set());\r\n const [togglingPermission, setTogglingPermission] = useState<string | null>(null);\r\n const [loadingCustomRole, setLoadingCustomRole] = useState(false);\r\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\r\n\r\n // Create tenant-aware API instances\r\n const adminApi = useMemo(() => createAdminApi(tenantSlug), [tenantSlug]);\r\n const groupsApi = useMemo(() => createGroupsApi(tenantSlug), [tenantSlug]);\r\n\r\n React.useEffect(() => {\r\n const loadCustomRole = async () => {\r\n try {\r\n setLoadingCustomRole(true);\r\n const role = await groupsApi.getCustomRole(groupId);\r\n if (role) {\r\n setCustomRoleId(role.id);\r\n setCustomRolePermissions(new Set((role.permissions ?? []).map(p => p.id)));\r\n } else {\r\n setCustomRoleId(null);\r\n setCustomRolePermissions(new Set());\r\n }\r\n } catch (err) {\r\n if (!(err instanceof Error && err.message.includes('404'))) {\r\n console.error('Failed to load custom role:', err);\r\n }\r\n setCustomRoleId(null);\r\n setCustomRolePermissions(new Set());\r\n } finally {\r\n setLoadingCustomRole(false);\r\n }\r\n };\r\n loadCustomRole();\r\n }, [groupId, groupsApi]);\r\n\r\n const handleTogglePermission = async (permissionId: string) => {\r\n // Prevent concurrent toggles (F5 fix)\r\n if (togglingPermission !== null) {\r\n return;\r\n }\r\n\r\n try {\r\n setTogglingPermission(permissionId);\r\n setErrorMessage(null);\r\n let roleId = customRoleId;\r\n let currentPermissions = new Set(customRolePermissions);\r\n\r\n if (!roleId) {\r\n const newRole = await groupsApi.createCustomRole(groupId);\r\n roleId = newRole.id;\r\n setCustomRoleId(roleId);\r\n currentPermissions = new Set();\r\n }\r\n\r\n const newPermissions = new Set(currentPermissions);\r\n if (newPermissions.has(permissionId)) {\r\n newPermissions.delete(permissionId);\r\n } else {\r\n newPermissions.add(permissionId);\r\n }\r\n\r\n const role = await adminApi.roles.getById(roleId);\r\n await adminApi.roles.update(roleId, {\r\n name: role.name,\r\n shortName: role.shortName || undefined,\r\n category: role.category || undefined,\r\n description: role.description || undefined,\r\n permissionIds: Array.from(newPermissions),\r\n });\r\n\r\n setCustomRolePermissions(newPermissions);\r\n await reloadData();\r\n } catch (err) {\r\n console.error('Failed to toggle permission:', err);\r\n // F7 fix: Show user-friendly error message\r\n setErrorMessage(t('groupPermissions.toggleError', 'Erreur lors de la modification de la permission. Veuillez réessayer.'));\r\n // Clear error after 5 seconds\r\n setTimeout(() => setErrorMessage(null), 5000);\r\n } finally {\r\n setTogglingPermission(null);\r\n }\r\n };\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 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 const getAllPermissionsForResource = useCallback((resource: ResourceNode) => {\r\n const allPermissions = [...resource.permissions];\r\n if (resource.childSections) {\r\n resource.childSections.forEach(section => {\r\n allPermissions.push(...section.permissions);\r\n });\r\n }\r\n return allPermissions;\r\n }, []);\r\n\r\n const getPermissionStatusForGroup = useCallback((resource: ResourceNode, isSection: boolean = false): { status: PermissionStatus; grantedCount: number } => {\r\n if (isSection) {\r\n return calculatePermissionStatus(resource, (permId) => effectivePermissions.has(permId));\r\n }\r\n\r\n const allPermissions = getAllPermissionsForResource(resource);\r\n const grantedCount = allPermissions.filter(p => effectivePermissions.has(p.id)).length;\r\n const totalCount = allPermissions.length;\r\n\r\n let status: PermissionStatus;\r\n if (grantedCount === 0) {\r\n status = 'none';\r\n } else if (grantedCount === totalCount) {\r\n status = 'all';\r\n } else {\r\n const hasOnlyRead = allPermissions.every(p =>\r\n !effectivePermissions.has(p.id) || p.action === 'read'\r\n ) && allPermissions.some(p => p.action === 'read' && effectivePermissions.has(p.id));\r\n status = hasOnlyRead ? 'read-only' : 'some';\r\n }\r\n\r\n return { status, grantedCount };\r\n }, [effectivePermissions, getAllPermissionsForResource]);\r\n\r\n type GroupedApp = ReturnType<typeof groupByApplicationWithSections>[0];\r\n\r\n const filterModulesByStatus = (modules: GroupedApp['modules']) => {\r\n return modules.filter((m: GroupedApp['modules'][0]) => {\r\n const { status } = calculateModuleWithSectionsStatus(m.module, m.sections, (permId) => effectivePermissions.has(permId));\r\n return statusFilters.has(status);\r\n });\r\n };\r\n\r\n const applyStatusFilters = (grouped: ReturnType<typeof groupByApplicationWithSections>) => {\r\n if (statusFilters.size === 0) return grouped;\r\n return grouped.map(appGroup => ({\r\n ...appGroup,\r\n modules: filterModulesByStatus(appGroup.modules)\r\n })).filter(g => g.modules.length > 0);\r\n };\r\n\r\n const groupedResources = useMemo(() => {\r\n let grouped = groupByApplicationWithSections(filteredResources);\r\n return applyStatusFilters(grouped);\r\n }, [filteredResources, statusFilters, effectivePermissions]);\r\n\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 addUniqueSourceRole = (sourceRoles: GroupRoleWithScope[], role: GroupRoleWithScope) => {\r\n if (!sourceRoles.find(r => r.id === role.id && r.tenantId === role.tenantId)) {\r\n sourceRoles.push(role);\r\n }\r\n };\r\n\r\n const getSourceRolesForResource = (resource: ResourceNode): GroupRoleWithScope[] => {\r\n const sourceRoles: GroupRoleWithScope[] = [];\r\n resource.permissions.forEach(perm => {\r\n if (effectivePermissions.has(perm.id)) {\r\n getPermissionSources(perm.id).forEach(role => {\r\n addUniqueSourceRole(sourceRoles, role);\r\n });\r\n }\r\n });\r\n return sourceRoles;\r\n };\r\n\r\n const isCustomRole = (roleName: string): boolean => {\r\n return roleName.startsWith('group_') && roleName.endsWith('_custom');\r\n };\r\n\r\n const getDisplayName = (role: GroupRoleWithScope): string => {\r\n return isCustomRole(role.name) ? t('groupPermissions.customBadge', 'Custom') : (role.shortName || role.name);\r\n };\r\n\r\n const groupAsRole: MatrixRoleDto | null = useMemo(() => {\r\n if (!group) return null;\r\n return {\r\n id: customRoleId || `group_${groupId}_custom`,\r\n name: group.name,\r\n shortName: group.name,\r\n category: 'Custom' as const,\r\n description: null,\r\n isSystem: false,\r\n permissions: [],\r\n permissionIds: [],\r\n };\r\n }, [group, customRoleId, groupId]);\r\n\r\n const getGroupPermissionInheritance = useCallback((_roleId: string, permissionId: string): PermissionInheritanceInfo => {\r\n const isGranted = effectivePermissions.has(permissionId);\r\n const isFromCustomRole = customRolePermissions.has(permissionId);\r\n const sourceRoles = isGranted ? getPermissionSources(permissionId) : [];\r\n const inheritedRole = sourceRoles.find(r => !isCustomRole(r.name));\r\n\r\n return {\r\n isDirect: isFromCustomRole,\r\n isInherited: isGranted && !isFromCustomRole && sourceRoles.length > 0,\r\n inheritedFromPath: inheritedRole ? inheritedRole.name : undefined,\r\n inheritedFromId: inheritedRole?.id,\r\n };\r\n }, [effectivePermissions, customRolePermissions, getPermissionSources]);\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <Loader2 className=\"h-8 w-8 animate-spin text-[var(--color-accent-500)]\" />\r\n <span className=\"ml-3 text-[var(--text-secondary)]\">{t('groupPermissions.loading', 'Chargement des permissions...')}</span>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--error-bg)] p-4 border border-[var(--error-border)]\">\r\n <div className=\"flex items-center\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <p className=\"ml-2 text-sm text-[var(--error-text)]\">{error}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!group) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n <Shield className=\"h-12 w-12 mx-auto mb-4 text-[var(--text-muted)]\" />\r\n <p>{t('groupPermissions.noGroup', 'Groupe non trouvé')}</p>\r\n </div>\r\n );\r\n }\r\n\r\n const getPaddingClass = (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 getResourceIcon = (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 getResourceLabelClass = (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 renderResourceRows = (resources: ResourceNode[], baseIndex: number) => {\r\n return resources.map((resource, idx) =>\r\n renderResourceRow(resource, baseIndex + idx, 'resource', false, false)\r\n );\r\n };\r\n\r\n const renderSectionRow = (\r\n sectionWithResources: ReturnType<typeof groupByApplicationWithSections>[0]['modules'][0]['sections'][0],\r\n moduleIndex: number,\r\n sectionIndex: number\r\n ) => {\r\n const { section, resources } = sectionWithResources;\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 {renderResourceRow(section, moduleIndex + sectionIndex + 1, 'section', hasResources, isSectionCollapsed)}\r\n {hasResources && !isSectionCollapsed && renderResourceRows(resources, moduleIndex + sectionIndex + 2)}\r\n </React.Fragment>\r\n );\r\n };\r\n\r\n const renderSectionRows = (\r\n sections: ReturnType<typeof groupByApplicationWithSections>[0]['modules'][0]['sections'],\r\n moduleIndex: number,\r\n hasSections: boolean,\r\n isModuleCollapsed: boolean\r\n ) => {\r\n if (!hasSections || isModuleCollapsed) return null;\r\n return sections.map((sectionWithResources, sectionIndex) =>\r\n renderSectionRow(sectionWithResources, moduleIndex, sectionIndex)\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 isSection = level === 'section';\r\n const { status, grantedCount } = getPermissionStatusForGroup(resource, isSection);\r\n const totalCount = isSection ? resource.permissions.length : getAllPermissionsForResource(resource).length;\r\n const cellBg = getPermissionCellBackground(status);\r\n const sourceRoles = getSourceRolesForResource(resource);\r\n const isPopoverOpen = openPopover === resource.id;\r\n const paddingLeft = getPaddingClass(level);\r\n\r\n return (\r\n <tr\r\n key={resource.id}\r\n className={`hover:bg-[var(--bg-hover)] ${rowIndex % 2 === 0 ? 'item-light' : 'item-medium'}`}\r\n >\r\n <td\r\n className={`sticky left-0 z-10 ${rowIndex % 2 === 0 ? 'item-light' : 'item-medium'} 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 {hasChildren && (\r\n <button\r\n onClick={() => level === 'module' ? toggleModule(resource.id) : toggleSection(resource.id)}\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 {getResourceIcon(level)}\r\n <span className={`text-sm ${getResourceLabelClass(level)}`}>\r\n {resource.label}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n ({totalCount})\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 type=\"button\"\r\n onClick={() => handleCellClick(resource.id)}\r\n className={`w-full h-full min-h-[36px] flex items-center justify-center rounded transition-colors hover:opacity-80 ${\r\n isPopoverOpen ? 'ring-2 ring-[var(--color-accent-500)]' : ''\r\n }`}\r\n title={`${resource.label}: ${grantedCount}/${totalCount}`}\r\n >\r\n <PermissionStatusIndicator\r\n status={status}\r\n grantedCount={grantedCount}\r\n totalCount={totalCount}\r\n />\r\n </button>\r\n {isPopoverOpen && group && groupAsRole && (\r\n <PermissionPopover\r\n mode=\"editable\"\r\n role={groupAsRole}\r\n resource={resource}\r\n onClose={() => setOpenPopover(null)}\r\n onTogglePermission={handleTogglePermission}\r\n getPermissionInheritance={getGroupPermissionInheritance}\r\n />\r\n )}\r\n </td>\r\n\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ width: '140px', minWidth: '140px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1\">\r\n {sourceRoles.length > 0 ? (\r\n sourceRoles.map(role => {\r\n const isCustom = isCustomRole(role.name);\r\n const displayName = getDisplayName(role);\r\n const scopeIcon = role.isGlobal ? (\r\n <Globe className=\"h-2.5 w-2.5 text-[var(--info-text)]\" />\r\n ) : (\r\n <Building2 className=\"h-2.5 w-2.5 text-[var(--warning-text)]\" />\r\n );\r\n const scopeTitle = role.isGlobal\r\n ? t('groupPermissions.globalScope', 'Global')\r\n : role.tenantName || t('groupPermissions.tenantScope', 'Tenant');\r\n return (\r\n <button\r\n key={`${role.id}-${role.tenantId || 'global'}`}\r\n onClick={() => !isCustom && navigate(`/administration/permissions/roles/${role.id}`)}\r\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full transition-all ${\r\n isCustom\r\n ? 'bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)] border border-[var(--color-accent-300)] dark:border-[var(--color-accent-700)] cursor-default'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)] border border-[var(--border-color)] cursor-pointer hover:ring-1 hover:ring-[var(--color-accent-500)] hover:shadow-sm'\r\n }`}\r\n title={`${isCustom ? t('groupPermissions.customRoleTooltip', 'Rôle personnalisé') : t('groupPermissions.clickToViewRole', 'Cliquer pour voir le rôle')} (${scopeTitle})`}\r\n >\r\n {scopeIcon}\r\n {displayName}\r\n {isCustom && <Star className=\"h-3 w-3\" />}\r\n </button>\r\n );\r\n })\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n </div>\r\n </td>\r\n\r\n {/* Tenant Column */}\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ width: '120px', minWidth: '120px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1\">\r\n {sourceRoles.length > 0 ? (\r\n getTenantBadgesFromRoles(sourceRoles).map(({ key, isGlobal, displayName }) => (\r\n <span\r\n key={key}\r\n className={`inline-flex items-center px-2 py-0.5 text-xs rounded-full ${\r\n isGlobal\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)] border border-[var(--border-color)]'\r\n }`}\r\n >\r\n {isGlobal\r\n ? t('groupPermissions.globalScope', 'Global')\r\n : (displayName || t('groupPermissions.tenantScope', 'Tenant'))}\r\n </span>\r\n ))\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n </div>\r\n </td>\r\n\r\n {/* Source Column */}\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ width: '100px', minWidth: '100px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1\">\r\n {sourceRoles.length > 0 ? (\r\n getSourceTypesFromRoles(sourceRoles, isCustomRole).map((source, idx) => (\r\n <span\r\n key={`source-${source.type}-${idx}`}\r\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full ${\r\n source.type === 'Direct'\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)]'\r\n : 'bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)] border border-[var(--color-accent-300)] dark:border-[var(--color-accent-700)]'\r\n }`}\r\n title={source.type === 'Custom'\r\n ? t('groupPermissions.customPermissions', 'Permissions personnalisées')\r\n : t('groupPermissions.directAssignmentTooltip', 'Rôle assigné directement au groupe')}\r\n >\r\n {source.type === 'Direct' && <UserCheck className=\"h-3 w-3\" />}\r\n {source.type === 'Custom' && <User className=\"h-3 w-3\" />}\r\n {source.type === 'Direct'\r\n ? t('groupPermissions.directAssignment', 'Direct')\r\n : t('groupPermissions.customSource', 'Custom')}\r\n </span>\r\n ))\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n </div>\r\n </td>\r\n\r\n <td\r\n className=\"px-3 py-2\"\r\n style={{ minWidth: '200px' }}\r\n >\r\n <div className=\"flex flex-wrap gap-1.5 items-center relative\">\r\n {resource.permissions\r\n .filter(perm => effectivePermissions.has(perm.id))\r\n .map(perm => {\r\n const isFromCustomRole = customRolePermissions.has(perm.id);\r\n const isToggling = togglingPermission === perm.id;\r\n const actionColor = ACTION_COLORS[perm.action] || 'bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)]';\r\n const icon = ACTION_ICONS[perm.action] || <Eye className=\"h-3.5 w-3.5\" />;\r\n\r\n return (\r\n <button\r\n key={perm.id}\r\n onClick={() => handleTogglePermission(perm.id)}\r\n disabled={isToggling || loadingCustomRole || !isFromCustomRole}\r\n className={`inline-flex items-center gap-1.5 px-2 py-1 rounded-[var(--radius-badge)] border text-xs font-medium transition-all ${actionColor} ${\r\n isFromCustomRole ? 'ring-2 ring-[var(--color-accent-600)] dark:ring-[var(--color-accent-400)] hover:opacity-80 cursor-pointer' : 'opacity-60 cursor-not-allowed'\r\n } disabled:opacity-50`}\r\n title={isFromCustomRole ? t('groupPermissions.clickToRemove', 'Cliquer pour retirer') : t('groupPermissions.grantedByRole', 'Accordé par un rôle')}\r\n >\r\n {isToggling ? (\r\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\r\n ) : (\r\n icon\r\n )}\r\n <span className=\"capitalize\">\r\n {t(`assignments.actions.${perm.action === '*' ? 'all' : perm.action}.label`)}\r\n </span>\r\n {isFromCustomRole && <Star className=\"h-3 w-3\" />}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n };\r\n\r\n return (\r\n <div>\r\n {!compact && (\r\n <>\r\n {/* Flex container: sidebar filters + content aligned at top */}\r\n <div className=\"flex flex-col lg:flex-row lg:items-start lg:gap-6\">\r\n <div className=\"w-full lg:w-72 lg:flex-shrink-0 space-y-4 mb-4 lg:mb-0 lg:sticky lg:top-4\">\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)] mb-3\">\r\n {t('groupPermissions.filters.title', 'Filtres')}\r\n </h4>\r\n\r\n <div className=\"space-y-3\">\r\n <div className=\"space-y-1\">\r\n <label className=\"text-xs text-[var(--text-secondary)]\">\r\n {t('groupPermissions.filters.application', 'Application')}\r\n </label>\r\n <select\r\n value={filters.applicationFilter}\r\n onChange={(e) => updateFilters({ applicationFilter: e.target.value, moduleFilter: 'all' })}\r\n className=\"w-full px-3 py-1.5 text-sm bg-[var(--bg-primary)] 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('groupPermissions.filters.allApplications', 'Toutes les applications')}</option>\r\n {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=\"space-y-1\">\r\n <label className=\"text-xs text-[var(--text-secondary)]\">\r\n {t('groupPermissions.filters.module', 'Module')}\r\n </label>\r\n <select\r\n value={filters.moduleFilter}\r\n onChange={(e) => updateFilters({ moduleFilter: e.target.value })}\r\n className=\"w-full px-3 py-1.5 text-sm bg-[var(--bg-primary)] 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('groupPermissions.filters.allModules', 'Tous les modules')}</option>\r\n {modules\r\n .filter(mod =>\r\n (filters.applicationFilter === 'all' || mod.app === filters.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 <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <span className=\"text-xs font-medium text-[var(--text-secondary)] block mb-2\">\r\n {t('groupPermissions.filterByStatus', 'Filtrer par statut')}\r\n </span>\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n <button\r\n onClick={() => toggleStatusFilter('all')}\r\n className={`inline-flex items-center gap-1 px-2 py-1 text-xs 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 w-3 ${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 px-2 py-1 text-xs 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 w-3 ${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 px-2 py-1 text-xs 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 w-3 ${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 px-2 py-1 text-xs 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 w-3 ${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=\"mt-2 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 <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\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 </div>\r\n\r\n {/* Role badges */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)] mb-3\">\r\n {t('groupPermissions.assignedRoles', 'Rôles assignés')}\r\n </h4>\r\n {groupRoles.length > 0 ? (\r\n <div className=\"flex flex-wrap gap-2\">\r\n {groupRoles.map(role => {\r\n const isCustom = isCustomRole(role.name);\r\n const scopeIcon = role.isGlobal ? (\r\n <Globe className=\"h-3 w-3 text-[var(--info-text)]\" />\r\n ) : (\r\n <Building2 className=\"h-3 w-3 text-[var(--warning-text)]\" />\r\n );\r\n const scopeLabel = role.isGlobal\r\n ? t('groupPermissions.globalScope', 'Global')\r\n : role.tenantName || t('groupPermissions.tenantScope', 'Tenant');\r\n return (\r\n <div key={`${role.id}-${role.tenantId || 'global'}`} className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => !isCustom && navigate(`/administration/permissions/roles/${role.id}`)}\r\n className={`inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)] transition-all ${\r\n isCustom ? 'cursor-default' : 'cursor-pointer hover:ring-2 hover:ring-[var(--color-accent-500)] hover:shadow-md'\r\n }`}\r\n title={isCustom ? t('groupPermissions.customRoleTooltip', 'Rôle personnalisé') : t('groupPermissions.clickToViewRole', 'Cliquer pour voir le rôle')}\r\n >\r\n <Shield className=\"h-3.5 w-3.5\" />\r\n {role.shortName || role.name}\r\n </button>\r\n <span\r\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full ${\r\n role.isGlobal\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]'\r\n : 'bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]'\r\n }`}\r\n title={role.isGlobal\r\n ? t('groupPermissions.globalScopeTooltip', 'Ce rôle s\\'applique à tous les tenants')\r\n : t('groupPermissions.tenantScopeTooltip', 'Ce rôle s\\'applique uniquement à ce tenant: {{tenant}}', { tenant: role.tenantName })}\r\n >\r\n {scopeIcon}\r\n <span className=\"hidden sm:inline\">{scopeLabel}</span>\r\n </span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n ) : (\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--text-muted)]\">\r\n <Info className=\"h-4 w-4\" />\r\n <span>{t('groupPermissions.noRolesInfo', 'Ce groupe n\\'a aucun rôle.')}</span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Info messages */}\r\n {isTenantMode && (\r\n <div className=\"flex items-center gap-2 p-3 rounded-[var(--radius-card)] bg-[var(--accent-bg)] border border-[var(--accent-border)]\">\r\n <Shield className=\"h-4 w-4 text-[var(--accent-text)]\" />\r\n <span className=\"text-sm text-[var(--accent-text)]\">\r\n {t('groupPermissions.tenantModeInfo', 'Affichage des permissions dans le contexte du tenant.')}\r\n </span>\r\n </div>\r\n )}\r\n\r\n {errorMessage && (\r\n <div className=\"flex items-center gap-2 p-3 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <AlertCircle className=\"h-4 w-4 text-[var(--error-text)]\" />\r\n <span className=\"text-sm text-[var(--error-text)]\">{errorMessage}</span>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Permissions table */}\r\n <div className=\"flex-1 min-w-0\">\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('groupPermissions.status', 'Statut')}\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={{ width: '140px', minWidth: '140px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('groupPermissions.sourceRoles', 'Rôles sources')}\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={{ width: '120px', minWidth: '120px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('groupPermissions.tenant', 'Tenant')}\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={{ width: '100px', minWidth: '100px', height: '48px', verticalAlign: 'middle' }}\r\n >\r\n {t('groupPermissions.source', 'Source')}\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={{ minWidth: '200px', 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 <tr className=\"bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\">\r\n <td\r\n className=\"sticky left-0 z-10 px-3 py-3 bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\"\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-5 w-5 text-[var(--color-accent-400)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n )}\r\n <FolderOpen className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n <span className=\"text-sm font-bold text-[var(--color-accent-300)] uppercase tracking-wider\">\r\n {appGroup.application}\r\n </span>\r\n <span className=\"text-xs text-[var(--color-accent-400)] 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 colSpan={5} className=\"px-0 py-3\" />\r\n </tr>\r\n\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 {renderResourceRow(module, moduleIndex, 'module', hasSections, isModuleCollapsed)}\r\n {renderSectionRows(sections, moduleIndex, hasSections, isModuleCollapsed)}\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 </div>\r\n </>\r\n )}\r\n\r\n {compact && (\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 scope=\"col\" className=\"sticky left-0 z-20 item-medium px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '280px', minWidth: '280px', maxWidth: '280px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('assignments.resource')}\r\n </th>\r\n <th scope=\"col\" className=\"px-2 text-center text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '60px', minWidth: '60px', maxWidth: '60px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.status', 'Statut')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '140px', minWidth: '140px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.sourceRoles', 'Rôles sources')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '120px', minWidth: '120px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.tenant', 'Tenant')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ width: '100px', minWidth: '100px', height: '48px', verticalAlign: 'middle' }}>\r\n {t('groupPermissions.source', 'Source')}\r\n </th>\r\n <th scope=\"col\" className=\"px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\" style={{ minWidth: '200px', height: '48px', verticalAlign: 'middle' }}>\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 <React.Fragment key={appGroup.application}>\r\n {appGroup.modules.map((moduleWithSections, moduleIndex) => (\r\n <React.Fragment key={moduleWithSections.module.id}>\r\n {renderResourceRow(moduleWithSections.module, moduleIndex, 'module', false, false)}\r\n </React.Fragment>\r\n ))}\r\n </React.Fragment>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport * as LucideIcons from 'lucide-react';\r\nimport {\r\n Boxes,\r\n Loader2,\r\n ChevronDown,\r\n ChevronRight,\r\n Shield,\r\n Key,\r\n Layers,\r\n RefreshCw,\r\n} from 'lucide-react';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport { groupsApi } from '@/services/api/groupsApi';\r\nimport type { UserApplicationAccessDto } from '@/services/api/adminApi';\r\n\r\ninterface GroupApplicationsTabProps {\r\n readonly groupId: string;\r\n readonly tenantId?: string;\r\n}\r\n\r\nexport function GroupApplicationsTab({ groupId, tenantId }: GroupApplicationsTabProps): ReactElement {\r\n const { t } = useTranslation(['groups', 'admin']);\r\n const [applications, setApplications] = useState<UserApplicationAccessDto[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [expandedApps, setExpandedApps] = useState<Set<string>>(new Set());\r\n\r\n const loadApplicationAccess = useCallback(async () => {\r\n setLoading(true);\r\n try {\r\n const data = await groupsApi.getApplicationAccess(groupId, tenantId);\r\n setApplications(data);\r\n } catch {\r\n setApplications([]);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [groupId, tenantId]);\r\n\r\n useEffect(() => {\r\n void loadApplicationAccess();\r\n }, [loadApplicationAccess]);\r\n\r\n const toggleExpand = (appId: string) => {\r\n setExpandedApps(prev => {\r\n const next = new Set(prev);\r\n if (next.has(appId)) next.delete(appId);\r\n else next.add(appId);\r\n return next;\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 <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 (applications.length === 0) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n <Boxes className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('groups:applications.noAccess')}</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\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('groups:applications.title')}\r\n </h3>\r\n <button\r\n onClick={() => void loadApplicationAccess()}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]\"\r\n title={t('admin:common.refresh', 'Refresh')}\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"space-y-2\">\r\n {applications.map(app => (\r\n <ApplicationCard\r\n key={app.applicationId}\r\n app={app}\r\n isExpanded={expandedApps.has(app.applicationId)}\r\n onToggle={() => toggleExpand(app.applicationId)}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nfunction ApplicationCard({\r\n app,\r\n isExpanded,\r\n onToggle,\r\n}: {\r\n app: UserApplicationAccessDto;\r\n isExpanded: boolean;\r\n onToggle: () => void;\r\n}) {\r\n const { t } = useTranslation(['groups', 'admin']);\r\n const icons = LucideIcons as unknown as Record<string, LucideIcon>;\r\n const AppIcon = app.icon ? icons[app.icon] : null;\r\n\r\n const permissionsByModule = useMemo(() => {\r\n const groups: Record<string, { moduleName: string; permissions: typeof app.permissions }> = {};\r\n for (const perm of app.permissions) {\r\n const key = perm.moduleName || '_global';\r\n if (!groups[key]) {\r\n groups[key] = { moduleName: perm.moduleName || t('groups:applications.globalPermissions'), permissions: [] };\r\n }\r\n groups[key].permissions.push(perm);\r\n }\r\n return Object.values(groups);\r\n }, [app.permissions, t]);\r\n\r\n return (\r\n <div className=\"border border-[var(--border-color)] rounded-[var(--radius-card)] bg-[var(--bg-card)] overflow-hidden\">\r\n <button\r\n onClick={onToggle}\r\n className=\"w-full flex items-center gap-3 p-4 text-left hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {isExpanded ? (\r\n <ChevronDown className=\"w-4 h-4 text-[var(--text-muted)] flex-shrink-0\" />\r\n ) : (\r\n <ChevronRight className=\"w-4 h-4 text-[var(--text-muted)] flex-shrink-0\" />\r\n )}\r\n\r\n <div className=\"w-9 h-9 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10 flex items-center justify-center flex-shrink-0\">\r\n {AppIcon ? (\r\n <AppIcon className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n ) : (\r\n <Layers className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n )}\r\n </div>\r\n\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"font-medium text-[var(--text-primary)] truncate\">{app.applicationLabel}</p>\r\n <p className=\"text-xs text-[var(--text-muted)] truncate\">{app.applicationCode}</p>\r\n </div>\r\n\r\n {app.hasFullAccess ? (\r\n <span className=\"px-2.5 py-1 text-xs font-medium rounded-full bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)] flex-shrink-0\">\r\n {t('groups:applications.fullAccess')}\r\n </span>\r\n ) : (\r\n <span className=\"px-2.5 py-1 text-xs font-medium rounded-full bg-[var(--color-accent-500)]/10 text-[var(--color-accent-600)] border border-[var(--color-accent-500)]/20 flex-shrink-0\">\r\n {t('groups:applications.permissionCount', { count: app.permissions.length })}\r\n </span>\r\n )}\r\n\r\n <span className=\"text-xs text-[var(--text-muted)] flex items-center gap-1 flex-shrink-0\">\r\n <Shield className=\"w-3.5 h-3.5\" />\r\n {app.roles.length}\r\n </span>\r\n </button>\r\n\r\n {isExpanded && (\r\n <div className=\"border-t border-[var(--border-color)] p-4 space-y-4 bg-[var(--bg-secondary)]\">\r\n <div>\r\n <h5 className=\"text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider mb-2\">\r\n {t('groups:applications.rolesGrantingAccess')}\r\n </h5>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {app.roles.map(role => (\r\n <span\r\n key={role.roleId}\r\n className=\"inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full bg-[var(--bg-card)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n >\r\n <Shield className=\"w-3 h-3 text-[var(--color-accent-500)]\" />\r\n {role.roleName}\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {!app.hasFullAccess && app.permissions.length > 0 && (\r\n <div>\r\n <h5 className=\"text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider mb-2\">\r\n {t('groups:applications.permissionsDetail')}\r\n </h5>\r\n <div className=\"space-y-3\">\r\n {permissionsByModule.map(group => (\r\n <div key={group.moduleName}>\r\n <p className=\"text-xs font-medium text-[var(--text-secondary)] mb-1\">{group.moduleName}</p>\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {group.permissions.map(perm => (\r\n <span\r\n key={perm.path}\r\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded bg-[var(--bg-card)] border border-[var(--border-color)] text-[var(--text-secondary)]\"\r\n >\r\n <Key className=\"w-2.5 h-2.5 text-[var(--text-tertiary)]\" />\r\n {perm.action || extractActionFromPath(perm.path)}\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {app.hasFullAccess && (\r\n <p className=\"text-xs text-[var(--success-text)] italic\">\r\n {t('groups:applications.fullAccessDescription')}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction extractActionFromPath(path: string): string {\r\n const parts = path.split('.');\r\n return parts.at(-1)!;\r\n}\r\n","import type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Building2, User, ArrowRightLeft, Globe } from 'lucide-react';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\n\r\ninterface ScopeBannerProps {\r\n /** Additional CSS classes */\r\n readonly className?: string;\r\n /** Show switch scope button */\r\n readonly showSwitch?: boolean;\r\n /** Callback when switch is clicked (opens tenant selector) */\r\n readonly onSwitchClick?: () => void;\r\n}\r\n\r\n/**\r\n * Banner component displaying current tenant context.\r\n * Shows the current workspace name to help users understand\r\n * what scope their actions will affect.\r\n */\r\nexport function ScopeBanner({ className = '', showSwitch = true, onSwitchClick }: ScopeBannerProps): ReactElement | null {\r\n const { t } = useTranslation('admin');\r\n const { currentTenant, hasMultipleTenants, isGlobalView } = useTenant();\r\n\r\n // Show banner in global view or when user has multiple tenants with a current tenant\r\n if (!isGlobalView && (!hasMultipleTenants || !currentTenant)) {\r\n return null;\r\n }\r\n\r\n // Global view mode\r\n if (isGlobalView) {\r\n return (\r\n <div\r\n className={`flex items-center justify-between gap-4 px-4 py-2.5 border bg-emerald-500/5 border-emerald-500/20 ${className}`}\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n {/* Global Icon */}\r\n <div\r\n className=\"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-emerald-500/10\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <Globe className=\"w-4 h-4 text-emerald-600\" />\r\n </div>\r\n\r\n {/* Scope Info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"font-medium text-emerald-700\">\r\n {t('scope.banner.globalMode', 'Vue globale')}\r\n </span>\r\n <p className=\"text-xs text-emerald-600/70 mt-0.5\">\r\n {t('scope.banner.globalModeDesc', 'Vous voyez les données de tous les tenants')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Switch Button */}\r\n {showSwitch && onSwitchClick && (\r\n <button\r\n onClick={onSwitchClick}\r\n className=\"flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-emerald-700 hover:text-emerald-800 hover:bg-emerald-500/10 transition-colors\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <ArrowRightLeft className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('scope.banner.selectTenant', 'Sélectionner un tenant')}</span>\r\n </button>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n // Tenant view mode\r\n const isB2B = currentTenant?.type === 'Business';\r\n\r\n return (\r\n <div\r\n className={`flex items-center justify-between gap-4 px-4 py-2.5 border bg-[var(--color-accent-500)]/5 border-[var(--color-accent-500)]/20 ${className}`}\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n {/* Scope Icon */}\r\n <div\r\n className={`flex-shrink-0 w-8 h-8 flex items-center justify-center ${\r\n isB2B ? 'bg-blue-500/10' : 'bg-violet-500/10'\r\n }`}\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n {isB2B ? (\r\n <Building2 className=\"w-4 h-4 text-blue-500\" />\r\n ) : (\r\n <User className=\"w-4 h-4 text-violet-500\" />\r\n )}\r\n </div>\r\n\r\n {/* Scope Info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"font-medium text-[var(--text-primary)]\">\r\n {t('scope.banner.tenantMode', 'Espace de travail: {{tenantName}}', { tenantName: currentTenant?.name })}\r\n </span>\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">\r\n {t('scope.banner.tenantModeDesc', 'Les modifications s\\'appliquent uniquement à ce tenant')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Switch Button */}\r\n {showSwitch && onSwitchClick && (\r\n <button\r\n onClick={onSwitchClick}\r\n className=\"flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors\"\r\n style={{ borderRadius: 'var(--radius-button)' }}\r\n >\r\n <ArrowRightLeft className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('scope.banner.switchScope', 'Changer de scope')}</span>\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useRef, useMemo } 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 {\r\n ArrowLeft,\r\n Users,\r\n Shield,\r\n Building2,\r\n Key,\r\n Loader2,\r\n Save,\r\n Trash2,\r\n Edit3,\r\n Mail,\r\n AlertTriangle,\r\n AlertCircle,\r\n CheckCircle,\r\n Cloud,\r\n X,\r\n AppWindow,\r\n GitBranch,\r\n CornerDownRight,\r\n Unlink,\r\n Plus,\r\n Search,\r\n} from 'lucide-react';\r\nimport {\r\n groupsApi,\r\n type GroupDetailDto,\r\n type GroupListDto,\r\n type InheritedMemberDto,\r\n} from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\nimport { GroupRoleAssignment } from '@/components/platform/administration/GroupRoleAssignment';\r\nimport { GroupTenantsTab } from '@/components/platform/administration/GroupTenantsTab';\r\nimport { GroupMembersTab } from '@/components/platform/administration/GroupMembersTab';\r\nimport { GroupPermissionMatrix } from '@/components/platform/administration/permissions/GroupPermissionMatrix';\r\nimport { GroupApplicationsTab } from '@/components/platform/administration/GroupApplicationsTab';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useAdminTenants } from '@/hooks/useAdminTenants';\r\nimport { ScopeBanner } from '@/components/ui/ScopeBanner';\r\nimport { useTabNavigation } from '@/hooks/useTabNavigation';\r\n\r\ntype TabId = 'info' | 'hierarchy' | 'members' | 'roles' | 'tenants' | 'applications' | 'permissions';\r\n\r\nconst VALID_TABS: TabId[] = ['info', 'hierarchy', 'members', 'roles', 'tenants', 'applications', 'permissions'];\r\n\r\nconst isValidGuid = (value: string | undefined): boolean => {\r\n if (!value) return false;\r\n const guidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\r\n return guidRegex.test(value);\r\n};\r\n\r\nconst useGroupDetailState = () => {\r\n const [group, setGroup] = useState<GroupDetailDto | null>(null);\r\n const [roles, setRoles] = useState<RoleListDto[] | null>(null);\r\n const [rolesLoading, setRolesLoading] = useState(false);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [formData, setFormData] = useState({ name: '', description: '' });\r\n\r\n return {\r\n group, setGroup, roles, setRoles, rolesLoading, setRolesLoading,\r\n loading, setLoading, saving, setSaving, error, setError, success, setSuccess,\r\n isEditing, setIsEditing, formData, setFormData,\r\n };\r\n};\r\n\r\nfunction HierarchyTab({\r\n groupId,\r\n group,\r\n onRefresh,\r\n onSuccess,\r\n onError,\r\n}: {\r\n groupId: string;\r\n group: GroupDetailDto;\r\n onRefresh: () => Promise<void>;\r\n onSuccess: (msg: string) => void;\r\n onError: (msg: string) => void;\r\n}) {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const [allGroups, setAllGroups] = useState<GroupListDto[]>([]);\r\n const [loadingGroups, setLoadingGroups] = useState(false);\r\n const [showParentSelector, setShowParentSelector] = useState(false);\r\n const [showChildSelector, setShowChildSelector] = useState(false);\r\n const [showCreateChild, setShowCreateChild] = useState(false);\r\n const [parentSearch, setParentSearch] = useState('');\r\n const [childSearch, setChildSearch] = useState('');\r\n const [saving, setSaving] = useState(false);\r\n const [newChildName, setNewChildName] = useState('');\r\n const [newChildDescription, setNewChildDescription] = useState('');\r\n const [newChildIsSecurityGroup, setNewChildIsSecurityGroup] = useState(false);\r\n const [inheritedMembers, setInheritedMembers] = useState<InheritedMemberDto[]>([]);\r\n const [loadingInheritedMembers, setLoadingInheritedMembers] = useState(false);\r\n\r\n const loadAllGroups = useCallback(async () => {\r\n try {\r\n setLoadingGroups(true);\r\n const groups = await groupsApi.getAll();\r\n setAllGroups(groups);\r\n } catch {\r\n // silently fail — selector just won't have options\r\n } finally {\r\n setLoadingGroups(false);\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (showParentSelector || showChildSelector) {\r\n loadAllGroups();\r\n }\r\n }, [showParentSelector, showChildSelector, loadAllGroups]);\r\n\r\n useEffect(() => {\r\n if (!group.parentGroupId) return;\r\n const loadInheritedMembers = async () => {\r\n try {\r\n setLoadingInheritedMembers(true);\r\n const members = await groupsApi.getInheritedMembers(groupId);\r\n setInheritedMembers(members);\r\n } catch {\r\n // silently fail\r\n } finally {\r\n setLoadingInheritedMembers(false);\r\n }\r\n };\r\n loadInheritedMembers();\r\n }, [groupId, group.parentGroupId]);\r\n\r\n const membersByAncestor = useMemo(() => {\r\n const grouped = new Map<string, { groupId: string; groupName: string; level: number; members: InheritedMemberDto[] }>();\r\n for (const m of inheritedMembers) {\r\n const key = m.inheritedFromGroupId;\r\n if (!grouped.has(key)) {\r\n grouped.set(key, { groupId: m.inheritedFromGroupId, groupName: m.inheritedFromGroupName, level: m.level, members: [] });\r\n }\r\n grouped.get(key)!.members.push(m);\r\n }\r\n return Array.from(grouped.values()).sort((a, b) => a.level - b.level);\r\n }, [inheritedMembers]);\r\n\r\n // Exclude current group + its descendants from parent candidates\r\n const getDescendantIds = (id: string, groups: GroupListDto[]): Set<string> => {\r\n const ids = new Set<string>();\r\n const queue = [id];\r\n while (queue.length > 0) {\r\n const current = queue.shift()!;\r\n ids.add(current);\r\n groups.filter(g => g.parentGroupId === current).forEach(g => queue.push(g.id));\r\n }\r\n return ids;\r\n };\r\n\r\n const excludedForParent = getDescendantIds(groupId, allGroups);\r\n const parentCandidates = allGroups\r\n .filter(g => !excludedForParent.has(g.id) && g.isActive)\r\n .filter(g => !parentSearch || g.name.toLowerCase().includes(parentSearch.toLowerCase()));\r\n\r\n // Child candidates: groups that are NOT already children, NOT the current group, NOT an ancestor\r\n const existingChildIds = new Set(group.childGroups?.map(c => c.id) || []);\r\n const childCandidates = allGroups\r\n .filter(g => g.id !== groupId && !existingChildIds.has(g.id) && g.isActive)\r\n .filter(g => g.parentGroupId !== groupId) // not already a child\r\n .filter(g => !childSearch || g.name.toLowerCase().includes(childSearch.toLowerCase()));\r\n\r\n const handleSetParent = async (parentId: string) => {\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(groupId, { parentGroupId: parentId });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.parentSet'));\r\n setShowParentSelector(false);\r\n setParentSearch('');\r\n } catch {\r\n onError(t('groups:hierarchy.errors.setParentFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleClearParent = async () => {\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(groupId, { parentGroupId: null });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.parentCleared'));\r\n } catch {\r\n onError(t('groups:hierarchy.errors.clearParentFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleAddChild = async (childId: string) => {\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(childId, { parentGroupId: groupId });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.childAdded'));\r\n setShowChildSelector(false);\r\n setChildSearch('');\r\n } catch {\r\n onError(t('groups:hierarchy.errors.addChildFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleRemoveChild = async (childId: string, childName: string) => {\r\n if (!confirm(t('groups:hierarchy.confirmRemoveChild', { name: childName }))) return;\r\n try {\r\n setSaving(true);\r\n await groupsApi.setParentGroup(childId, { parentGroupId: null });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.childRemoved'));\r\n } catch {\r\n onError(t('groups:hierarchy.errors.removeChildFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleCreateChild = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!newChildName.trim()) return;\r\n try {\r\n setSaving(true);\r\n await groupsApi.create({\r\n name: newChildName.trim(),\r\n description: newChildDescription.trim() || undefined,\r\n isSecurityGroup: newChildIsSecurityGroup,\r\n parentGroupId: groupId,\r\n });\r\n await onRefresh();\r\n onSuccess(t('groups:hierarchy.childCreated'));\r\n setShowCreateChild(false);\r\n setNewChildName('');\r\n setNewChildDescription('');\r\n setNewChildIsSecurityGroup(false);\r\n } catch {\r\n onError(t('groups:hierarchy.errors.createChildFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:hierarchy.info')}\r\n </p>\r\n </div>\r\n\r\n {/* Parent Group Section */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <CornerDownRight className=\"w-5 h-5\" />\r\n {t('groups:hierarchy.parentGroup')}\r\n </h3>\r\n {!group.parentGroupId && !showParentSelector && (\r\n <button\r\n onClick={() => setShowParentSelector(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.setParent')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {group.parentGroupId ? (\r\n <div className=\"flex items-center justify-between p-4 rounded-lg bg-[var(--bg-secondary)]\">\r\n <Link\r\n to={`/administration/users/groups/${group.parentGroupId}`}\r\n className=\"flex items-center gap-3 text-sm font-medium text-[var(--color-accent-500)] hover:underline\"\r\n >\r\n <div className=\"p-2 rounded-lg bg-[var(--accent-bg)]\">\r\n <GitBranch className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n </div>\r\n {group.parentGroupName || group.parentGroupId}\r\n </Link>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => { setShowParentSelector(true); }}\r\n className=\"flex items-center gap-1 px-2 py-1 text-xs rounded-[var(--radius-button)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Edit3 className=\"w-3 h-3\" />\r\n {t('common:edit', 'Modifier')}\r\n </button>\r\n <button\r\n onClick={handleClearParent}\r\n disabled={saving}\r\n className=\"flex items-center gap-1 px-2 py-1 text-xs rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Unlink className=\"w-3 h-3\" />\r\n {t('groups:hierarchy.clearParent')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : !showParentSelector ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('groups:hierarchy.noParent')}\r\n </p>\r\n ) : null}\r\n\r\n {/* Parent Selector */}\r\n {showParentSelector && (\r\n <div className=\"mt-4 p-4 rounded-lg border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <div className=\"relative flex-1\">\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={parentSearch}\r\n onChange={(e) => setParentSearch(e.target.value)}\r\n placeholder={t('groups:hierarchy.searchGroups')}\r\n className=\"w-full pl-9 pr-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n autoFocus\r\n />\r\n </div>\r\n <button\r\n onClick={() => { setShowParentSelector(false); setParentSearch(''); }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <div className=\"max-h-48 overflow-y-auto space-y-1\">\r\n {loadingGroups && (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-tertiary)]\" />\r\n </div>\r\n )}\r\n {!loadingGroups && parentCandidates.length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('groups:hierarchy.noGroupsAvailable')}\r\n </p>\r\n )}\r\n {!loadingGroups && parentCandidates.length > 0 && (\r\n parentCandidates.map((g) => (\r\n <button\r\n key={g.id}\r\n onClick={() => handleSetParent(g.id)}\r\n disabled={saving}\r\n className=\"w-full flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <GitBranch className=\"w-4 h-4 text-[var(--text-tertiary)] flex-shrink-0\" />\r\n <div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{g.name}</span>\r\n {g.parentGroupName && (\r\n <span className=\"ml-2 text-xs text-[var(--text-tertiary)]\">\r\n ({t('groups:hierarchy.childOf')} {g.parentGroupName})\r\n </span>\r\n )}\r\n </div>\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Inherited Members Section */}\r\n {group.parentGroupId && (\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2 mb-4\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:hierarchy.inheritedMembers')}\r\n {!loadingInheritedMembers && (\r\n <span className=\"ml-1 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {inheritedMembers.length}\r\n </span>\r\n )}\r\n </h3>\r\n\r\n <div className=\"p-4 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] mb-4\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:hierarchy.inheritedMembersInfo')}\r\n </p>\r\n </div>\r\n\r\n {loadingInheritedMembers && (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-tertiary)]\" />\r\n </div>\r\n )}\r\n\r\n {!loadingInheritedMembers && inheritedMembers.length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('groups:hierarchy.noInheritedMembers')}\r\n </p>\r\n )}\r\n\r\n {!loadingInheritedMembers && membersByAncestor.length > 0 && (\r\n <div className=\"space-y-4\">\r\n {membersByAncestor.map((ancestorGroup) => (\r\n <div\r\n key={ancestorGroup.groupId}\r\n className=\"p-4 rounded-lg border border-dashed border-[var(--border-color)]\"\r\n >\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <Link\r\n to={`/administration/users/groups/${ancestorGroup.groupId}`}\r\n className=\"text-sm font-medium text-[var(--color-accent-500)] hover:underline flex items-center gap-1.5\"\r\n >\r\n <GitBranch className=\"w-4 h-4\" />\r\n {ancestorGroup.groupName}\r\n </Link>\r\n <span className=\"px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {t('groups:hierarchy.level', { level: ancestorGroup.level })}\r\n </span>\r\n </div>\r\n <div className=\"space-y-1\">\r\n {ancestorGroup.members.map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"p-1.5 rounded-full bg-[var(--bg-secondary)]\">\r\n <Users className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{member.fullName}</span>\r\n <span className=\"ml-2 text-xs text-[var(--text-tertiary)]\">{member.email}</span>\r\n </div>\r\n </Link>\r\n ))}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Child Groups Section */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <GitBranch className=\"w-5 h-5\" />\r\n {t('groups:hierarchy.childGroups')}\r\n <span className=\"ml-1 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {group.childGroups?.length || 0}\r\n </span>\r\n </h3>\r\n {!showChildSelector && !showCreateChild && (\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => setShowCreateChild(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.createChild')}\r\n </button>\r\n <button\r\n onClick={() => setShowChildSelector(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <GitBranch className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.addExisting')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Child Selector */}\r\n {showChildSelector && (\r\n <div className=\"mb-4 p-4 rounded-lg border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <div className=\"relative flex-1\">\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={childSearch}\r\n onChange={(e) => setChildSearch(e.target.value)}\r\n placeholder={t('groups:hierarchy.searchGroups')}\r\n className=\"w-full pl-9 pr-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n autoFocus\r\n />\r\n </div>\r\n <button\r\n onClick={() => { setShowChildSelector(false); setChildSearch(''); }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <div className=\"max-h-48 overflow-y-auto space-y-1\">\r\n {loadingGroups && (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-tertiary)]\" />\r\n </div>\r\n )}\r\n {!loadingGroups && childCandidates.length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('groups:hierarchy.noGroupsAvailable')}\r\n </p>\r\n )}\r\n {!loadingGroups && childCandidates.length > 0 && (\r\n childCandidates.map((g) => (\r\n <button\r\n key={g.id}\r\n onClick={() => handleAddChild(g.id)}\r\n disabled={saving}\r\n className=\"w-full flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <Plus className=\"w-4 h-4 text-[var(--color-accent-500)] flex-shrink-0\" />\r\n <div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{g.name}</span>\r\n {g.parentGroupName && (\r\n <span className=\"ml-2 text-xs text-[var(--text-tertiary)]\">\r\n ({t('groups:hierarchy.childOf')} {g.parentGroupName})\r\n </span>\r\n )}\r\n </div>\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Create Child Form */}\r\n {showCreateChild && (\r\n <form onSubmit={handleCreateChild} className=\"mb-4 p-4 rounded-lg border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-between mb-3\">\r\n <h4 className=\"text-sm font-semibold text-[var(--text-primary)]\">\r\n {t('groups:hierarchy.createChild')}\r\n </h4>\r\n <button\r\n type=\"button\"\r\n onClick={() => { setShowCreateChild(false); setNewChildName(''); setNewChildDescription(''); setNewChildIsSecurityGroup(false); }}\r\n className=\"p-1 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n <div className=\"space-y-3\">\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('admin:groups.groupName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newChildName}\r\n onChange={(e) => setNewChildName(e.target.value)}\r\n placeholder={t('admin:groups.groupNamePlaceholder')}\r\n className=\"w-full px-3 py-2 text-sm 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 required\r\n autoFocus\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('groups:detail.info.description')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newChildDescription}\r\n onChange={(e) => setNewChildDescription(e.target.value)}\r\n placeholder={t('admin:groups.descriptionPlaceholder')}\r\n className=\"w-full px-3 py-2 text-sm 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 <label className=\"flex items-center gap-2 cursor-pointer\">\r\n <input\r\n type=\"checkbox\"\r\n checked={newChildIsSecurityGroup}\r\n onChange={(e) => setNewChildIsSecurityGroup(e.target.checked)}\r\n className=\"rounded border-[var(--border-color)]\"\r\n />\r\n <span className=\"text-sm text-[var(--text-primary)]\">\r\n {t('admin:groups.isSecurityGroup')}\r\n </span>\r\n </label>\r\n <div className=\"flex items-center gap-2 pt-1\">\r\n <button\r\n type=\"button\"\r\n onClick={() => { setShowCreateChild(false); setNewChildName(''); setNewChildDescription(''); setNewChildIsSecurityGroup(false); }}\r\n className=\"px-3 py-1.5 text-sm rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common:cancel', 'Annuler')}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n disabled={!newChildName.trim() || saving}\r\n className=\"inline-flex items-center gap-1 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 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Plus className=\"w-4 h-4\" />}\r\n {t('common:create', 'Créer')}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n )}\r\n\r\n {/* Existing Children List */}\r\n {(group.childGroups?.length ?? 0) > 0 ? (\r\n <div className=\"space-y-2\">\r\n {group.childGroups.map((child) => (\r\n <div\r\n key={child.id}\r\n className=\"flex items-center justify-between p-3 rounded-lg bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Link\r\n to={`/administration/users/groups/${child.id}`}\r\n className=\"flex items-center gap-3\"\r\n >\r\n <div className=\"p-1.5 rounded-lg bg-[var(--accent-bg)]\">\r\n <GitBranch className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{child.name}</span>\r\n {!child.isActive && (\r\n <span className=\"px-1.5 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)]\">\r\n {t('common.inactive', 'Inactive')}\r\n </span>\r\n )}\r\n </Link>\r\n <button\r\n onClick={() => handleRemoveChild(child.id, child.name)}\r\n disabled={saving}\r\n className=\"flex items-center gap-1 px-2 py-1 text-xs rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Unlink className=\"w-3 h-3\" />\r\n {t('groups:hierarchy.removeChild')}\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n ) : !showChildSelector && !showCreateChild ? (\r\n <div className=\"text-center py-8\">\r\n <GitBranch className=\"w-8 h-8 mx-auto mb-2 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('groups:hierarchy.noChildren')}\r\n </p>\r\n <div className=\"mt-3 flex items-center justify-center gap-2\">\r\n <button\r\n onClick={() => setShowCreateChild(true)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.createChild')}\r\n </button>\r\n <button\r\n onClick={() => setShowChildSelector(true)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <GitBranch className=\"w-4 h-4\" />\r\n {t('groups:hierarchy.addExisting')}\r\n </button>\r\n </div>\r\n </div>\r\n ) : null}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport function GroupDetailPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'groups']);\r\n const { id: groupId } = useParams<{ id: string }>();\r\n const navigate = useNavigate();\r\n\r\n const { currentTenant, hasMultipleTenants } = useTenant();\r\n const { tenants: adminTenantsList } = useAdminTenants();\r\n const { activeTab, setActiveTab } = useTabNavigation<TabId>('info', VALID_TABS);\r\n const visitedTabsRef = useRef<Set<TabId>>(new Set(['info']));\r\n const { group, setGroup, roles, setRoles, rolesLoading, setRolesLoading, loading, setLoading, saving, setSaving, error, setError, success, setSuccess, isEditing, setIsEditing, formData, setFormData } = useGroupDetailState();\r\n\r\n const loadGroup = useCallback(async (silent = false) => {\r\n if (!groupId || !isValidGuid(groupId)) return;\r\n try {\r\n if (!silent) setLoading(true);\r\n const data = await groupsApi.getById(groupId);\r\n setGroup(data);\r\n setFormData({\r\n name: data.name,\r\n description: data.description || ''\r\n });\r\n } catch (err) {\r\n console.error('Failed to load group:', err);\r\n setError(t('groups:detail.errors.loadFailed', 'Erreur lors du chargement du groupe'));\r\n } finally {\r\n if (!silent) setLoading(false);\r\n }\r\n }, [groupId, t]);\r\n\r\n const loadRoles = useCallback(async () => {\r\n try {\r\n setRolesLoading(true);\r\n const result = await adminApi.roles.getAssignable();\r\n setRoles(Array.isArray(result) ? result : []);\r\n } catch (err) {\r\n console.error('Failed to load roles:', err);\r\n setRoles([]);\r\n } finally {\r\n setRolesLoading(false);\r\n }\r\n }, []);\r\n\r\n // Load group data on mount\r\n useEffect(() => {\r\n if (groupId && isValidGuid(groupId)) {\r\n loadGroup();\r\n }\r\n }, [groupId, loadGroup]);\r\n\r\n // Lazy load tab data when tab is first visited\r\n useEffect(() => {\r\n if (!visitedTabsRef.current.has(activeTab)) {\r\n visitedTabsRef.current.add(activeTab);\r\n }\r\n\r\n // Load roles only when roles or permissions tab is first visited\r\n if ((activeTab === 'roles' || activeTab === 'permissions') && roles === null && !rolesLoading) {\r\n loadRoles();\r\n }\r\n }, [activeTab, roles, rolesLoading]);\r\n\r\n const handleSave = useCallback(async () => {\r\n if (!groupId || !group) return;\r\n\r\n try {\r\n setSaving(true);\r\n setError(null);\r\n await groupsApi.update(groupId, {\r\n name: formData.name,\r\n description: formData.description || undefined\r\n });\r\n await loadGroup();\r\n setSuccess(t('groups:detail.saveSuccess', 'Groupe mis à jour avec succès'));\r\n setIsEditing(false);\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err) {\r\n console.error('Failed to save group:', err);\r\n setError(t('groups:detail.errors.saveFailed', 'Erreur lors de l\\'enregistrement'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [groupId, group, formData, loadGroup, t]);\r\n\r\n const handleActivate = useCallback(async () => {\r\n if (!groupId) return;\r\n try {\r\n await groupsApi.activate(groupId);\r\n await loadGroup();\r\n setSuccess(t('groups:detail.activateSuccess', 'Groupe activé'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err) {\r\n console.error('Failed to activate group:', err);\r\n setError(t('groups:detail.errors.activateFailed', 'Erreur lors de l\\'activation'));\r\n }\r\n }, [groupId, loadGroup, t]);\r\n\r\n const handleDeactivate = useCallback(async () => {\r\n if (!groupId) return;\r\n try {\r\n await groupsApi.deactivate(groupId);\r\n await loadGroup();\r\n setSuccess(t('groups:detail.deactivateSuccess', 'Groupe désactivé'));\r\n setTimeout(() => setSuccess(null), 3000);\r\n } catch (err) {\r\n console.error('Failed to deactivate group:', err);\r\n setError(t('groups:detail.errors.deactivateFailed', 'Erreur lors de la désactivation'));\r\n }\r\n }, [groupId, loadGroup, t]);\r\n\r\n const handleDelete = useCallback(async () => {\r\n if (!groupId || !group) return;\r\n\r\n const confirmMessage = group.isSyncedFromEntra\r\n ? t('groups:detail.confirmDeleteEntra', { name: group.name, defaultValue: `Le groupe \"${group.name}\" est synchronisé depuis Entra ID. Il sera recréé lors de la prochaine synchronisation.\\n\\nÊtes-vous sûr de vouloir le supprimer ?` })\r\n : t('groups:detail.confirmDelete', { name: group.name, defaultValue: `Êtes-vous sûr de vouloir supprimer le groupe \"${group.name}\" ?` });\r\n\r\n if (!confirm(confirmMessage)) {\r\n return;\r\n }\r\n try {\r\n await groupsApi.delete(groupId);\r\n navigate('/administration/users/groups');\r\n } catch (err) {\r\n console.error('Failed to delete group:', err);\r\n setError(t('groups:detail.errors.deleteFailed', 'Erreur lors de la suppression'));\r\n }\r\n }, [groupId, group, navigate, t]);\r\n\r\n const tabs: { id: TabId; label: string; icon: React.ElementType }[] = [\r\n { id: 'info', label: t('groups:detail.tabs.info', 'Informations'), icon: Users },\r\n { id: 'hierarchy', label: t('groups:detail.tabs.hierarchy', 'Hiérarchie'), icon: GitBranch },\r\n { id: 'members', label: t('groups:detail.tabs.members', 'Membres'), icon: Users },\r\n { id: 'roles', label: t('groups:detail.tabs.roles', 'Rôles'), icon: Shield },\r\n { id: 'tenants', label: t('groups:detail.tabs.tenants', 'Tenants'), icon: Building2 },\r\n { id: 'applications', label: t('groups:detail.tabs.applications', 'Applications'), icon: AppWindow },\r\n { id: 'permissions', label: t('groups:detail.tabs.permissions', 'Permissions'), icon: Key }\r\n ];\r\n\r\n if (!groupId || !isValidGuid(groupId)) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <div className=\"text-center\">\r\n <AlertTriangle className=\"w-12 h-12 mx-auto mb-4 text-[var(--text-tertiary)]\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('groups:detail.invalidId', 'ID de groupe invalide')}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (!group) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <div className=\"text-center\">\r\n <AlertTriangle className=\"w-12 h-12 mx-auto mb-4 text-[var(--warning-text)]\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {t('groups:detail.notFound', 'Groupe non trouvé')}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('admin:nav.administration', 'Administration'), href: '/administration' },\r\n { label: t('admin:nav.groups', 'Groupes'), href: '/administration/users/groups' },\r\n { label: group.name }\r\n ]}\r\n />\r\n\r\n {/* Scope Banner */}\r\n {hasMultipleTenants && currentTenant && (\r\n <ScopeBanner />\r\n )}\r\n\r\n {/* Header */}\r\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4\">\r\n <div className=\"flex items-center gap-4\">\r\n <button\r\n onClick={() => navigate(-1)}\r\n className=\"p-2 rounded-lg bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <ArrowLeft className=\"w-5 h-5\" />\r\n </button>\r\n <div className=\"flex items-center gap-3\">\r\n <div className={`p-3 rounded-xl ${\r\n group.isSecurityGroup\r\n ? 'bg-[var(--info-bg)] text-[var(--info-text)]'\r\n : 'bg-[var(--accent-bg)] text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? <Shield className=\"w-6 h-6\" /> : <Users className=\"w-6 h-6\" />}\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {group.name}\r\n </h1>\r\n <div className=\"flex items-center gap-2 mt-1\">\r\n {group.isActive ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-[var(--success-bg)] text-[var(--success-text)]\">\r\n <CheckCircle className=\"w-3 h-3\" />\r\n {t('common.active', 'Actif')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-[var(--error-bg)] text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-3 h-3\" />\r\n {t('common.inactive', 'Inactif')}\r\n </span>\r\n )}\r\n {group.isSyncedFromEntra && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n <Cloud className=\"w-3 h-3\" />\r\n Entra ID\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-2\">\r\n {group.isActive ? (\r\n <button\r\n onClick={handleDeactivate}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--warning-dot)] text-white hover:opacity-90 transition-colors\"\r\n >\r\n <AlertTriangle className=\"w-4 h-4\" />\r\n {t('common.deactivate', 'Désactiver')}\r\n </button>\r\n ) : (\r\n <button\r\n onClick={handleActivate}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--success-dot)] text-white hover:opacity-90 transition-colors\"\r\n >\r\n <CheckCircle className=\"w-4 h-4\" />\r\n {t('common.activate', 'Activer')}\r\n </button>\r\n )}\r\n <button\r\n onClick={handleDelete}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--error-dot)] text-white hover:opacity-90 transition-colors\"\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n {t('common.delete', 'Supprimer')}\r\n </button>\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)] flex items-center gap-3\">\r\n <AlertCircle className=\"w-5 h-5 text-[var(--error-text)] flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-[var(--error-text)]\">{error}</p>\r\n <button\r\n onClick={() => loadGroup()}\r\n className=\"mt-1 text-sm text-[var(--error-text)] hover:opacity-80 underline\"\r\n >\r\n {t('common:actions.retry', 'Réessayer')}\r\n </button>\r\n </div>\r\n <button onClick={() => setError(null)} className=\"ml-auto self-start\">\r\n <X className=\"w-4 h-4 text-[var(--error-text)]\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {success && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)] flex items-center gap-3\">\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)] flex-shrink-0\" />\r\n <p className=\"text-[var(--success-text)]\">{success}</p>\r\n </div>\r\n )}\r\n\r\n {/* Tabs */}\r\n <div className=\"border-b border-[var(--border-color)]\">\r\n <nav className=\"flex gap-1 overflow-x-auto pb-px\">\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-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\r\n activeTab === tab.id\r\n ? 'border-[var(--color-accent-500)] text-[var(--color-accent-500)]'\r\n : 'border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:border-[var(--border-color)]'\r\n }`}\r\n >\r\n <tab.icon className=\"w-4 h-4\" />\r\n {tab.label}\r\n </button>\r\n ))}\r\n </nav>\r\n </div>\r\n\r\n {/* Tab Content */}\r\n\r\n {/* Info Tab */}\r\n {activeTab === 'info' && (\r\n <div className=\"space-y-6\">\r\n {/* Basic Information */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:detail.info.basicInfo', 'Informations de base')}\r\n </h3>\r\n {!group.isSyncedFromEntra && !isEditing && (\r\n <button\r\n onClick={() => setIsEditing(true)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Edit3 className=\"w-4 h-4\" />\r\n {t('common.edit', 'Modifier')}\r\n </button>\r\n )}\r\n {isEditing && (\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => {\r\n setIsEditing(false);\r\n setFormData({ name: group.name, description: group.description || '' });\r\n }}\r\n className=\"px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel', 'Annuler')}\r\n </button>\r\n <button\r\n onClick={handleSave}\r\n disabled={saving}\r\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] 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', 'Enregistrer')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {isEditing ? (\r\n <div className=\"grid grid-cols-1 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('groups:detail.info.name', 'Nom')}\r\n </label>\r\n <input\r\n type=\"text\"\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 <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('groups:detail.info.description', '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)]\"\r\n />\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.name', 'Nom')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] font-medium\">{group.name}</p>\r\n </div>\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.type', 'Type')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] font-medium\">\r\n {group.isSecurityGroup\r\n ? t('groups:detail.info.securityGroup', 'Groupe de sécurité')\r\n : t('groups:detail.info.distributionGroup', 'Groupe de distribution')}\r\n </p>\r\n </div>\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)] sm:col-span-2\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.description', 'Description')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">{group.description || '-'}</p>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Entra Information (if synced) */}\r\n {group.isSyncedFromEntra && (\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2 mb-4\">\r\n <Cloud className=\"w-5 h-5\" />\r\n {t('groups:detail.info.entraInfo', 'Microsoft Entra ID')}\r\n </h3>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.entraObjectId', 'Object ID')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] font-mono\">{group.entraObjectId}</p>\r\n </div>\r\n {group.mail && (\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.mail', 'Email')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)] flex items-center gap-2\">\r\n <Mail className=\"w-4 h-4\" />\r\n {group.mail}\r\n </p>\r\n </div>\r\n )}\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('groups:detail.info.lastSync', 'Dernière synchronisation')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {group.lastEntraSyncAt\r\n ? new Date(group.lastEntraSyncAt).toLocaleString()\r\n : '-'}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"mt-4 p-3 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)]\">\r\n <p className=\"text-sm text-[var(--info-text)]\">\r\n {t('groups:detail.info.entraNote', 'Ce groupe est synchronisé depuis Microsoft Entra ID. Les informations de base ne peuvent pas être modifiées ici.')}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Members Summary */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] flex items-center gap-2 mb-4\">\r\n <Users className=\"w-5 h-5\" />\r\n {t('groups:detail.info.members', 'Membres')}\r\n <span className=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-[var(--bg-secondary)] text-[var(--text-secondary)]\">\r\n {group.members?.length || 0}\r\n </span>\r\n </h3>\r\n {(group.members?.length ?? 0) > 0 ? (\r\n <div className=\"space-y-2\">\r\n {group.members.slice(0, 5).map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full bg-[var(--accent-bg)] flex items-center justify-center\">\r\n <span className=\"text-sm font-medium text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0)}\r\n </span>\r\n </div>\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">{member.fullName}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{member.email}</p>\r\n </div>\r\n </Link>\r\n ))}\r\n {group.members.length > 5 && (\r\n <p className=\"text-sm text-[var(--text-secondary)] text-center py-2\">\r\n {t('groups:detail.info.moreMembers', '+ {{count}} autres membres', { count: group.members.length - 5 })}\r\n </p>\r\n )}\r\n </div>\r\n ) : (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('groups:detail.info.noMembers', 'Aucun membre dans ce groupe')}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* Metadata */}\r\n <div className=\"p-6 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)] mb-4\">\r\n {t('groups:detail.info.metadata', 'Métadonnées')}\r\n </h3>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('common.createdAt', 'Créé le')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(group.createdAt).toLocaleString()}\r\n </p>\r\n </div>\r\n {group.updatedAt && (\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('common.updatedAt', 'Modifié le')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {new Date(group.updatedAt).toLocaleString()}\r\n </p>\r\n </div>\r\n )}\r\n {group.createdBy && (\r\n <div className=\"p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <p className=\"text-xs text-[var(--text-tertiary)] uppercase tracking-wider mb-1\">\r\n {t('common.createdBy', 'Créé par')}\r\n </p>\r\n <p className=\"text-sm text-[var(--text-primary)]\">{group.createdBy}</p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Hierarchy Tab */}\r\n {activeTab === 'hierarchy' && groupId && (\r\n <HierarchyTab\r\n groupId={groupId}\r\n group={group}\r\n onRefresh={loadGroup}\r\n onSuccess={(msg) => { setSuccess(msg); setTimeout(() => setSuccess(null), 3000); }}\r\n onError={setError}\r\n />\r\n )}\r\n\r\n {/* Members Tab */}\r\n {activeTab === 'members' && groupId && (\r\n <GroupMembersTab\r\n groupId={groupId}\r\n groupName={group.name}\r\n isSyncedFromEntra={group.isSyncedFromEntra}\r\n />\r\n )}\r\n\r\n {/* Roles Tab */}\r\n {activeTab === 'roles' && groupId && (\r\n <GroupRoleAssignment\r\n groupId={groupId}\r\n assignedRoles={group.roles || []}\r\n onSave={async () => {\r\n await loadGroup(true);\r\n }}\r\n roles={roles ?? []}\r\n loading={rolesLoading}\r\n isGlobalScope={true}\r\n adminTenants={adminTenantsList.map(at => ({\r\n tenantId: at.id,\r\n tenantSlug: at.slug,\r\n tenantName: at.name,\r\n tenantType: at.type,\r\n }))}\r\n />\r\n )}\r\n\r\n {/* Tenants Tab */}\r\n {activeTab === 'tenants' && groupId && (\r\n <GroupTenantsTab groupId={groupId} groupName={group.name} />\r\n )}\r\n\r\n {/* Applications Tab */}\r\n {activeTab === 'applications' && groupId && (\r\n <GroupApplicationsTab groupId={groupId} />\r\n )}\r\n\r\n {/* Permissions Tab */}\r\n {activeTab === 'permissions' && groupId && (\r\n <GroupPermissionMatrix\r\n groupId={groupId}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["CATEGORY_STYLES","DEFAULT_CATEGORY_STYLE","GroupRoleAssignment","groupId","assignedRoles","onSave","rolesProp","loading","tenantId","isGlobalScope","adminTenants","t","useTranslation","roles","searchQuery","setSearchQuery","useState","scopeFilter","setScopeFilter","removing","setRemoving","modalOpen","setModalOpen","error","setError","removingRef","useRef","groupTenants","setGroupTenants","useEffect","cancelled","groupsApi","tenants","inheritedRoles","setInheritedRoles","inheritedLoading","setInheritedLoading","tenantOptions","useMemo","a","b","filteredAssignedRoles","scoped","ar","query","roleMap","map","r","handleRemoveRole","useCallback","roleId","roleTenantId","isGlobal","err","handleOpenModal","handleCloseModal","handleAssigned","jsxs","jsx","AlertCircle","X","Search","e","to","ChevronDown","Plus","Loader2","roleDetail","category","catStyle","customIcon","getCustomRoleIcon","removingKey","isRemoving","Globe","Building2","Trash2","AssignRoleModal","GitMerge","ir","initialTenantId","initialIsGlobalScope","onAssigned","onClose","filterCategory","setFilterCategory","filterApplication","setFilterApplication","saving","setSaving","savingRef","setRoles","rolesLoading","setRolesLoading","adminApi","result","groupTenantIds","setGroupTenantIds","applications","setApplications","tenantIds","tid","results","appMap","apps","app","id","name","modalTenants","at","modalScope","setModalScope","tenant","modalIsGlobal","modalTenantId","currentScopeRoleIds","ids","tenantAppIds","setTenantAppIds","scopedRoles","categories","cats","filteredRoles","filtered","handleAssignRole","TenantScopeSelector","Filter","c","cat","role","isAlreadyAssigned","isAssigning","getSelectAllClass","isAllSelected","getTenantItemClass","isSelected","getTenantCheckboxClass","filterAvailableTenants","allTenants","assignedTenantIds","filterAssignedTenants","pageSearchQuery","GroupTenantsTab","groupName","navigate","useNavigate","getIconForType","useTenantTypeSettings","setTenants","inheritedTenants","setInheritedTenants","setAllTenants","setLoading","showAddModal","setShowAddModal","removingTenantId","setRemovingTenantId","success","setSuccess","selectedTenantIds","setSelectedTenantIds","setPageSearchQuery","viewMode","setViewMode","adding","setAdding","loadTenants","data","inherited","loadAllTenants","handleRemoveTenant","errorMessage","addTenantsAndTrackResults","successCount","failedTenants","tenantName","filteredAvailableTenants","handleAddSelectedTenants","toggleTenantSelection","prev","toggleSelectAll","allIds","allSelected","filteredTenants","RefreshCw","LayoutGrid","LayoutList","AlertTriangle","CheckCircle","typeInfo","TenantIcon","getLucideIcon","colors","getColorClasses","Fragment","RowIcon","GitBranch","InheritedIcon","Link","LinkIcon","Check","modalTypeInfo","ModalIcon","modalColors","GroupMembersTab","isSyncedFromEntra","members","setMembers","allUsers","setAllUsers","removingUserId","setRemovingUserId","selectedUserIds","setSelectedUserIds","isAddingMultiple","setIsAddingMultiple","loadMembers","loadAllUsers","response","users","handleAddMultipleMembers","userIdsArray","userId","toggleUserSelection","next","handleRemoveMember","member","m","filteredAvailableUsers","u","getInitials","part","getViewModeButtonClass","isActive","Users","Table","Info","user","useGroupPermissions","options","loadGroup","loadGroupRoles","groupData","matrixData","matrixRoleMap","allRoles","gr","matrixRole","baseResult","useEntityPermissions","group","groupRoles","getPermissionSources","permissionId","sources","roleInheritance","info","getTenantBadgesFromRoles","sourceRoles","tenantMap","key","getSourceTypesFromRoles","isCustomRoleFn","type","s","ACTION_ICONS","Shield","Eye","Edit","UserPlus","Play","ACTION_COLORS","GroupPermissionMatrix","compact","tenantSlug","filteredResources","effectivePermissions","filters","modules","updateFilters","reloadData","isTenantMode","collapsedApps","toggleApp","useCollapsibleState","collapsedModules","setCollapsedModules","collapsedSections","setCollapsedSections","statusFilters","setStatusFilters","openPopover","setOpenPopover","customRoleId","setCustomRoleId","customRolePermissions","setCustomRolePermissions","togglingPermission","setTogglingPermission","loadingCustomRole","setLoadingCustomRole","setErrorMessage","createAdminApi","createGroupsApi","React","p","handleTogglePermission","currentPermissions","newPermissions","handleCellClick","resourceId","toggleStatusFilter","status","toggleModule","moduleId","toggleSection","sectionId","getAllPermissionsForResource","resource","allPermissions","section","getPermissionStatusForGroup","isSection","calculatePermissionStatus","permId","grantedCount","totalCount","filterModulesByStatus","calculateModuleWithSectionsStatus","applyStatusFilters","grouped","appGroup","groupedResources","groupByApplicationWithSections","totalModuleCount","sum","addUniqueSourceRole","getSourceRolesForResource","perm","isCustomRole","roleName","getDisplayName","groupAsRole","getGroupPermissionInheritance","_roleId","isGranted","isFromCustomRole","inheritedRole","getPaddingClass","level","getResourceIcon","Database","FileText","Box","getResourceLabelClass","renderResourceRows","resources","baseIndex","idx","renderResourceRow","renderSectionRow","sectionWithResources","moduleIndex","sectionIndex","hasResources","isSectionCollapsed","renderSectionRows","sections","hasSections","isModuleCollapsed","rowIndex","hasChildren","isCollapsed","cellBg","getPermissionCellBackground","isPopoverOpen","paddingLeft","ChevronRight","PermissionStatusIndicator","PermissionPopover","isCustom","displayName","scopeIcon","scopeTitle","Star","source","UserCheck","User","isToggling","actionColor","icon","mod","Ban","scopeLabel","appKey","isAppCollapsed","FolderOpen","moduleWithSections","module","GroupApplicationsTab","expandedApps","setExpandedApps","loadApplicationAccess","toggleExpand","appId","Boxes","ApplicationCard","isExpanded","onToggle","icons","LucideIcons","AppIcon","permissionsByModule","groups","Layers","Key","extractActionFromPath","path","ScopeBanner","className","showSwitch","onSwitchClick","currentTenant","hasMultipleTenants","isGlobalView","useTenant","ArrowRightLeft","isB2B","VALID_TABS","isValidGuid","value","useGroupDetailState","setGroup","isEditing","setIsEditing","formData","setFormData","HierarchyTab","onRefresh","onSuccess","onError","allGroups","setAllGroups","loadingGroups","setLoadingGroups","showParentSelector","setShowParentSelector","showChildSelector","setShowChildSelector","showCreateChild","setShowCreateChild","parentSearch","setParentSearch","childSearch","setChildSearch","newChildName","setNewChildName","newChildDescription","setNewChildDescription","newChildIsSecurityGroup","setNewChildIsSecurityGroup","inheritedMembers","setInheritedMembers","loadingInheritedMembers","setLoadingInheritedMembers","loadAllGroups","membersByAncestor","excludedForParent","queue","current","g","parentCandidates","existingChildIds","childCandidates","handleSetParent","parentId","handleClearParent","handleAddChild","childId","handleRemoveChild","childName","handleCreateChild","CornerDownRight","Edit3","Unlink","ancestorGroup","child","GroupDetailPage","useParams","adminTenantsList","useAdminTenants","activeTab","setActiveTab","useTabNavigation","visitedTabsRef","silent","loadRoles","handleSave","handleActivate","handleDeactivate","handleDelete","confirmMessage","tabs","AppWindow","Breadcrumb","ArrowLeft","Cloud","tab","Save","Mail","msg"],"mappings":"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"}