@atlashub/smartstack 3.21.0 → 3.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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":"index-DCcl7Qof.js","sources":["../../src/pages/platform/administration/entra/EntraDashboardPage.tsx","../../src/pages/platform/administration/entra/EntraGroupsPage.tsx","../../src/pages/platform/administration/entra/EntraUsersPage.tsx","../../src/pages/platform/administration/entra/EntraConflictsPage.tsx","../../src/pages/platform/administration/entra/EntraSettingsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { Tooltip } from '@/components/ui/Tooltip';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport {\r\n Cloud,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n CheckCircle,\r\n XCircle,\r\n Clock,\r\n Users,\r\n Building2,\r\n Link2,\r\n Play,\r\n AlertCircle,\r\n Calendar,\r\n Database,\r\n} from 'lucide-react';\r\nimport {\r\n entraApi,\r\n type EntraSyncStatusDto,\r\n type EntraSyncResultDto,\r\n} from '@/services/api/entraApi';\r\n\r\n// ============================================\r\n// Sync Status Card Component\r\n// ============================================\r\n\r\ninterface SyncStatusCardProps {\r\n readonly resourceType: string;\r\n readonly icon: LucideIcon;\r\n readonly status: string;\r\n readonly lastFullSyncAt: string | null;\r\n readonly lastDeltaSyncAt: string | null;\r\n readonly totalItemsSynced: number;\r\n readonly pendingConflicts: number;\r\n readonly lastError: string | null;\r\n readonly syncing: boolean;\r\n readonly canSync: boolean;\r\n readonly onSync: () => void;\r\n readonly formatDate: (date: string | null) => string;\r\n readonly t: (key: string, options?: Record<string, unknown>) => string;\r\n}\r\n\r\nfunction SyncStatusCard({\r\n resourceType,\r\n icon: Icon,\r\n status,\r\n lastFullSyncAt,\r\n lastDeltaSyncAt,\r\n totalItemsSynced,\r\n pendingConflicts,\r\n lastError,\r\n syncing,\r\n canSync,\r\n onSync,\r\n formatDate,\r\n t,\r\n}: SyncStatusCardProps) {\r\n const getStatusConfig = () => {\r\n switch (status) {\r\n case 'Success':\r\n return {\r\n icon: CheckCircle,\r\n color: 'text-[var(--success-text)]',\r\n bg: 'bg-[var(--success-bg)]',\r\n label: t('common:success'),\r\n };\r\n case 'Failed':\r\n return {\r\n icon: XCircle,\r\n color: 'text-[var(--error-text)]',\r\n bg: 'bg-[var(--error-bg)]',\r\n label: t('common:failed'),\r\n };\r\n case 'Running':\r\n return {\r\n icon: Loader2,\r\n color: 'text-[var(--color-accent-500)]',\r\n bg: 'bg-[var(--color-accent-100)]',\r\n label: t('common:running'),\r\n animate: true,\r\n };\r\n default:\r\n return {\r\n icon: Clock,\r\n color: 'text-[var(--text-tertiary)]',\r\n bg: 'bg-[var(--bg-tertiary)]',\r\n label: t('common:pending'),\r\n };\r\n }\r\n };\r\n\r\n const statusConfig = getStatusConfig();\r\n const StatusIcon = statusConfig.icon;\r\n\r\n return (\r\n <div className=\"h-full flex flex-col rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] overflow-hidden shadow-sm hover:shadow-md transition-shadow\">\r\n {/* Header with gradient */}\r\n <div className=\"px-4 py-3 bg-gradient-to-r from-[var(--color-accent-500)]/10 to-[var(--color-accent-600)]/5 border-b border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-lg bg-[var(--color-accent-500)]/20\">\r\n <Icon className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n </div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">\r\n {t(`entra:resourceTypes.${resourceType.toLowerCase()}`)}\r\n </h3>\r\n </div>\r\n <div className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium ${statusConfig.bg} ${statusConfig.color}`}>\r\n <StatusIcon className={`w-3.5 h-3.5 ${statusConfig.animate ? 'animate-spin' : ''}`} />\r\n {statusConfig.label}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Grid */}\r\n <div className=\"flex-1 flex flex-col p-4\">\r\n <div className=\"grid grid-cols-3 gap-3 mb-4\">\r\n <div className=\"text-center p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-center gap-1 mb-1\">\r\n <Database className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <p className=\"text-xl font-bold text-[var(--text-primary)]\">{totalItemsSynced.toLocaleString()}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{t('entra:dashboard.itemsSynced')}</p>\r\n </div>\r\n <div className=\"text-center p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-center gap-1 mb-1\">\r\n <Calendar className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\" title={formatDate(lastFullSyncAt)}>\r\n {lastFullSyncAt ? new Date(lastFullSyncAt).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' }) : '-'}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{t('entra:dashboard.lastFullSync')}</p>\r\n </div>\r\n <div className=\"text-center p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-center gap-1 mb-1\">\r\n <RefreshCw className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\" title={formatDate(lastDeltaSyncAt)}>\r\n {lastDeltaSyncAt ? new Date(lastDeltaSyncAt).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' }) : '-'}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{t('entra:dashboard.lastDeltaSync')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* Pending Conflicts Warning */}\r\n {pendingConflicts > 0 && (\r\n <div className=\"flex items-center gap-2 p-3 mb-4 rounded-lg bg-[var(--warning-bg)] border border-[var(--warning-border)]\">\r\n <AlertCircle className=\"w-4 h-4 text-[var(--warning-text)] flex-shrink-0\" />\r\n <span className=\"text-sm text-[var(--warning-text)] font-medium\">\r\n {pendingConflicts} {t('entra:dashboard.pendingConflicts')}\r\n </span>\r\n </div>\r\n )}\r\n\r\n {/* Last Error */}\r\n {lastError && (\r\n <div className=\"p-3 mb-4 rounded-lg bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <p className=\"text-xs text-[var(--error-text)] line-clamp-2\">{lastError}</p>\r\n </div>\r\n )}\r\n\r\n {/* Action Button - Always at bottom */}\r\n <Tooltip\r\n content={!canSync ? t('entra:dashboard.noSyncPermission') : undefined}\r\n position=\"top\"\r\n variant=\"error\"\r\n disabled={canSync}\r\n >\r\n <button\r\n onClick={onSync}\r\n disabled={syncing || !canSync}\r\n className=\"mt-auto w-full inline-flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium 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 shadow-sm\"\r\n >\r\n {syncing ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <RefreshCw className=\"w-4 h-4\" />\r\n )}\r\n {t('entra:dashboard.syncNow')}\r\n </button>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport function EntraDashboardPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const { hasPermission } = useAuth();\r\n const [loading, setLoading] = useState(true);\r\n const [refreshing, setRefreshing] = useState(false);\r\n const [syncStatus, setSyncStatus] = useState<EntraSyncStatusDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [syncing, setSyncing] = useState<string | null>(null);\r\n const [lastSyncResult, setLastSyncResult] = useState<EntraSyncResultDto | null>(null);\r\n\r\n // Permission check for sync operations\r\n const canSync = hasPermission('administration.entra.execute');\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setError(null);\r\n const status = await entraApi.dashboard.getSyncStatus();\r\n setSyncStatus(Array.isArray(status) ? status : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load Entra dashboard data:', err);\r\n setSyncStatus([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('entra:dashboard.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n setRefreshing(false);\r\n }\r\n }, [t]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleRefresh = () => {\r\n setRefreshing(true);\r\n loadData();\r\n };\r\n\r\n const handleSync = async (type: 'all' | 'users' | 'groups' | 'memberships') => {\r\n setSyncing(type);\r\n setLastSyncResult(null);\r\n try {\r\n let result: EntraSyncResultDto;\r\n switch (type) {\r\n case 'users':\r\n result = await entraApi.sync.syncUsers();\r\n break;\r\n case 'groups':\r\n result = await entraApi.sync.syncGroups();\r\n break;\r\n case 'memberships':\r\n result = await entraApi.sync.syncMemberships();\r\n break;\r\n default:\r\n result = await entraApi.sync.syncAll();\r\n }\r\n setLastSyncResult(result);\r\n await loadData();\r\n } catch (err: unknown) {\r\n console.error('Sync failed:', err);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 403) {\r\n setError(t('entra:dashboard.syncPermissionDenied'));\r\n } else if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else {\r\n setError(t('entra:dashboard.syncError'));\r\n }\r\n } finally {\r\n setSyncing(null);\r\n }\r\n };\r\n\r\n const handleForceFullSync = async () => {\r\n if (!confirm(t('entra:dashboard.forceFullSyncConfirm'))) return;\r\n setSyncing('force');\r\n try {\r\n await entraApi.sync.forceFullSync();\r\n await loadData();\r\n } catch (err: unknown) {\r\n console.error('Force full sync failed:', err);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 403) {\r\n setError(t('entra:dashboard.syncPermissionDenied'));\r\n } else if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else {\r\n setError(t('entra:dashboard.syncError'));\r\n }\r\n } finally {\r\n setSyncing(null);\r\n }\r\n };\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return t('common:never');\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\r\n };\r\n\r\n const getResourceIcon = (resourceType: string): LucideIcon => {\r\n switch (resourceType) {\r\n case 'Users':\r\n return Users;\r\n case 'Groups':\r\n return Building2;\r\n case 'Memberships':\r\n return Link2;\r\n default:\r\n return Cloud;\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 const totalPendingConflicts = syncStatus.reduce((sum, s) => sum + s.pendingConflicts, 0);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.dashboard', 'Dashboard') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <Cloud className=\"w-6 h-6 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:dashboard.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:dashboard.subtitle')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={handleRefresh}\r\n disabled={refreshing}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] disabled:opacity-50 transition-colors\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${refreshing ? 'animate-spin' : ''}`} />\r\n {t('common:refresh')}\r\n </button>\r\n <Tooltip\r\n content={!canSync ? t('entra:dashboard.noSyncPermission') : undefined}\r\n position=\"bottom\"\r\n variant=\"error\"\r\n disabled={canSync}\r\n >\r\n <button\r\n onClick={() => handleSync('all')}\r\n disabled={syncing !== null || !canSync}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium 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 {syncing === 'all' ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Play className=\"w-4 h-4\" />\r\n )}\r\n {t('entra:dashboard.syncAll')}\r\n </button>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Pending Conflicts Warning */}\r\n {totalPendingConflicts > 0 && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--warning-bg)] border border-[var(--warning-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--warning-text)]\">\r\n <AlertCircle className=\"w-5 h-5\" />\r\n <span>\r\n {t('entra:dashboard.conflictsWarning', { count: totalPendingConflicts })}\r\n </span>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Last Sync Result */}\r\n {lastSyncResult && (\r\n <div className={`p-4 rounded-[var(--radius-card)] border ${\r\n lastSyncResult.success\r\n ? 'bg-[var(--success-bg)] border-[var(--success-border)]'\r\n : 'bg-[var(--error-bg)] border-[var(--error-border)]'\r\n }`}>\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n {lastSyncResult.success ? (\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n ) : (\r\n <XCircle className=\"w-5 h-5 text-[var(--error-text)]\" />\r\n )}\r\n <span className={lastSyncResult.success ? 'text-[var(--success-text)]' : 'text-[var(--error-text)]'}>\r\n {lastSyncResult.success\r\n ? t('entra:dashboard.syncSuccess')\r\n : t('entra:dashboard.syncFailed')}\r\n </span>\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:dashboard.syncStats', {\r\n created: lastSyncResult.created,\r\n updated: lastSyncResult.updated,\r\n deleted: lastSyncResult.deleted,\r\n })}\r\n </div>\r\n </div>\r\n {lastSyncResult.errorMessage && (\r\n <p className=\"mt-2 text-sm text-[var(--error-text)]\">\r\n {lastSyncResult.errorMessage}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Sync Status Cards */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\r\n {syncStatus.map((status) => (\r\n <SyncStatusCard\r\n key={status.resourceType}\r\n resourceType={status.resourceType}\r\n icon={getResourceIcon(status.resourceType)}\r\n status={status.status}\r\n lastFullSyncAt={status.lastFullSyncAt}\r\n lastDeltaSyncAt={status.lastDeltaSyncAt}\r\n totalItemsSynced={status.totalItemsSynced}\r\n pendingConflicts={status.pendingConflicts}\r\n lastError={status.lastError}\r\n syncing={syncing === status.resourceType.toLowerCase()}\r\n canSync={canSync}\r\n onSync={() => handleSync(status.resourceType.toLowerCase() as 'users' | 'groups' | 'memberships')}\r\n formatDate={formatDate}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n\r\n {/* Force Full Sync */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">\r\n {t('entra:dashboard.forceFullSync')}\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:dashboard.forceFullSyncDescription')}\r\n </p>\r\n </div>\r\n <Tooltip\r\n content={!canSync ? t('entra:dashboard.noSyncPermission') : undefined}\r\n position=\"left\"\r\n variant=\"error\"\r\n disabled={canSync}\r\n >\r\n <button\r\n onClick={handleForceFullSync}\r\n disabled={syncing !== null || !canSync}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--warning-border)] bg-[var(--warning-bg)] text-[var(--warning-text)] hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {syncing === 'force' ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <AlertTriangle className=\"w-4 h-4\" />\r\n )}\r\n {t('entra:dashboard.forceFullSync')}\r\n </button>\r\n </Tooltip>\r\n </div>\r\n </div>\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 { Link, useNavigate } from 'react-router-dom';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n Cloud,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n Search,\r\n Users,\r\n Shield,\r\n Plus,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n LayoutGrid,\r\n List,\r\n Filter,\r\n Building2,\r\n GitBranch,\r\n} from 'lucide-react';\r\nimport {\r\n entraApi,\r\n type EntraGroupDto,\r\n type EntraGroupMemberDto,\r\n} from '@/services/api/entraApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\n\r\ntype ViewMode = 'cards' | 'table';\r\ntype GroupTypeFilter = 'all' | 'security' | 'distribution';\r\n\r\ninterface GroupWithMembers extends EntraGroupDto {\r\n membersLoaded?: EntraGroupMemberDto[];\r\n}\r\n\r\nconst getGroupHierarchyDisplay = (group: EntraGroupDto) => {\r\n if (group.parentGroupName) {\r\n return (\r\n <span className=\"flex items-center gap-1 text-xs\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.parentGroupName}\r\n </span>\r\n );\r\n }\r\n if (group.childGroupCount > 0) {\r\n return (\r\n <span className=\"flex items-center gap-1 text-xs text-[var(--text-tertiary)]\">\r\n {group.childGroupCount} child groups\r\n </span>\r\n );\r\n }\r\n return <span className=\"text-xs text-[var(--text-tertiary)]\">-</span>;\r\n};\r\n\r\nexport function EntraGroupsPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'admin', 'common']);\r\n const { hasPermission } = useAuth();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const navigate = useNavigate();\r\n const [loading, setLoading] = useState(true);\r\n const [groups, setGroups] = useState<GroupWithMembers[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [selectedGroup, setSelectedGroup] = useState<GroupWithMembers | null>(null);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [expandedGroupId, setExpandedGroupId] = useState<string | null>(null);\r\n const [members, setMembers] = useState<Record<string, EntraGroupMemberDto[]>>({});\r\n const [loadingMembers, setLoadingMembers] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [groupTypeFilter, setGroupTypeFilter] = useState<GroupTypeFilter>('all');\r\n const [assigning, setAssigning] = useState(false);\r\n\r\n const canAssign = hasPermission('administration.entra.assign');\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setError(null);\r\n const [groupsData, rolesData] = await Promise.all([\r\n entraApi.groups.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n setGroups(Array.isArray(groupsData) ? groupsData : []);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load Entra groups:', err);\r\n setGroups([]);\r\n setRoles([]);\r\n const axiosError = err as { response?: { status?: number; data?: { code?: string } } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else if (axiosError.response?.data?.code === 'TENANT_REQUIRED') {\r\n setError(t('entra:groups.tenantRequired'));\r\n } else {\r\n setError(t('entra:groups.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await entraApi.groups.getMembers(groupId);\r\n setMembers(prev => ({ ...prev, [groupId]: data }));\r\n setExpandedGroupId(groupId);\r\n } catch (err) {\r\n console.error('Failed to load members:', err);\r\n setError(t('entra:groups.loadMembersError'));\r\n } finally {\r\n setLoadingMembers(null);\r\n }\r\n };\r\n\r\n const reloadGroupsAndRoles = useCallback(async () => {\r\n const [groupsData, rolesData] = await Promise.all([\r\n entraApi.groups.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n const safeGroupsData = Array.isArray(groupsData) ? groupsData : [];\r\n setGroups(safeGroupsData);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n return safeGroupsData;\r\n }, [currentTenant?.id]);\r\n\r\n const handleAssignRole = async (roleId: string, isInheritable: boolean = true) => {\r\n if (!selectedGroup) return;\r\n setAssigning(true);\r\n try {\r\n await entraApi.groups.assignRole(selectedGroup.id, { roleId, isInheritable });\r\n const safeGroupsData = await reloadGroupsAndRoles();\r\n const updatedGroup = safeGroupsData.find(g => g.id === selectedGroup.id);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('entra:groups.assignError'));\r\n } finally {\r\n setAssigning(false);\r\n }\r\n };\r\n\r\n const handleRemoveRole = async (groupId: string, roleId: string) => {\r\n if (!confirm(t('entra:groups.removeRoleConfirm'))) return;\r\n try {\r\n await entraApi.groups.removeRole(groupId, roleId);\r\n await reloadGroupsAndRoles();\r\n if (selectedGroup?.id === groupId) {\r\n const updatedGroups = await entraApi.groups.getAll();\r\n const updatedGroup = updatedGroups.find(g => g.id === groupId);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n }\r\n } catch (err) {\r\n console.error('Failed to remove role:', err);\r\n setError(t('entra:groups.removeError'));\r\n }\r\n };\r\n\r\n const filteredGroups = groups.filter((g) => {\r\n const matchesSearch =\r\n g.displayName.toLowerCase().includes(searchQuery.toLowerCase()) ||\r\n g.description?.toLowerCase().includes(searchQuery.toLowerCase());\r\n\r\n const matchesType =\r\n groupTypeFilter === 'all' ||\r\n (groupTypeFilter === 'security' && g.isSecurityGroup) ||\r\n (groupTypeFilter === 'distribution' && !g.isSecurityGroup);\r\n\r\n return matchesSearch && matchesType;\r\n });\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return '-';\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\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 return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.groups', 'Groups') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-blue-500/10\">\r\n <Cloud className=\"w-6 h-6 text-blue-500\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:groups.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:groups.subtitle', { count: groups.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-blue-500/10 border border-blue-500/20\">\r\n <div className=\"flex items-start gap-3\">\r\n <Cloud className=\"w-5 h-5 text-blue-500 flex-shrink-0 mt-0.5\" />\r\n <div>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {t('entra:groups.syncedInfo')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n {t('entra:groups.syncedInfoDescription')}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"ml-auto p-1 hover:bg-[var(--error-text)]/10 rounded\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filters */}\r\n <div className=\"flex flex-col sm:flex-row gap-4\">\r\n {/* Search */}\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('entra:groups.searchPlaceholder')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Type Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={groupTypeFilter}\r\n onChange={(e) => setGroupTypeFilter(e.target.value as GroupTypeFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allTypes')}</option>\r\n <option value=\"security\">{t('admin:groups.securityGroup')}</option>\r\n <option value=\"distribution\">{t('admin:groups.distributionGroup')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\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={`p-2 rounded-[var(--radius-button)] transition-colors ${\r\n viewMode === 'cards'\r\n ? 'bg-[var(--color-accent-500)] text-white'\r\n : 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n title={t('admin:groups.cardView')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${\r\n viewMode === 'table'\r\n ? 'bg-[var(--color-accent-500)] text-white'\r\n : 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n title={t('admin:groups.tableView')}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Groups List */}\r\n {filteredGroups.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {searchQuery || groupTypeFilter !== 'all'\r\n ? t('admin:groups.noResults')\r\n : t('entra:groups.noGroups')}\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\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-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.groupName')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:type')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.members')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('entra:groups.hierarchy')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.assignedRoles')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('entra:groups.lastSynced')}\r\n </th>\r\n {canAssign && !isGlobalView && (\r\n <th className=\"px-4 py-3 text-right text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:actionsColumn')}\r\n </th>\r\n )}\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredGroups.map((group) => (\r\n <tr\r\n key={group.id}\r\n className=\"hover:bg-[var(--bg-hover)] cursor-pointer\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-4 h-4\" />\r\n ) : (\r\n <Building2 className=\"w-4 h-4\" />\r\n )}\r\n </div>\r\n <div>\r\n <span className=\"font-medium text-[var(--text-primary)]\">{group.displayName}</span>\r\n {group.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate max-w-xs\">\r\n {group.description}\r\n </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-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n <span className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n {group.memberCount}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {getGroupHierarchyDisplay(group)}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {group.assignedRoles.slice(0, 2).map((role) => (\r\n <span\r\n key={role.roleId}\r\n className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\"\r\n >\r\n {role.roleName}\r\n </span>\r\n ))}\r\n {group.assignedRoles.length > 2 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n +{group.assignedRoles.length - 2}\r\n </span>\r\n )}\r\n {group.inheritedRoles.length > 0 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-green-500/10 text-green-600\" title={t('entra:groups.inheritedRoles')}>\r\n +{group.inheritedRoles.length} {t('entra:groups.inherited')}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-xs text-[var(--text-tertiary)]\">\r\n {formatDate(group.lastSyncedAt)}\r\n </td>\r\n {canAssign && !isGlobalView && (\r\n <td className=\"px-4 py-3 text-right\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={() => {\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n title={t('admin:groups.assignRole')}\r\n >\r\n <Plus className=\"w-4 h-4\" />\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 {filteredGroups.length > 0 && viewMode !== 'table' && (\r\n /* Cards View */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {filteredGroups.map((group) => (\r\n <button\r\n type=\"button\"\r\n key={group.id}\r\n className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)] overflow-hidden cursor-pointer hover:border-[var(--color-accent-500)] transition-colors text-left\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n >\r\n {/* Card Header */}\r\n <div className=\"p-4\">\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2.5 rounded-[var(--radius-button)] flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-5 h-5\" />\r\n ) : (\r\n <Building2 className=\"w-5 h-5\" />\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <span className=\"font-semibold text-[var(--text-primary)] truncate\">\r\n {group.displayName}\r\n </span>\r\n <span className={`px-2 py-0.5 text-xs rounded-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500 border border-blue-500/20'\r\n : 'bg-purple-500/10 text-purple-500 border border-purple-500/20'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n {!group.isActive && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n {t('common:inactive')}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1 line-clamp-2\">\r\n {group.description}\r\n </p>\r\n )}\r\n <div className=\"flex items-center gap-4 mt-2 text-sm text-[var(--text-tertiary)] flex-wrap\">\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n loadMembers(group.id);\r\n }}\r\n className=\"flex items-center gap-1 hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.memberCount', { count: group.memberCount })}\r\n {loadingMembers === group.id && (\r\n <Loader2 className=\"w-3 h-3 animate-spin ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId === group.id && (\r\n <ChevronUp className=\"w-3 h-3 ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId !== group.id && (\r\n <ChevronDown className=\"w-3 h-3 ml-1\" />\r\n )}\r\n </button>\r\n {group.childGroupCount > 0 && (\r\n <span className=\"flex items-center gap-1 text-xs\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.childGroupCount} {t('entra:groups.childGroups')}\r\n </span>\r\n )}\r\n </div>\r\n {group.parentGroupName && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1 flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('entra:groups.parentGroup')}: {group.parentGroupName}\r\n </p>\r\n )}\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('entra:groups.lastSynced')}: {formatDate(group.lastSyncedAt)}\r\n </p>\r\n </div>\r\n </div>\r\n {canAssign && !isGlobalView && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors flex-shrink-0\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.assignRole')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Assigned Roles */}\r\n {(group.assignedRoles.length > 0 || group.inheritedRoles.length > 0) && (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n {group.assignedRoles.length > 0 && (\r\n <>\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {t('admin:groups.assignedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2 mb-3\">\r\n {group.assignedRoles.map((role) => (\r\n <div\r\n key={role.roleId}\r\n className=\"inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-badge)] bg-[var(--bg-primary)] border border-[var(--border-color)] group\"\r\n >\r\n <Shield className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n <span className=\"text-sm text-[var(--text-primary)]\">{role.roleName}</span>\r\n {role.isInheritable && (\r\n <span className=\"text-xs text-green-600\" title={t('entra:groups.inheritableRole')}>\r\n ↓\r\n </span>\r\n )}\r\n {canAssign && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleRemoveRole(group.id, role.roleId);\r\n }}\r\n className=\"ml-1 p-0.5 rounded opacity-0 group-hover:opacity-100 hover:bg-[var(--error-bg)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] transition-all\"\r\n title={t('common:remove')}\r\n >\r\n <X className=\"w-3 h-3\" />\r\n </button>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n {group.inheritedRoles.length > 0 && (\r\n <>\r\n <h4 className=\"text-xs font-medium text-[var(--text-tertiary)] mb-2 flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('entra:groups.inheritedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {group.inheritedRoles.map((role) => (\r\n <div\r\n key={`${role.roleId}-${role.sourceGroupId}`}\r\n className=\"inline-flex items-center gap-2 px-2 py-1 rounded-[var(--radius-badge)] bg-green-500/5 border border-green-500/20\"\r\n title={`${t('entra:groups.inheritedFrom')} ${role.sourceGroupName}`}\r\n >\r\n <Shield className=\"w-3 h-3 text-green-600\" />\r\n <span className=\"text-xs text-green-700\">{role.roleName}</span>\r\n <span className=\"text-xs text-green-600/60\">← {role.sourceGroupName}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Members Panel */}\r\n {expandedGroupId === group.id && members[group.id] && (\r\n <div className=\"border-t border-[var(--border-color)] bg-[var(--bg-primary)]\" onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()} role=\"presentation\">\r\n <div className=\"p-4\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center gap-2\">\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.members')} ({members[group.id].length})\r\n </h4>\r\n {members[group.id].length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.noMembers')}\r\n </p>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-64 overflow-y-auto\">\r\n {members[group.id].slice(0, 10).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-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0).toUpperCase()}\r\n </div>\r\n <div className=\"min-w-0 flex-1\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">\r\n {member.email}\r\n </p>\r\n </div>\r\n {!member.isDirect && member.sourceGroupName && (\r\n <span className=\"text-xs text-[var(--text-tertiary)] flex items-center gap-1\" title={t('entra:groups.memberFromChildGroup')}>\r\n <GitBranch className=\"w-3 h-3\" />\r\n </span>\r\n )}\r\n </Link>\r\n ))}\r\n </div>\r\n )}\r\n {members[group.id].length > 10 && (\r\n <p className=\"mt-3 text-center text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.showingMembers', {\r\n shown: 10,\r\n total: members[group.id].length,\r\n })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {showAssignModal && selectedGroup && (\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-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.assignRoleTitle')}\r\n </h2>\r\n <button\r\n onClick={() => {\r\n setShowAssignModal(false);\r\n setSelectedGroup(null);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4\">\r\n <p className=\"text-sm text-[var(--text-secondary)] mb-4\">\r\n {t('admin:groups.assignRoleDescription', { group: selectedGroup.displayName })}\r\n </p>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {roles\r\n .filter((role) => !selectedGroup.assignedRoles.some(r => r.roleId === role.id))\r\n .map((role) => (\r\n <button\r\n key={role.id}\r\n onClick={() => handleAssignRole(role.id)}\r\n disabled={assigning}\r\n className=\"w-full flex items-center gap-3 p-3 rounded-[var(--radius-button)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors text-left disabled:opacity-50\"\r\n >\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n <div className=\"flex-1\">\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n {assigning && (\r\n <Loader2 className=\"w-4 h-4 animate-spin text-[var(--color-accent-500)]\" />\r\n )}\r\n </button>\r\n ))}\r\n {roles.filter((role) => !selectedGroup.assignedRoles.some(r => r.roleId === role.id)).length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('admin:groups.allRolesAssigned')}\r\n </p>\r\n )}\r\n </div>\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 { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n Users,\r\n RefreshCw,\r\n AlertTriangle,\r\n CheckCircle,\r\n XCircle,\r\n Mail,\r\n Calendar,\r\n ExternalLink,\r\n} from 'lucide-react';\r\nimport { adminApi, type UserListDto } from '@/services/api/adminApi';\r\nimport { DataTable, type DataTableColumn } from '@/components/ui/DataTable';\r\n\r\nexport function EntraUsersPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const navigate = useNavigate();\r\n const [loading, setLoading] = useState(true);\r\n const [users, setUsers] = useState<UserListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n // Only fetch users synced from Entra ID (have entraObjectId)\r\n const response = await adminApi.users.getAll({ pageSize: 1000, entraOnly: true });\r\n setUsers(response?.items ?? []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load users:', err);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('entra:users.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return t('common:never');\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\r\n };\r\n\r\n // Define columns for DataTable\r\n const columns: DataTableColumn<UserListDto>[] = [\r\n {\r\n key: 'fullName',\r\n label: t('entra:users.columns.user'),\r\n sortable: true,\r\n render: (user) => (\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-primary-100)] dark:bg-[var(--color-primary-900)] flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-sm font-medium text-[var(--color-primary-600)]\">\r\n {user.fullName?.charAt(0).toUpperCase() || '?'}\r\n </span>\r\n </div>\r\n <span className=\"font-medium text-[var(--text-primary)]\">{user.fullName}</span>\r\n </div>\r\n ),\r\n },\r\n {\r\n key: 'email',\r\n label: t('entra:users.columns.email'),\r\n sortable: true,\r\n render: (user) => (\r\n <div className=\"flex items-center gap-1 text-sm text-[var(--text-secondary)]\">\r\n <Mail className=\"w-4 h-4\" />\r\n {user.email}\r\n </div>\r\n ),\r\n },\r\n {\r\n key: 'isActive',\r\n label: t('entra:users.columns.status'),\r\n sortable: true,\r\n render: (user) =>\r\n user.isActive ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400\">\r\n <CheckCircle className=\"w-3 h-3\" />\r\n {t('common:active')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400\">\r\n <XCircle className=\"w-3 h-3\" />\r\n {t('common:inactive')}\r\n </span>\r\n ),\r\n },\r\n {\r\n key: 'lastEntraSyncAt',\r\n label: t('entra:users.columns.lastSync'),\r\n sortable: true,\r\n render: (user) => (\r\n <div className=\"flex items-center gap-1 text-sm text-[var(--text-secondary)]\">\r\n <Calendar className=\"w-4 h-4\" />\r\n {formatDate(user.lastEntraSyncAt)}\r\n </div>\r\n ),\r\n },\r\n {\r\n key: 'actions',\r\n label: t('entra:users.columns.actions'),\r\n align: 'right',\r\n render: (user) => (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n navigate(`/administration/users/${user.id}`);\r\n }}\r\n className=\"inline-flex items-center gap-1 text-sm text-[var(--color-primary-600)] hover:underline\"\r\n >\r\n {t('common:viewDetails')}\r\n <ExternalLink className=\"w-4 h-4\" />\r\n </button>\r\n ),\r\n },\r\n ];\r\n\r\n // Custom search filter for users\r\n const searchFilter = (user: UserListDto, searchTerm: string) => {\r\n const search = searchTerm.toLowerCase();\r\n return (\r\n user.fullName?.toLowerCase().includes(search) ||\r\n user.email?.toLowerCase().includes(search) ||\r\n false\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.users', 'Users') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-lg bg-[var(--color-primary-100)] dark:bg-[var(--color-primary-900)]\">\r\n <Users className=\"w-6 h-6 text-[var(--color-primary-600)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:users.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:users.subtitle', { count: users.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg border border-[var(--border-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] hover:bg-[var(--bg-secondary)]\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800\">\r\n <div className=\"flex items-center gap-2 text-red-700 dark:text-red-400\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* DataTable */}\r\n <DataTable\r\n data={users}\r\n columns={columns}\r\n loading={loading}\r\n searchable\r\n searchPlaceholder={t('entra:users.searchPlaceholder')}\r\n searchFilter={searchFilter}\r\n pagination={{ pageSize: 20, showSizeSelector: true }}\r\n onRowClick={(user) => navigate(`/administration/users/${user.id}`)}\r\n getRowKey={(user) => user.id}\r\n emptyMessage={t('entra:users.noUsers')}\r\n emptyIcon={<Users className=\"w-12 h-12 mx-auto text-[var(--text-secondary)] opacity-50\" />}\r\n defaultSortKey=\"fullName\"\r\n striped\r\n />\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useRef } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n AlertTriangle,\r\n RefreshCw,\r\n Loader2,\r\n CheckCircle,\r\n} from 'lucide-react';\r\nimport {\r\n entraApi,\r\n type EntraSyncConflictDto,\r\n type ResolveConflictRequest,\r\n} from '@/services/api/entraApi';\r\nimport { ConflictCard, ResolutionModal } from '@/components/platform/administration/entra';\r\n\r\n// ============================================\r\n// Main Component\r\n// ============================================\r\n\r\nexport function EntraConflictsPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const [loading, setLoading] = useState(true);\r\n const [conflicts, setConflicts] = useState<EntraSyncConflictDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [selectedConflict, setSelectedConflict] = useState<EntraSyncConflictDto | null>(null);\r\n const [resolving, setResolving] = useState(false);\r\n\r\n // Abort controller ref for preventing race conditions\r\n const abortControllerRef = useRef<AbortController | null>(null);\r\n const isLoadingRef = useRef(false);\r\n\r\n const loadData = useCallback(async () => {\r\n // Prevent concurrent loads\r\n if (isLoadingRef.current) return;\r\n\r\n // Cancel any pending request\r\n if (abortControllerRef.current) {\r\n abortControllerRef.current.abort();\r\n }\r\n\r\n abortControllerRef.current = new AbortController();\r\n isLoadingRef.current = true;\r\n\r\n try {\r\n setError(null);\r\n const data = await entraApi.conflicts.getAll();\r\n setConflicts(Array.isArray(data) ? data : []);\r\n } catch (err: unknown) {\r\n // Ignore abort errors\r\n if (err instanceof Error && err.name === 'AbortError') {\r\n return;\r\n }\r\n // Log error type only, not the full error object (PII protection)\r\n console.error('Failed to load conflicts:', err instanceof Error ? err.message : 'Unknown error');\r\n setConflicts([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('entra:conflicts.loadError'));\r\n }\r\n } finally {\r\n isLoadingRef.current = false;\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (abortControllerRef.current) {\r\n abortControllerRef.current.abort();\r\n }\r\n };\r\n }, [loadData]);\r\n\r\n const handleResolve = useCallback(async (resolution: ResolveConflictRequest['resolution'], notes?: string) => {\r\n if (!selectedConflict || resolving) return;\r\n\r\n setResolving(true);\r\n try {\r\n await entraApi.conflicts.resolve(selectedConflict.id, {\r\n resolution,\r\n notes: notes || undefined,\r\n });\r\n setSelectedConflict(null);\r\n await loadData();\r\n } catch (err) {\r\n // Log error type only, not the full error object (PII protection)\r\n console.error('Failed to resolve conflict:', err instanceof Error ? err.message : 'Unknown error');\r\n setError(t('entra:conflicts.resolveError'));\r\n } finally {\r\n setResolving(false);\r\n }\r\n }, [selectedConflict, resolving, loadData, t]);\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 return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.conflicts', 'Conflicts') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <AlertTriangle className=\"w-6 h-6 text-[var(--color-accent-600)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:conflicts.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:conflicts.subtitle', { count: conflicts.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <button\r\n onClick={loadData}\r\n disabled={loading}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors disabled:opacity-50\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\r\n {t('common:refresh')}\r\n </button>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n </div>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"text-[var(--error-text)] hover:opacity-70\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* No Conflicts - Empty State */}\r\n {conflicts.length === 0 ? (\r\n <div className=\"text-center py-16 px-6 rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)]\">\r\n <div className=\"mx-auto w-16 h-16 rounded-full bg-[var(--success-bg)] flex items-center justify-center mb-4\">\r\n <CheckCircle className=\"w-8 h-8 text-[var(--success-text)]\" />\r\n </div>\r\n <h2 className=\"text-xl font-semibold text-[var(--text-primary)] mb-2\">\r\n {t('entra:conflicts.noConflicts')}\r\n </h2>\r\n <p className=\"text-[var(--text-secondary)] max-w-md mx-auto\">\r\n {t('entra:conflicts.noConflictsDescription')}\r\n </p>\r\n </div>\r\n ) : (\r\n /* Conflicts Grid */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {conflicts.map((conflict) => (\r\n <ConflictCard\r\n key={conflict.id}\r\n conflict={conflict}\r\n onResolve={setSelectedConflict}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Resolve Modal */}\r\n {selectedConflict && (\r\n <ResolutionModal\r\n conflict={selectedConflict}\r\n onClose={() => setSelectedConflict(null)}\r\n onResolve={handleResolve}\r\n resolving={resolving}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, type ReactNode } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport {\r\n Settings,\r\n Key,\r\n Eye,\r\n EyeOff,\r\n Save,\r\n AlertTriangle,\r\n CheckCircle,\r\n ExternalLink,\r\n Shield,\r\n Clock,\r\n Loader2,\r\n TestTube,\r\n Users,\r\n Layers,\r\n Building2,\r\n Copy,\r\n Check,\r\n GitMerge,\r\n Filter,\r\n} from 'lucide-react';\r\nimport { entraApi } from '@/services/api/entraApi';\r\nimport type { TestConnectionResult, EntraConfigurationDto } from '@/services/api/entraApi';\r\n\r\ninterface EntraCredentials {\r\n tenantId: string;\r\n clientId: string;\r\n clientSecret: string;\r\n}\r\n\r\ninterface SyncSettings {\r\n syncEnabled: boolean;\r\n syncIntervalMinutes: number;\r\n useDeltaSync: boolean;\r\n defaultConflictResolution: 'ManualReview' | 'EntraWins' | 'LocalWins';\r\n autoCreateReferences: boolean;\r\n // User sync filters\r\n syncOnlyActiveUsers: boolean;\r\n syncUserTypes: string; // comma-separated: member, guest, shared, room, equipment\r\n}\r\n\r\n// Available user types for sync\r\n// Note: shared, room, equipment require mailboxSettings which is not available in bulk user listing API\r\nconst USER_TYPES = [\r\n { id: 'member', labelKey: 'userTypes.member', descriptionKey: 'userTypes.memberDescription', supported: true },\r\n { id: 'guest', labelKey: 'userTypes.guest', descriptionKey: 'userTypes.guestDescription', supported: true },\r\n { id: 'shared', labelKey: 'userTypes.shared', descriptionKey: 'userTypes.sharedDescription', supported: false },\r\n { id: 'room', labelKey: 'userTypes.room', descriptionKey: 'userTypes.roomDescription', supported: false },\r\n { id: 'equipment', labelKey: 'userTypes.equipment', descriptionKey: 'userTypes.equipmentDescription', supported: false },\r\n];\r\n\r\n// Required permissions for Microsoft Graph API\r\nconst REQUIRED_PERMISSIONS = [\r\n { code: 'User.Read.All', descriptionKey: 'userReadAll' },\r\n { code: 'Group.Read.All', descriptionKey: 'groupReadAll' },\r\n { code: 'GroupMember.Read.All', descriptionKey: 'groupMemberReadAll' },\r\n];\r\n\r\n// ============================================\r\n// Reusable Components\r\n// ============================================\r\n\r\ninterface SectionCardProps {\r\n readonly icon: LucideIcon;\r\n readonly title: string;\r\n readonly description?: string;\r\n readonly action?: ReactNode;\r\n readonly children: ReactNode;\r\n readonly className?: string;\r\n}\r\n\r\nfunction SectionCard({ icon: Icon, title, description, action, children, className = '' }: SectionCardProps) {\r\n return (\r\n <div className={`rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] shadow-sm overflow-hidden ${className}`}>\r\n {/* Header */}\r\n <div className=\"px-6 py-4 border-b border-[var(--border-subtle)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30\">\r\n <Icon className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h2 className=\"text-base font-semibold text-[var(--text-primary)]\">{title}</h2>\r\n {description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">{description}</p>\r\n )}\r\n </div>\r\n </div>\r\n {action}\r\n </div>\r\n </div>\r\n {/* Content */}\r\n <div className=\"p-6\">\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\ninterface ToggleProps {\r\n readonly checked: boolean;\r\n readonly onChange: () => void;\r\n readonly label: string;\r\n readonly description?: string;\r\n}\r\n\r\nfunction Toggle({ checked, onChange, label, description }: ToggleProps) {\r\n return (\r\n <div className=\"flex items-center justify-between py-3\">\r\n <div className=\"flex-1 min-w-0 pr-4\">\r\n <label className=\"text-sm font-medium text-[var(--text-primary)]\">{label}</label>\r\n {description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">{description}</p>\r\n )}\r\n </div>\r\n <button\r\n type=\"button\"\r\n role=\"switch\"\r\n aria-checked={checked}\r\n onClick={onChange}\r\n className={`relative inline-flex h-6 w-11 flex-shrink-0 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:ring-offset-2 focus:ring-offset-[var(--bg-primary)] ${\r\n checked ? 'bg-[var(--color-accent-600)]' : 'bg-[var(--bg-tertiary)]'\r\n }`}\r\n >\r\n <span\r\n className={`inline-block h-4 w-4 transform rounded-full bg-[var(--toggle-knob)] shadow-md transition-transform ${\r\n checked ? 'translate-x-6' : 'translate-x-1'\r\n }`}\r\n />\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\n// ============================================\r\n// Validation\r\n// ============================================\r\n\r\nconst isValidGuid = (value: string): boolean => {\r\n if (!value) return true;\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 useEntraSettings = () => {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [testing, setTesting] = useState(false);\r\n const [testResult, setTestResult] = useState<TestConnectionResult | null>(null);\r\n const [showSecret, setShowSecret] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n const [hasExistingSecret, setHasExistingSecret] = useState(false);\r\n const [copiedPermission, setCopiedPermission] = useState<string | null>(null);\r\n const [validationErrors, setValidationErrors] = useState<{\r\n tenantId?: string;\r\n clientId?: string;\r\n }>({});\r\n\r\n const [credentials, setCredentials] = useState<EntraCredentials>({\r\n tenantId: '',\r\n clientId: '',\r\n clientSecret: '',\r\n });\r\n\r\n const [syncSettings, setSyncSettings] = useState<SyncSettings>({\r\n syncEnabled: false,\r\n syncIntervalMinutes: 60,\r\n useDeltaSync: true,\r\n defaultConflictResolution: 'ManualReview',\r\n autoCreateReferences: true,\r\n syncOnlyActiveUsers: true,\r\n syncUserTypes: 'member',\r\n });\r\n\r\n return {\r\n t, loading, setLoading, saving, setSaving, testing, setTesting,\r\n testResult, setTestResult, showSecret, setShowSecret, error, setError,\r\n success, setSuccess, hasExistingSecret, setHasExistingSecret,\r\n copiedPermission, setCopiedPermission, validationErrors, setValidationErrors,\r\n credentials, setCredentials, syncSettings, setSyncSettings\r\n };\r\n};\r\n\r\n// ============================================\r\n// Helpers\r\n// ============================================\r\n\r\nfunction getCheckboxCardClass(isDisabled: boolean, isChecked: boolean): string {\r\n if (isDisabled) return 'opacity-50 cursor-not-allowed border-[var(--border-color)] bg-[var(--bg-tertiary)]';\r\n if (isChecked) return 'cursor-pointer border-[var(--color-accent-500)] bg-[var(--color-accent-50)] dark:bg-[var(--color-accent-900)]/20';\r\n return 'cursor-pointer border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-tertiary)]';\r\n}\r\n\r\n// ============================================\r\n// Main Component\r\n// ============================================\r\n\r\nexport function EntraSettingsPage(): ReactElement {\r\n const state = useEntraSettings();\r\n\r\n const loadConfiguration = useCallback(async () => {\r\n try {\r\n state.setLoading(true);\r\n const config: EntraConfigurationDto = await entraApi.settings.getConfiguration();\r\n\r\n state.setCredentials({\r\n tenantId: config.tenantId || '',\r\n clientId: config.clientId || '',\r\n clientSecret: '',\r\n });\r\n state.setHasExistingSecret(config.hasClientSecret);\r\n\r\n state.setSyncSettings({\r\n syncEnabled: config.syncEnabled,\r\n syncIntervalMinutes: config.syncIntervalMinutes,\r\n useDeltaSync: config.useDeltaSync,\r\n defaultConflictResolution: config.defaultConflictResolution as SyncSettings['defaultConflictResolution'],\r\n autoCreateReferences: config.autoCreateReferences,\r\n syncOnlyActiveUsers: config.syncOnlyActiveUsers ?? true,\r\n syncUserTypes: config.syncUserTypes ?? 'member',\r\n });\r\n } catch (err) {\r\n console.error('Failed to load configuration:', err);\r\n state.setError(state.t('entra:settings.saveError'));\r\n } finally {\r\n state.setLoading(false);\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []); // React setters are stable, no need to include them in dependencies\r\n\r\n useEffect(() => {\r\n loadConfiguration();\r\n }, [loadConfiguration]);\r\n\r\n const handleCopyPermission = async (code: string) => {\r\n try {\r\n await navigator.clipboard.writeText(code);\r\n state.setCopiedPermission(code);\r\n setTimeout(() => state.setCopiedPermission(null), 2000);\r\n } catch (err) {\r\n console.error('Failed to copy:', err);\r\n }\r\n };\r\n\r\n const validateCredentialField = (field: 'tenantId' | 'clientId', value: string) => {\r\n const errorKey = isValidGuid(value) ? undefined : state.t('entra:settings.invalidGuidFormat');\r\n state.setValidationErrors(prev => ({ ...prev, [field]: errorKey }));\r\n };\r\n\r\n const handleCredentialChange = (field: keyof EntraCredentials, value: string) => {\r\n state.setCredentials(prev => ({ ...prev, [field]: value }));\r\n if (field === 'tenantId' || field === 'clientId') {\r\n validateCredentialField(field, value);\r\n }\r\n };\r\n\r\n const hasValidationErrors = Boolean(\r\n state.validationErrors.tenantId || state.validationErrors.clientId\r\n );\r\n\r\n const handleTestConnection = async () => {\r\n state.setTesting(true);\r\n state.setTestResult(null);\r\n state.setError(null);\r\n state.setSuccess(null);\r\n try {\r\n let result: TestConnectionResult;\r\n\r\n if (state.credentials.clientSecret) {\r\n result = await entraApi.settings.testConnection({\r\n tenantId: state.credentials.tenantId,\r\n clientId: state.credentials.clientId,\r\n clientSecret: state.credentials.clientSecret,\r\n });\r\n } else if (state.hasExistingSecret) {\r\n result = await entraApi.settings.testStoredConnection();\r\n } else {\r\n state.setError(state.t('entra:settings.testFailed'));\r\n state.setTesting(false);\r\n return;\r\n }\r\n\r\n state.setTestResult(result);\r\n if (result.success) {\r\n state.setSuccess(state.t('entra:settings.testSuccess'));\r\n } else {\r\n state.setError(result.errorMessage || state.t('entra:settings.testFailed'));\r\n }\r\n } catch (err) {\r\n console.error('Connection test failed:', err);\r\n state.setTestResult({ success: false, errorMessage: state.t('entra:settings.testFailed'), tenantName: null, userCount: null, groupCount: null });\r\n state.setError(state.t('entra:settings.testFailed'));\r\n } finally {\r\n state.setTesting(false);\r\n }\r\n };\r\n\r\n const handleSaveCredentials = async () => {\r\n state.setSaving(true);\r\n state.setError(null);\r\n state.setSuccess(null);\r\n try {\r\n await entraApi.settings.saveCredentials({\r\n tenantId: state.credentials.tenantId,\r\n clientId: state.credentials.clientId,\r\n clientSecret: state.credentials.clientSecret,\r\n });\r\n state.setSuccess(state.t('entra:settings.credentialsSaved'));\r\n state.setHasExistingSecret(true);\r\n state.setCredentials((prev) => ({ ...prev, clientSecret: '' }));\r\n } catch (err) {\r\n console.error('Failed to save credentials:', err);\r\n state.setError(state.t('entra:settings.saveError'));\r\n } finally {\r\n state.setSaving(false);\r\n }\r\n };\r\n\r\n const handleSaveSettings = async () => {\r\n state.setSaving(true);\r\n state.setError(null);\r\n state.setSuccess(null);\r\n try {\r\n await entraApi.settings.saveSyncSettings({\r\n syncEnabled: state.syncSettings.syncEnabled,\r\n syncIntervalMinutes: state.syncSettings.syncIntervalMinutes,\r\n useDeltaSync: state.syncSettings.useDeltaSync,\r\n defaultConflictResolution: state.syncSettings.defaultConflictResolution,\r\n autoCreateReferences: state.syncSettings.autoCreateReferences,\r\n syncOnlyActiveUsers: state.syncSettings.syncOnlyActiveUsers,\r\n syncUserTypes: state.syncSettings.syncUserTypes,\r\n });\r\n state.setSuccess(state.t('entra:settings.settingsSaved'));\r\n } catch (err) {\r\n console.error('Failed to save settings:', err);\r\n state.setError(state.t('entra:settings.saveError'));\r\n } finally {\r\n state.setSaving(false);\r\n }\r\n };\r\n\r\n if (state.loading) {\r\n return (\r\n <div className=\"flex items-center justify-center h-64\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: state.t('header.title'), href: '/administration' },\r\n { label: state.t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: state.t('entra.settings', 'Settings') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"p-3 rounded-[var(--radius-card)] bg-gradient-to-br from-[var(--color-accent-500)] to-[var(--color-accent-700)] shadow-lg\">\r\n <Settings className=\"w-7 h-7 text-white\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {state.t('entra:settings.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {state.t('entra:settings.subtitle')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Required Permissions Warning */}\r\n <div className=\"rounded-[var(--radius-card)] border-2 border-[var(--warning-border)] bg-[var(--warning-bg)] overflow-hidden\">\r\n <div className=\"px-5 py-4\">\r\n <div className=\"flex items-start gap-4\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--warning-border)]\">\r\n <Shield className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center justify-between gap-4 mb-2\">\r\n <h2 className=\"font-semibold text-[var(--warning-text)]\">\r\n {state.t('entra:settings.permissionsWarningTitle')}\r\n </h2>\r\n <a\r\n href=\"https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--warning-border)] text-[var(--warning-text)] hover:opacity-80 transition-opacity\"\r\n >\r\n {state.t('entra:settings.configureInAzure')}\r\n <ExternalLink className=\"w-3.5 h-3.5\" />\r\n </a>\r\n </div>\r\n <p className=\"text-sm text-[var(--warning-text)] opacity-90 mb-4\">\r\n {state.t('entra:settings.permissionsWarningDescription')}\r\n </p>\r\n\r\n {/* Copyable Permissions */}\r\n <div className=\"flex flex-wrap gap-2\">\r\n {REQUIRED_PERMISSIONS.map((perm) => (\r\n <button\r\n key={perm.code}\r\n onClick={() => handleCopyPermission(perm.code)}\r\n className=\"group inline-flex items-center gap-2 px-3 py-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)] border border-[var(--warning-border)] hover:border-[var(--warning-dot)] transition-all hover:shadow-sm\"\r\n title={state.t(`entra:settings.permissions.${perm.descriptionKey}`)}\r\n >\r\n <code className=\"text-sm font-mono font-medium text-[var(--text-primary)]\">{perm.code}</code>\r\n {state.copiedPermission === perm.code ? (\r\n <Check className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n ) : (\r\n <Copy className=\"w-4 h-4 text-[var(--warning-text)] group-hover:opacity-80\" />\r\n )}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Error/Success Messages */}\r\n {state.error && (\r\n <div className=\"flex items-center gap-3 p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <AlertTriangle className=\"w-5 h-5 text-[var(--error-text)] flex-shrink-0\" />\r\n <span className=\"text-sm text-[var(--error-text)]\">{state.error}</span>\r\n </div>\r\n )}\r\n\r\n {state.success && (\r\n <div className=\"flex items-center gap-3 p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)]\">\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)] flex-shrink-0\" />\r\n <span className=\"text-sm text-[var(--success-text)]\">{state.success}</span>\r\n </div>\r\n )}\r\n\r\n {/* Main Content Grid */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* ============================================ */}\r\n {/* Left Column - Credentials */}\r\n {/* ============================================ */}\r\n <SectionCard\r\n icon={Key}\r\n title={state.t('entra:settings.credentials')}\r\n description=\"Azure AD Application\"\r\n action={\r\n <a\r\n href=\"https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"inline-flex items-center gap-1.5 text-sm text-[var(--color-accent-500)] hover:text-[var(--color-accent-600)] transition-colors\"\r\n >\r\n {state.t('entra:settings.azurePortal')}\r\n <ExternalLink className=\"w-4 h-4\" />\r\n </a>\r\n }\r\n >\r\n <div className=\"space-y-5\">\r\n {/* Tenant ID */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1.5\">\r\n {state.t('entra:settings.tenantId')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={state.credentials.tenantId}\r\n onChange={(e) => handleCredentialChange('tenantId', e.target.value)}\r\n placeholder=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\r\n autoComplete=\"off\"\r\n className={`w-full px-3 py-2.5 rounded-[var(--radius-input)] border bg-[var(--bg-secondary)] text-[var(--text-primary)] font-mono text-sm focus:outline-none focus:ring-2 focus:border-transparent transition-shadow ${\r\n state.validationErrors.tenantId\r\n ? 'border-[var(--error-border)] focus:ring-[var(--error-border)]'\r\n : 'border-[var(--border-color)] focus:ring-[var(--color-accent-500)]'\r\n }`}\r\n />\r\n {state.validationErrors.tenantId ? (\r\n <p className=\"mt-1.5 text-xs text-[var(--error-text)]\">{state.validationErrors.tenantId}</p>\r\n ) : (\r\n <p className=\"mt-1.5 text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.tenantIdHelp')}</p>\r\n )}\r\n </div>\r\n\r\n {/* Client ID */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1.5\">\r\n {state.t('entra:settings.clientId')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={state.credentials.clientId}\r\n onChange={(e) => handleCredentialChange('clientId', e.target.value)}\r\n placeholder=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\r\n autoComplete=\"off\"\r\n className={`w-full px-3 py-2.5 rounded-[var(--radius-input)] border bg-[var(--bg-secondary)] text-[var(--text-primary)] font-mono text-sm focus:outline-none focus:ring-2 focus:border-transparent transition-shadow ${\r\n state.validationErrors.clientId\r\n ? 'border-[var(--error-border)] focus:ring-[var(--error-border)]'\r\n : 'border-[var(--border-color)] focus:ring-[var(--color-accent-500)]'\r\n }`}\r\n />\r\n {state.validationErrors.clientId ? (\r\n <p className=\"mt-1.5 text-xs text-[var(--error-text)]\">{state.validationErrors.clientId}</p>\r\n ) : (\r\n <p className=\"mt-1.5 text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.clientIdHelp')}</p>\r\n )}\r\n </div>\r\n\r\n {/* Client Secret */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1.5\">\r\n {state.t('entra:settings.clientSecret')}\r\n {state.hasExistingSecret && (\r\n <span className=\"ml-2 inline-flex items-center gap-1 text-xs text-[var(--success-text)]\">\r\n <CheckCircle className=\"w-3 h-3\" />\r\n {state.t('common:configured')}\r\n </span>\r\n )}\r\n </label>\r\n <div className=\"relative\">\r\n <input\r\n type={state.showSecret ? 'text' : 'password'}\r\n value={state.credentials.clientSecret}\r\n onChange={(e) => handleCredentialChange('clientSecret', e.target.value)}\r\n placeholder={state.hasExistingSecret ? '••••••••••••••••••••••••••••••••••••••••' : 'OvA8Q~xxxxxxxxxxxxxxxxxxxxxxxxxxxx'}\r\n autoComplete=\"new-password\"\r\n className=\"w-full px-3 py-2.5 pr-10 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] font-mono text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-shadow\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => state.setShowSecret(!state.showSecret)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 text-[var(--text-tertiary)] hover:text-[var(--text-primary)] transition-colors\"\r\n >\r\n {state.showSecret ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </button>\r\n </div>\r\n <p className=\"mt-1.5 text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.clientSecretHelp')}</p>\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center gap-3 pt-2\">\r\n <button\r\n onClick={handleTestConnection}\r\n disabled={state.testing || hasValidationErrors || !state.credentials.tenantId || !state.credentials.clientId || (!state.credentials.clientSecret && !state.hasExistingSecret)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {state.testing && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {!state.testing && state.testResult?.success && <CheckCircle className=\"w-4 h-4 text-[var(--success-text)]\" />}\r\n {!state.testing && state.testResult && !state.testResult.success && <AlertTriangle className=\"w-4 h-4 text-[var(--error-text)]\" />}\r\n {!state.testing && !state.testResult && <TestTube className=\"w-4 h-4\" />}\r\n {state.t('entra:settings.testConnection')}\r\n </button>\r\n <button\r\n onClick={handleSaveCredentials}\r\n disabled={state.saving || hasValidationErrors || !state.credentials.tenantId || !state.credentials.clientId || !state.credentials.clientSecret}\r\n className=\"inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium 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 shadow-sm\"\r\n >\r\n {state.saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {state.t('common:save')}\r\n </button>\r\n </div>\r\n\r\n {/* Test Result Details */}\r\n {state.testResult?.success && (\r\n <div className=\"mt-4 p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)]\">\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n <span className=\"font-medium text-[var(--success-text)]\">\r\n {state.t('entra:settings.connectionSuccessful')}\r\n </span>\r\n </div>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-3\">\r\n {state.testResult.tenantName && (\r\n <div className=\"flex items-center gap-2 p-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)]\">\r\n <Building2 className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n <div className=\"min-w-0\">\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.tenantName')}</p>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">{state.testResult.tenantName}</p>\r\n </div>\r\n </div>\r\n )}\r\n {state.testResult.userCount !== null && (\r\n <div className=\"flex items-center gap-2 p-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)]\">\r\n <Users className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n <div>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.userCount')}</p>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">{state.testResult.userCount}</p>\r\n </div>\r\n </div>\r\n )}\r\n {state.testResult.groupCount !== null && (\r\n <div className=\"flex items-center gap-2 p-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)]\">\r\n <Layers className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n <div>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.groupCount')}</p>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">{state.testResult.groupCount}</p>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </SectionCard>\r\n\r\n {/* ============================================ */}\r\n {/* Right Column - Sync Settings Stack */}\r\n {/* ============================================ */}\r\n <div className=\"space-y-6\">\r\n {/* Sync Configuration */}\r\n <SectionCard\r\n icon={Clock}\r\n title={state.t('entra:settings.syncSettings')}\r\n description=\"Scheduling & Performance\"\r\n >\r\n <div className=\"divide-y divide-[var(--border-subtle)]\">\r\n <Toggle\r\n checked={state.syncSettings.syncEnabled}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, syncEnabled: !prev.syncEnabled }))}\r\n label={state.t('entra:settings.syncEnabled')}\r\n description={state.t('entra:settings.syncEnabledHelp')}\r\n />\r\n\r\n <div className=\"py-4\">\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {state.t('entra:settings.syncInterval')}\r\n </label>\r\n <select\r\n value={state.syncSettings.syncIntervalMinutes}\r\n onChange={(e) => state.setSyncSettings((prev) => ({ ...prev, syncIntervalMinutes: Number(e.target.value) }))}\r\n className=\"w-full px-3 py-2.5 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] transition-shadow\"\r\n >\r\n <option value={15}>15 {state.t('common:minutes')}</option>\r\n <option value={30}>30 {state.t('common:minutes')}</option>\r\n <option value={60}>1 {state.t('common:hour')}</option>\r\n <option value={120}>2 {state.t('common:hours')}</option>\r\n <option value={360}>6 {state.t('common:hours')}</option>\r\n <option value={720}>12 {state.t('common:hours')}</option>\r\n <option value={1440}>24 {state.t('common:hours')}</option>\r\n </select>\r\n </div>\r\n\r\n <Toggle\r\n checked={state.syncSettings.useDeltaSync}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, useDeltaSync: !prev.useDeltaSync }))}\r\n label={state.t('entra:settings.useDeltaSync')}\r\n description={state.t('entra:settings.useDeltaSyncHelp')}\r\n />\r\n\r\n <Toggle\r\n checked={state.syncSettings.autoCreateReferences}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, autoCreateReferences: !prev.autoCreateReferences }))}\r\n label={state.t('entra:settings.autoCreateReferences')}\r\n description={state.t('entra:settings.autoCreateReferencesHelp')}\r\n />\r\n </div>\r\n </SectionCard>\r\n\r\n {/* Conflict Resolution */}\r\n <SectionCard\r\n icon={GitMerge}\r\n title={state.t('entra:settings.conflictResolution')}\r\n description=\"Data Priority\"\r\n >\r\n <div>\r\n <select\r\n value={state.syncSettings.defaultConflictResolution}\r\n onChange={(e) => state.setSyncSettings((prev) => ({ ...prev, defaultConflictResolution: e.target.value as SyncSettings['defaultConflictResolution'] }))}\r\n className=\"w-full px-3 py-2.5 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] transition-shadow\"\r\n >\r\n <option value=\"ManualReview\">{state.t('entra:settings.conflictResolutions.manualReview')}</option>\r\n <option value=\"EntraWins\">{state.t('entra:settings.conflictResolutions.entraWins')}</option>\r\n <option value=\"LocalWins\">{state.t('entra:settings.conflictResolutions.localWins')}</option>\r\n </select>\r\n <p className=\"mt-2 text-xs text-[var(--text-tertiary)]\">\r\n {state.t('entra:settings.conflictResolutionHelp')}\r\n </p>\r\n </div>\r\n </SectionCard>\r\n\r\n {/* User Filters */}\r\n <SectionCard\r\n icon={Filter}\r\n title={state.t('entra:settings.userSyncFilters')}\r\n description=\"User Types & Filters\"\r\n >\r\n <div className=\"space-y-4\">\r\n <Toggle\r\n checked={state.syncSettings.syncOnlyActiveUsers}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, syncOnlyActiveUsers: !prev.syncOnlyActiveUsers }))}\r\n label={state.t('entra:settings.syncOnlyActiveUsers')}\r\n description={state.t('entra:settings.syncOnlyActiveUsersHelp')}\r\n />\r\n\r\n <div className=\"pt-2 border-t border-[var(--border-subtle)]\">\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {state.t('entra:settings.syncUserTypesLabel')}\r\n </label>\r\n <p className=\"text-xs text-[var(--text-tertiary)] mb-3\">\r\n {state.t('entra:settings.syncUserTypesHelp')}\r\n </p>\r\n <div className=\"space-y-2\">\r\n {USER_TYPES.map((userType) => {\r\n const selectedTypes = state.syncSettings.syncUserTypes.split(',').map(t => t.trim()).filter(Boolean);\r\n const isChecked = selectedTypes.includes(userType.id);\r\n const isDisabled = !userType.supported;\r\n\r\n const handleToggle = () => {\r\n if (isDisabled) return;\r\n let newTypes: string[];\r\n if (isChecked) {\r\n newTypes = selectedTypes.filter(t => t !== userType.id);\r\n } else {\r\n newTypes = [...selectedTypes, userType.id];\r\n }\r\n if (newTypes.length === 0) newTypes = ['member'];\r\n state.setSyncSettings(prev => ({ ...prev, syncUserTypes: newTypes.join(',') }));\r\n };\r\n\r\n return (\r\n <label\r\n key={userType.id}\r\n className={`flex items-start gap-3 p-3 rounded-[var(--radius-button)] border transition-all ${\r\n getCheckboxCardClass(isDisabled, isChecked)\r\n }`}\r\n >\r\n <input\r\n type=\"checkbox\"\r\n checked={isChecked}\r\n onChange={handleToggle}\r\n disabled={isDisabled}\r\n className=\"mt-0.5 w-4 h-4 rounded border-[var(--border-color)] text-[var(--color-accent-600)] focus:ring-[var(--color-accent-500)] disabled:opacity-50\"\r\n />\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {state.t(`entra:settings.${userType.labelKey}`)}\r\n </span>\r\n {isDisabled && (\r\n <span className=\"text-xs px-1.5 py-0.5 rounded bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n {state.t('common:comingSoon')}\r\n </span>\r\n )}\r\n </div>\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">\r\n {state.t(`entra:settings.${userType.descriptionKey}`)}\r\n </p>\r\n </div>\r\n </label>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n </SectionCard>\r\n\r\n {/* Save Button */}\r\n <div className=\"flex justify-end\">\r\n <button\r\n onClick={handleSaveSettings}\r\n disabled={state.saving}\r\n className=\"inline-flex items-center gap-2 px-6 py-2.5 text-sm font-medium 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 shadow-sm\"\r\n >\r\n {state.saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {state.t('common:save')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["SyncStatusCard","resourceType","Icon","status","lastFullSyncAt","lastDeltaSyncAt","totalItemsSynced","pendingConflicts","lastError","syncing","canSync","onSync","formatDate","t","statusConfig","CheckCircle","XCircle","Loader2","Clock","StatusIcon","jsxs","jsx","Database","Calendar","RefreshCw","AlertCircle","Tooltip","EntraDashboardPage","useTranslation","hasPermission","useAuth","loading","setLoading","useState","refreshing","setRefreshing","syncStatus","setSyncStatus","error","setError","setSyncing","lastSyncResult","setLastSyncResult","loadData","useCallback","entraApi","err","axiosError","useEffect","handleRefresh","handleSync","type","result","handleForceFullSync","date","getResourceIcon","Users","Building2","Link2","Cloud","totalPendingConflicts","sum","s","Breadcrumb","Play","AlertTriangle","getGroupHierarchyDisplay","group","GitBranch","EntraGroupsPage","currentTenant","isGlobalView","useTenant","navigate","useNavigate","groups","setGroups","roles","setRoles","searchQuery","setSearchQuery","selectedGroup","setSelectedGroup","showAssignModal","setShowAssignModal","expandedGroupId","setExpandedGroupId","members","setMembers","loadingMembers","setLoadingMembers","viewMode","setViewMode","groupTypeFilter","setGroupTypeFilter","assigning","setAssigning","canAssign","groupsData","rolesData","adminApi","loadMembers","groupId","data","prev","reloadGroupsAndRoles","safeGroupsData","handleAssignRole","roleId","isInheritable","updatedGroup","g","handleRemoveRole","filteredGroups","matchesSearch","matchesType","X","Search","e","Filter","LayoutGrid","List","Shield","role","Plus","ChevronUp","ChevronDown","Fragment","member","Link","r","EntraUsersPage","users","setUsers","response","columns","user","Mail","ExternalLink","searchFilter","searchTerm","search","DataTable","EntraConflictsPage","conflicts","setConflicts","selectedConflict","setSelectedConflict","resolving","setResolving","abortControllerRef","useRef","isLoadingRef","handleResolve","resolution","notes","conflict","ConflictCard","ResolutionModal","USER_TYPES","REQUIRED_PERMISSIONS","SectionCard","title","description","action","children","className","Toggle","checked","onChange","label","isValidGuid","value","useEntraSettings","saving","setSaving","testing","setTesting","testResult","setTestResult","showSecret","setShowSecret","success","setSuccess","hasExistingSecret","setHasExistingSecret","copiedPermission","setCopiedPermission","validationErrors","setValidationErrors","credentials","setCredentials","syncSettings","setSyncSettings","getCheckboxCardClass","isDisabled","isChecked","EntraSettingsPage","state","loadConfiguration","config","handleCopyPermission","code","validateCredentialField","field","errorKey","handleCredentialChange","hasValidationErrors","handleTestConnection","handleSaveCredentials","handleSaveSettings","Settings","perm","Check","Copy","Key","EyeOff","Eye","TestTube","Save","Layers","GitMerge","userType","selectedTypes","handleToggle","newTypes"],"mappings":"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"}
1
+ {"version":3,"file":"index-DzedSLdI.js","sources":["../../src/pages/platform/administration/entra/EntraDashboardPage.tsx","../../src/pages/platform/administration/entra/EntraGroupsPage.tsx","../../src/pages/platform/administration/entra/EntraUsersPage.tsx","../../src/pages/platform/administration/entra/EntraConflictsPage.tsx","../../src/pages/platform/administration/entra/EntraSettingsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { Tooltip } from '@/components/ui/Tooltip';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport {\r\n Cloud,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n CheckCircle,\r\n XCircle,\r\n Clock,\r\n Users,\r\n Building2,\r\n Link2,\r\n Play,\r\n AlertCircle,\r\n Calendar,\r\n Database,\r\n} from 'lucide-react';\r\nimport {\r\n entraApi,\r\n type EntraSyncStatusDto,\r\n type EntraSyncResultDto,\r\n} from '@/services/api/entraApi';\r\n\r\n// ============================================\r\n// Sync Status Card Component\r\n// ============================================\r\n\r\ninterface SyncStatusCardProps {\r\n readonly resourceType: string;\r\n readonly icon: LucideIcon;\r\n readonly status: string;\r\n readonly lastFullSyncAt: string | null;\r\n readonly lastDeltaSyncAt: string | null;\r\n readonly totalItemsSynced: number;\r\n readonly pendingConflicts: number;\r\n readonly lastError: string | null;\r\n readonly syncing: boolean;\r\n readonly canSync: boolean;\r\n readonly onSync: () => void;\r\n readonly formatDate: (date: string | null) => string;\r\n readonly t: (key: string, options?: Record<string, unknown>) => string;\r\n}\r\n\r\nfunction SyncStatusCard({\r\n resourceType,\r\n icon: Icon,\r\n status,\r\n lastFullSyncAt,\r\n lastDeltaSyncAt,\r\n totalItemsSynced,\r\n pendingConflicts,\r\n lastError,\r\n syncing,\r\n canSync,\r\n onSync,\r\n formatDate,\r\n t,\r\n}: SyncStatusCardProps) {\r\n const getStatusConfig = () => {\r\n switch (status) {\r\n case 'Success':\r\n return {\r\n icon: CheckCircle,\r\n color: 'text-[var(--success-text)]',\r\n bg: 'bg-[var(--success-bg)]',\r\n label: t('common:success'),\r\n };\r\n case 'Failed':\r\n return {\r\n icon: XCircle,\r\n color: 'text-[var(--error-text)]',\r\n bg: 'bg-[var(--error-bg)]',\r\n label: t('common:failed'),\r\n };\r\n case 'Running':\r\n return {\r\n icon: Loader2,\r\n color: 'text-[var(--color-accent-500)]',\r\n bg: 'bg-[var(--color-accent-100)]',\r\n label: t('common:running'),\r\n animate: true,\r\n };\r\n default:\r\n return {\r\n icon: Clock,\r\n color: 'text-[var(--text-tertiary)]',\r\n bg: 'bg-[var(--bg-tertiary)]',\r\n label: t('common:pending'),\r\n };\r\n }\r\n };\r\n\r\n const statusConfig = getStatusConfig();\r\n const StatusIcon = statusConfig.icon;\r\n\r\n return (\r\n <div className=\"h-full flex flex-col rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] overflow-hidden shadow-sm hover:shadow-md transition-shadow\">\r\n {/* Header with gradient */}\r\n <div className=\"px-4 py-3 bg-gradient-to-r from-[var(--color-accent-500)]/10 to-[var(--color-accent-600)]/5 border-b border-[var(--border-color)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-lg bg-[var(--color-accent-500)]/20\">\r\n <Icon className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n </div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">\r\n {t(`entra:resourceTypes.${resourceType.toLowerCase()}`)}\r\n </h3>\r\n </div>\r\n <div className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium ${statusConfig.bg} ${statusConfig.color}`}>\r\n <StatusIcon className={`w-3.5 h-3.5 ${statusConfig.animate ? 'animate-spin' : ''}`} />\r\n {statusConfig.label}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Grid */}\r\n <div className=\"flex-1 flex flex-col p-4\">\r\n <div className=\"grid grid-cols-3 gap-3 mb-4\">\r\n <div className=\"text-center p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-center gap-1 mb-1\">\r\n <Database className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <p className=\"text-xl font-bold text-[var(--text-primary)]\">{totalItemsSynced.toLocaleString()}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{t('entra:dashboard.itemsSynced')}</p>\r\n </div>\r\n <div className=\"text-center p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-center gap-1 mb-1\">\r\n <Calendar className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\" title={formatDate(lastFullSyncAt)}>\r\n {lastFullSyncAt ? new Date(lastFullSyncAt).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' }) : '-'}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{t('entra:dashboard.lastFullSync')}</p>\r\n </div>\r\n <div className=\"text-center p-3 rounded-lg bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-center gap-1 mb-1\">\r\n <RefreshCw className=\"w-3.5 h-3.5 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\" title={formatDate(lastDeltaSyncAt)}>\r\n {lastDeltaSyncAt ? new Date(lastDeltaSyncAt).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' }) : '-'}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{t('entra:dashboard.lastDeltaSync')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* Pending Conflicts Warning */}\r\n {pendingConflicts > 0 && (\r\n <div className=\"flex items-center gap-2 p-3 mb-4 rounded-lg bg-[var(--warning-bg)] border border-[var(--warning-border)]\">\r\n <AlertCircle className=\"w-4 h-4 text-[var(--warning-text)] flex-shrink-0\" />\r\n <span className=\"text-sm text-[var(--warning-text)] font-medium\">\r\n {pendingConflicts} {t('entra:dashboard.pendingConflicts')}\r\n </span>\r\n </div>\r\n )}\r\n\r\n {/* Last Error */}\r\n {lastError && (\r\n <div className=\"p-3 mb-4 rounded-lg bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <p className=\"text-xs text-[var(--error-text)] line-clamp-2\">{lastError}</p>\r\n </div>\r\n )}\r\n\r\n {/* Action Button - Always at bottom */}\r\n <Tooltip\r\n content={!canSync ? t('entra:dashboard.noSyncPermission') : undefined}\r\n position=\"top\"\r\n variant=\"error\"\r\n disabled={canSync}\r\n >\r\n <button\r\n onClick={onSync}\r\n disabled={syncing || !canSync}\r\n className=\"mt-auto w-full inline-flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium 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 shadow-sm\"\r\n >\r\n {syncing ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <RefreshCw className=\"w-4 h-4\" />\r\n )}\r\n {t('entra:dashboard.syncNow')}\r\n </button>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport function EntraDashboardPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const { hasPermission } = useAuth();\r\n const [loading, setLoading] = useState(true);\r\n const [refreshing, setRefreshing] = useState(false);\r\n const [syncStatus, setSyncStatus] = useState<EntraSyncStatusDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [syncing, setSyncing] = useState<string | null>(null);\r\n const [lastSyncResult, setLastSyncResult] = useState<EntraSyncResultDto | null>(null);\r\n\r\n // Permission check for sync operations\r\n const canSync = hasPermission('administration.entra.execute');\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setError(null);\r\n const status = await entraApi.dashboard.getSyncStatus();\r\n setSyncStatus(Array.isArray(status) ? status : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load Entra dashboard data:', err);\r\n setSyncStatus([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('entra:dashboard.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n setRefreshing(false);\r\n }\r\n }, [t]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleRefresh = () => {\r\n setRefreshing(true);\r\n loadData();\r\n };\r\n\r\n const handleSync = async (type: 'all' | 'users' | 'groups' | 'memberships') => {\r\n setSyncing(type);\r\n setLastSyncResult(null);\r\n try {\r\n let result: EntraSyncResultDto;\r\n switch (type) {\r\n case 'users':\r\n result = await entraApi.sync.syncUsers();\r\n break;\r\n case 'groups':\r\n result = await entraApi.sync.syncGroups();\r\n break;\r\n case 'memberships':\r\n result = await entraApi.sync.syncMemberships();\r\n break;\r\n default:\r\n result = await entraApi.sync.syncAll();\r\n }\r\n setLastSyncResult(result);\r\n await loadData();\r\n } catch (err: unknown) {\r\n console.error('Sync failed:', err);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 403) {\r\n setError(t('entra:dashboard.syncPermissionDenied'));\r\n } else if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else {\r\n setError(t('entra:dashboard.syncError'));\r\n }\r\n } finally {\r\n setSyncing(null);\r\n }\r\n };\r\n\r\n const handleForceFullSync = async () => {\r\n if (!confirm(t('entra:dashboard.forceFullSyncConfirm'))) return;\r\n setSyncing('force');\r\n try {\r\n await entraApi.sync.forceFullSync();\r\n await loadData();\r\n } catch (err: unknown) {\r\n console.error('Force full sync failed:', err);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 403) {\r\n setError(t('entra:dashboard.syncPermissionDenied'));\r\n } else if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else {\r\n setError(t('entra:dashboard.syncError'));\r\n }\r\n } finally {\r\n setSyncing(null);\r\n }\r\n };\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return t('common:never');\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\r\n };\r\n\r\n const getResourceIcon = (resourceType: string): LucideIcon => {\r\n switch (resourceType) {\r\n case 'Users':\r\n return Users;\r\n case 'Groups':\r\n return Building2;\r\n case 'Memberships':\r\n return Link2;\r\n default:\r\n return Cloud;\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 const totalPendingConflicts = syncStatus.reduce((sum, s) => sum + s.pendingConflicts, 0);\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.dashboard', 'Dashboard') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <Cloud className=\"w-6 h-6 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:dashboard.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:dashboard.subtitle')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={handleRefresh}\r\n disabled={refreshing}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] disabled:opacity-50 transition-colors\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${refreshing ? 'animate-spin' : ''}`} />\r\n {t('common:refresh')}\r\n </button>\r\n <Tooltip\r\n content={!canSync ? t('entra:dashboard.noSyncPermission') : undefined}\r\n position=\"bottom\"\r\n variant=\"error\"\r\n disabled={canSync}\r\n >\r\n <button\r\n onClick={() => handleSync('all')}\r\n disabled={syncing !== null || !canSync}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium 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 {syncing === 'all' ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Play className=\"w-4 h-4\" />\r\n )}\r\n {t('entra:dashboard.syncAll')}\r\n </button>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Pending Conflicts Warning */}\r\n {totalPendingConflicts > 0 && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--warning-bg)] border border-[var(--warning-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--warning-text)]\">\r\n <AlertCircle className=\"w-5 h-5\" />\r\n <span>\r\n {t('entra:dashboard.conflictsWarning', { count: totalPendingConflicts })}\r\n </span>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Last Sync Result */}\r\n {lastSyncResult && (\r\n <div className={`p-4 rounded-[var(--radius-card)] border ${\r\n lastSyncResult.success\r\n ? 'bg-[var(--success-bg)] border-[var(--success-border)]'\r\n : 'bg-[var(--error-bg)] border-[var(--error-border)]'\r\n }`}>\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n {lastSyncResult.success ? (\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n ) : (\r\n <XCircle className=\"w-5 h-5 text-[var(--error-text)]\" />\r\n )}\r\n <span className={lastSyncResult.success ? 'text-[var(--success-text)]' : 'text-[var(--error-text)]'}>\r\n {lastSyncResult.success\r\n ? t('entra:dashboard.syncSuccess')\r\n : t('entra:dashboard.syncFailed')}\r\n </span>\r\n </div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:dashboard.syncStats', {\r\n created: lastSyncResult.created,\r\n updated: lastSyncResult.updated,\r\n deleted: lastSyncResult.deleted,\r\n })}\r\n </div>\r\n </div>\r\n {lastSyncResult.errorMessage && (\r\n <p className=\"mt-2 text-sm text-[var(--error-text)]\">\r\n {lastSyncResult.errorMessage}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Sync Status Cards */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\r\n {syncStatus.map((status) => (\r\n <SyncStatusCard\r\n key={status.resourceType}\r\n resourceType={status.resourceType}\r\n icon={getResourceIcon(status.resourceType)}\r\n status={status.status}\r\n lastFullSyncAt={status.lastFullSyncAt}\r\n lastDeltaSyncAt={status.lastDeltaSyncAt}\r\n totalItemsSynced={status.totalItemsSynced}\r\n pendingConflicts={status.pendingConflicts}\r\n lastError={status.lastError}\r\n syncing={syncing === status.resourceType.toLowerCase()}\r\n canSync={canSync}\r\n onSync={() => handleSync(status.resourceType.toLowerCase() as 'users' | 'groups' | 'memberships')}\r\n formatDate={formatDate}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n\r\n {/* Force Full Sync */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)]\">\r\n {t('entra:dashboard.forceFullSync')}\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:dashboard.forceFullSyncDescription')}\r\n </p>\r\n </div>\r\n <Tooltip\r\n content={!canSync ? t('entra:dashboard.noSyncPermission') : undefined}\r\n position=\"left\"\r\n variant=\"error\"\r\n disabled={canSync}\r\n >\r\n <button\r\n onClick={handleForceFullSync}\r\n disabled={syncing !== null || !canSync}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--warning-border)] bg-[var(--warning-bg)] text-[var(--warning-text)] hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {syncing === 'force' ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <AlertTriangle className=\"w-4 h-4\" />\r\n )}\r\n {t('entra:dashboard.forceFullSync')}\r\n </button>\r\n </Tooltip>\r\n </div>\r\n </div>\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 { Link, useNavigate } from 'react-router-dom';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n Cloud,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n Search,\r\n Users,\r\n Shield,\r\n Plus,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n LayoutGrid,\r\n List,\r\n Filter,\r\n Building2,\r\n GitBranch,\r\n} from 'lucide-react';\r\nimport {\r\n entraApi,\r\n type EntraGroupDto,\r\n type EntraGroupMemberDto,\r\n} from '@/services/api/entraApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\n\r\ntype ViewMode = 'cards' | 'table';\r\ntype GroupTypeFilter = 'all' | 'security' | 'distribution';\r\n\r\ninterface GroupWithMembers extends EntraGroupDto {\r\n membersLoaded?: EntraGroupMemberDto[];\r\n}\r\n\r\nconst getGroupHierarchyDisplay = (group: EntraGroupDto) => {\r\n if (group.parentGroupName) {\r\n return (\r\n <span className=\"flex items-center gap-1 text-xs\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.parentGroupName}\r\n </span>\r\n );\r\n }\r\n if (group.childGroupCount > 0) {\r\n return (\r\n <span className=\"flex items-center gap-1 text-xs text-[var(--text-tertiary)]\">\r\n {group.childGroupCount} child groups\r\n </span>\r\n );\r\n }\r\n return <span className=\"text-xs text-[var(--text-tertiary)]\">-</span>;\r\n};\r\n\r\nexport function EntraGroupsPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'admin', 'common']);\r\n const { hasPermission } = useAuth();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const navigate = useNavigate();\r\n const [loading, setLoading] = useState(true);\r\n const [groups, setGroups] = useState<GroupWithMembers[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [selectedGroup, setSelectedGroup] = useState<GroupWithMembers | null>(null);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [expandedGroupId, setExpandedGroupId] = useState<string | null>(null);\r\n const [members, setMembers] = useState<Record<string, EntraGroupMemberDto[]>>({});\r\n const [loadingMembers, setLoadingMembers] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [groupTypeFilter, setGroupTypeFilter] = useState<GroupTypeFilter>('all');\r\n const [assigning, setAssigning] = useState(false);\r\n\r\n const canAssign = hasPermission('administration.entra.assign');\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setError(null);\r\n const [groupsData, rolesData] = await Promise.all([\r\n entraApi.groups.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n setGroups(Array.isArray(groupsData) ? groupsData : []);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load Entra groups:', err);\r\n setGroups([]);\r\n setRoles([]);\r\n const axiosError = err as { response?: { status?: number; data?: { code?: string } } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else if (axiosError.response?.data?.code === 'TENANT_REQUIRED') {\r\n setError(t('entra:groups.tenantRequired'));\r\n } else {\r\n setError(t('entra:groups.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await entraApi.groups.getMembers(groupId);\r\n setMembers(prev => ({ ...prev, [groupId]: data }));\r\n setExpandedGroupId(groupId);\r\n } catch (err) {\r\n console.error('Failed to load members:', err);\r\n setError(t('entra:groups.loadMembersError'));\r\n } finally {\r\n setLoadingMembers(null);\r\n }\r\n };\r\n\r\n const reloadGroupsAndRoles = useCallback(async () => {\r\n const [groupsData, rolesData] = await Promise.all([\r\n entraApi.groups.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n const safeGroupsData = Array.isArray(groupsData) ? groupsData : [];\r\n setGroups(safeGroupsData);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n return safeGroupsData;\r\n }, [currentTenant?.id]);\r\n\r\n const handleAssignRole = async (roleId: string, isInheritable: boolean = true) => {\r\n if (!selectedGroup) return;\r\n setAssigning(true);\r\n try {\r\n await entraApi.groups.assignRole(selectedGroup.id, { roleId, isInheritable });\r\n const safeGroupsData = await reloadGroupsAndRoles();\r\n const updatedGroup = safeGroupsData.find(g => g.id === selectedGroup.id);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('entra:groups.assignError'));\r\n } finally {\r\n setAssigning(false);\r\n }\r\n };\r\n\r\n const handleRemoveRole = async (groupId: string, roleId: string) => {\r\n if (!confirm(t('entra:groups.removeRoleConfirm'))) return;\r\n try {\r\n await entraApi.groups.removeRole(groupId, roleId);\r\n await reloadGroupsAndRoles();\r\n if (selectedGroup?.id === groupId) {\r\n const updatedGroups = await entraApi.groups.getAll();\r\n const updatedGroup = updatedGroups.find(g => g.id === groupId);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n }\r\n } catch (err) {\r\n console.error('Failed to remove role:', err);\r\n setError(t('entra:groups.removeError'));\r\n }\r\n };\r\n\r\n const filteredGroups = groups.filter((g) => {\r\n const matchesSearch =\r\n g.displayName.toLowerCase().includes(searchQuery.toLowerCase()) ||\r\n g.description?.toLowerCase().includes(searchQuery.toLowerCase());\r\n\r\n const matchesType =\r\n groupTypeFilter === 'all' ||\r\n (groupTypeFilter === 'security' && g.isSecurityGroup) ||\r\n (groupTypeFilter === 'distribution' && !g.isSecurityGroup);\r\n\r\n return matchesSearch && matchesType;\r\n });\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return '-';\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\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 return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.groups', 'Groups') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-blue-500/10\">\r\n <Cloud className=\"w-6 h-6 text-blue-500\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:groups.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:groups.subtitle', { count: groups.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Info banner */}\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-blue-500/10 border border-blue-500/20\">\r\n <div className=\"flex items-start gap-3\">\r\n <Cloud className=\"w-5 h-5 text-blue-500 flex-shrink-0 mt-0.5\" />\r\n <div>\r\n <p className=\"text-sm text-[var(--text-primary)]\">\r\n {t('entra:groups.syncedInfo')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-secondary)] mt-1\">\r\n {t('entra:groups.syncedInfoDescription')}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"ml-auto p-1 hover:bg-[var(--error-text)]/10 rounded\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filters */}\r\n <div className=\"flex flex-col sm:flex-row gap-4\">\r\n {/* Search */}\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('entra:groups.searchPlaceholder')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Type Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={groupTypeFilter}\r\n onChange={(e) => setGroupTypeFilter(e.target.value as GroupTypeFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allTypes')}</option>\r\n <option value=\"security\">{t('admin:groups.securityGroup')}</option>\r\n <option value=\"distribution\">{t('admin:groups.distributionGroup')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\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={`p-2 rounded-[var(--radius-button)] transition-colors ${\r\n viewMode === 'cards'\r\n ? 'bg-[var(--color-accent-500)] text-white'\r\n : 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n title={t('admin:groups.cardView')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${\r\n viewMode === 'table'\r\n ? 'bg-[var(--color-accent-500)] text-white'\r\n : 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n title={t('admin:groups.tableView')}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Groups List */}\r\n {filteredGroups.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {searchQuery || groupTypeFilter !== 'all'\r\n ? t('admin:groups.noResults')\r\n : t('entra:groups.noGroups')}\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\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-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.groupName')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:type')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.members')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('entra:groups.hierarchy')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.assignedRoles')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('entra:groups.lastSynced')}\r\n </th>\r\n {canAssign && !isGlobalView && (\r\n <th className=\"px-4 py-3 text-right text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:actionsColumn')}\r\n </th>\r\n )}\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {filteredGroups.map((group) => (\r\n <tr\r\n key={group.id}\r\n className=\"hover:bg-[var(--bg-hover)] cursor-pointer\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-4 h-4\" />\r\n ) : (\r\n <Building2 className=\"w-4 h-4\" />\r\n )}\r\n </div>\r\n <div>\r\n <span className=\"font-medium text-[var(--text-primary)]\">{group.displayName}</span>\r\n {group.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate max-w-xs\">\r\n {group.description}\r\n </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-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n <span className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n {group.memberCount}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {getGroupHierarchyDisplay(group)}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {group.assignedRoles.slice(0, 2).map((role) => (\r\n <span\r\n key={role.roleId}\r\n className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\"\r\n >\r\n {role.roleName}\r\n </span>\r\n ))}\r\n {group.assignedRoles.length > 2 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n +{group.assignedRoles.length - 2}\r\n </span>\r\n )}\r\n {group.inheritedRoles.length > 0 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-green-500/10 text-green-600\" title={t('entra:groups.inheritedRoles')}>\r\n +{group.inheritedRoles.length} {t('entra:groups.inherited')}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-xs text-[var(--text-tertiary)]\">\r\n {formatDate(group.lastSyncedAt)}\r\n </td>\r\n {canAssign && !isGlobalView && (\r\n <td className=\"px-4 py-3 text-right\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={() => {\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n title={t('admin:groups.assignRole')}\r\n >\r\n <Plus className=\"w-4 h-4\" />\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 {filteredGroups.length > 0 && viewMode !== 'table' && (\r\n /* Cards View */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {filteredGroups.map((group) => (\r\n <button\r\n type=\"button\"\r\n key={group.id}\r\n className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)] overflow-hidden cursor-pointer hover:border-[var(--color-accent-500)] transition-colors text-left\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n >\r\n {/* Card Header */}\r\n <div className=\"p-4\">\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2.5 rounded-[var(--radius-button)] flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-5 h-5\" />\r\n ) : (\r\n <Building2 className=\"w-5 h-5\" />\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <span className=\"font-semibold text-[var(--text-primary)] truncate\">\r\n {group.displayName}\r\n </span>\r\n <span className={`px-2 py-0.5 text-xs rounded-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500 border border-blue-500/20'\r\n : 'bg-purple-500/10 text-purple-500 border border-purple-500/20'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n {!group.isActive && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n {t('common:inactive')}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1 line-clamp-2\">\r\n {group.description}\r\n </p>\r\n )}\r\n <div className=\"flex items-center gap-4 mt-2 text-sm text-[var(--text-tertiary)] flex-wrap\">\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n loadMembers(group.id);\r\n }}\r\n className=\"flex items-center gap-1 hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.memberCount', { count: group.memberCount })}\r\n {loadingMembers === group.id && (\r\n <Loader2 className=\"w-3 h-3 animate-spin ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId === group.id && (\r\n <ChevronUp className=\"w-3 h-3 ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId !== group.id && (\r\n <ChevronDown className=\"w-3 h-3 ml-1\" />\r\n )}\r\n </button>\r\n {group.childGroupCount > 0 && (\r\n <span className=\"flex items-center gap-1 text-xs\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.childGroupCount} {t('entra:groups.childGroups')}\r\n </span>\r\n )}\r\n </div>\r\n {group.parentGroupName && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1 flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('entra:groups.parentGroup')}: {group.parentGroupName}\r\n </p>\r\n )}\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('entra:groups.lastSynced')}: {formatDate(group.lastSyncedAt)}\r\n </p>\r\n </div>\r\n </div>\r\n {canAssign && !isGlobalView && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors flex-shrink-0\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.assignRole')}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Assigned Roles */}\r\n {(group.assignedRoles.length > 0 || group.inheritedRoles.length > 0) && (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n {group.assignedRoles.length > 0 && (\r\n <>\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {t('admin:groups.assignedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2 mb-3\">\r\n {group.assignedRoles.map((role) => (\r\n <div\r\n key={role.roleId}\r\n className=\"inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-badge)] bg-[var(--bg-primary)] border border-[var(--border-color)] group\"\r\n >\r\n <Shield className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n <span className=\"text-sm text-[var(--text-primary)]\">{role.roleName}</span>\r\n {role.isInheritable && (\r\n <span className=\"text-xs text-green-600\" title={t('entra:groups.inheritableRole')}>\r\n ↓\r\n </span>\r\n )}\r\n {canAssign && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleRemoveRole(group.id, role.roleId);\r\n }}\r\n className=\"ml-1 p-0.5 rounded opacity-0 group-hover:opacity-100 hover:bg-[var(--error-bg)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] transition-all\"\r\n title={t('common:remove')}\r\n >\r\n <X className=\"w-3 h-3\" />\r\n </button>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n {group.inheritedRoles.length > 0 && (\r\n <>\r\n <h4 className=\"text-xs font-medium text-[var(--text-tertiary)] mb-2 flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('entra:groups.inheritedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {group.inheritedRoles.map((role) => (\r\n <div\r\n key={`${role.roleId}-${role.sourceGroupId}`}\r\n className=\"inline-flex items-center gap-2 px-2 py-1 rounded-[var(--radius-badge)] bg-green-500/5 border border-green-500/20\"\r\n title={`${t('entra:groups.inheritedFrom')} ${role.sourceGroupName}`}\r\n >\r\n <Shield className=\"w-3 h-3 text-green-600\" />\r\n <span className=\"text-xs text-green-700\">{role.roleName}</span>\r\n <span className=\"text-xs text-green-600/60\">← {role.sourceGroupName}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Members Panel */}\r\n {expandedGroupId === group.id && members[group.id] && (\r\n <div className=\"border-t border-[var(--border-color)] bg-[var(--bg-primary)]\" onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()} role=\"presentation\">\r\n <div className=\"p-4\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center gap-2\">\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.members')} ({members[group.id].length})\r\n </h4>\r\n {members[group.id].length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.noMembers')}\r\n </p>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-64 overflow-y-auto\">\r\n {members[group.id].slice(0, 10).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-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0).toUpperCase()}\r\n </div>\r\n <div className=\"min-w-0 flex-1\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">\r\n {member.email}\r\n </p>\r\n </div>\r\n {!member.isDirect && member.sourceGroupName && (\r\n <span className=\"text-xs text-[var(--text-tertiary)] flex items-center gap-1\" title={t('entra:groups.memberFromChildGroup')}>\r\n <GitBranch className=\"w-3 h-3\" />\r\n </span>\r\n )}\r\n </Link>\r\n ))}\r\n </div>\r\n )}\r\n {members[group.id].length > 10 && (\r\n <p className=\"mt-3 text-center text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.showingMembers', {\r\n shown: 10,\r\n total: members[group.id].length,\r\n })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {showAssignModal && selectedGroup && (\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-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.assignRoleTitle')}\r\n </h2>\r\n <button\r\n onClick={() => {\r\n setShowAssignModal(false);\r\n setSelectedGroup(null);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4\">\r\n <p className=\"text-sm text-[var(--text-secondary)] mb-4\">\r\n {t('admin:groups.assignRoleDescription', { group: selectedGroup.displayName })}\r\n </p>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {roles\r\n .filter((role) => !selectedGroup.assignedRoles.some(r => r.roleId === role.id))\r\n .map((role) => (\r\n <button\r\n key={role.id}\r\n onClick={() => handleAssignRole(role.id)}\r\n disabled={assigning}\r\n className=\"w-full flex items-center gap-3 p-3 rounded-[var(--radius-button)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors text-left disabled:opacity-50\"\r\n >\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n <div className=\"flex-1\">\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n {assigning && (\r\n <Loader2 className=\"w-4 h-4 animate-spin text-[var(--color-accent-500)]\" />\r\n )}\r\n </button>\r\n ))}\r\n {roles.filter((role) => !selectedGroup.assignedRoles.some(r => r.roleId === role.id)).length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('admin:groups.allRolesAssigned')}\r\n </p>\r\n )}\r\n </div>\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 { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n Users,\r\n RefreshCw,\r\n AlertTriangle,\r\n CheckCircle,\r\n XCircle,\r\n Mail,\r\n Calendar,\r\n ExternalLink,\r\n} from 'lucide-react';\r\nimport { adminApi, type UserListDto } from '@/services/api/adminApi';\r\nimport { DataTable, type DataTableColumn } from '@/components/ui/DataTable';\r\n\r\nexport function EntraUsersPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const navigate = useNavigate();\r\n const [loading, setLoading] = useState(true);\r\n const [users, setUsers] = useState<UserListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n // Only fetch users synced from Entra ID (have entraObjectId)\r\n const response = await adminApi.users.getAll({ pageSize: 1000, entraOnly: true });\r\n setUsers(response?.items ?? []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load users:', err);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('entra:users.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return t('common:never');\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\r\n };\r\n\r\n // Define columns for DataTable\r\n const columns: DataTableColumn<UserListDto>[] = [\r\n {\r\n key: 'fullName',\r\n label: t('entra:users.columns.user'),\r\n sortable: true,\r\n render: (user) => (\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-primary-100)] dark:bg-[var(--color-primary-900)] flex items-center justify-center flex-shrink-0\">\r\n <span className=\"text-sm font-medium text-[var(--color-primary-600)]\">\r\n {user.fullName?.charAt(0).toUpperCase() || '?'}\r\n </span>\r\n </div>\r\n <span className=\"font-medium text-[var(--text-primary)]\">{user.fullName}</span>\r\n </div>\r\n ),\r\n },\r\n {\r\n key: 'email',\r\n label: t('entra:users.columns.email'),\r\n sortable: true,\r\n render: (user) => (\r\n <div className=\"flex items-center gap-1 text-sm text-[var(--text-secondary)]\">\r\n <Mail className=\"w-4 h-4\" />\r\n {user.email}\r\n </div>\r\n ),\r\n },\r\n {\r\n key: 'isActive',\r\n label: t('entra:users.columns.status'),\r\n sortable: true,\r\n render: (user) =>\r\n user.isActive ? (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400\">\r\n <CheckCircle className=\"w-3 h-3\" />\r\n {t('common:active')}\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400\">\r\n <XCircle className=\"w-3 h-3\" />\r\n {t('common:inactive')}\r\n </span>\r\n ),\r\n },\r\n {\r\n key: 'lastEntraSyncAt',\r\n label: t('entra:users.columns.lastSync'),\r\n sortable: true,\r\n render: (user) => (\r\n <div className=\"flex items-center gap-1 text-sm text-[var(--text-secondary)]\">\r\n <Calendar className=\"w-4 h-4\" />\r\n {formatDate(user.lastEntraSyncAt)}\r\n </div>\r\n ),\r\n },\r\n {\r\n key: 'actions',\r\n label: t('entra:users.columns.actions'),\r\n align: 'right',\r\n render: (user) => (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n navigate(`/administration/users/${user.id}`);\r\n }}\r\n className=\"inline-flex items-center gap-1 text-sm text-[var(--color-primary-600)] hover:underline\"\r\n >\r\n {t('common:viewDetails')}\r\n <ExternalLink className=\"w-4 h-4\" />\r\n </button>\r\n ),\r\n },\r\n ];\r\n\r\n // Custom search filter for users\r\n const searchFilter = (user: UserListDto, searchTerm: string) => {\r\n const search = searchTerm.toLowerCase();\r\n return (\r\n user.fullName?.toLowerCase().includes(search) ||\r\n user.email?.toLowerCase().includes(search) ||\r\n false\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.users', 'Users') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-lg bg-[var(--color-primary-100)] dark:bg-[var(--color-primary-900)]\">\r\n <Users className=\"w-6 h-6 text-[var(--color-primary-600)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:users.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:users.subtitle', { count: users.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg border border-[var(--border-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] hover:bg-[var(--bg-secondary)]\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800\">\r\n <div className=\"flex items-center gap-2 text-red-700 dark:text-red-400\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* DataTable */}\r\n <DataTable\r\n data={users}\r\n columns={columns}\r\n loading={loading}\r\n searchable\r\n searchPlaceholder={t('entra:users.searchPlaceholder')}\r\n searchFilter={searchFilter}\r\n pagination={{ pageSize: 20, showSizeSelector: true }}\r\n onRowClick={(user) => navigate(`/administration/users/${user.id}`)}\r\n getRowKey={(user) => user.id}\r\n emptyMessage={t('entra:users.noUsers')}\r\n emptyIcon={<Users className=\"w-12 h-12 mx-auto text-[var(--text-secondary)] opacity-50\" />}\r\n defaultSortKey=\"fullName\"\r\n striped\r\n />\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useRef } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n AlertTriangle,\r\n RefreshCw,\r\n Loader2,\r\n CheckCircle,\r\n} from 'lucide-react';\r\nimport {\r\n entraApi,\r\n type EntraSyncConflictDto,\r\n type ResolveConflictRequest,\r\n} from '@/services/api/entraApi';\r\nimport { ConflictCard, ResolutionModal } from '@/components/platform/administration/entra';\r\n\r\n// ============================================\r\n// Main Component\r\n// ============================================\r\n\r\nexport function EntraConflictsPage(): ReactElement {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const [loading, setLoading] = useState(true);\r\n const [conflicts, setConflicts] = useState<EntraSyncConflictDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [selectedConflict, setSelectedConflict] = useState<EntraSyncConflictDto | null>(null);\r\n const [resolving, setResolving] = useState(false);\r\n\r\n // Abort controller ref for preventing race conditions\r\n const abortControllerRef = useRef<AbortController | null>(null);\r\n const isLoadingRef = useRef(false);\r\n\r\n const loadData = useCallback(async () => {\r\n // Prevent concurrent loads\r\n if (isLoadingRef.current) return;\r\n\r\n // Cancel any pending request\r\n if (abortControllerRef.current) {\r\n abortControllerRef.current.abort();\r\n }\r\n\r\n abortControllerRef.current = new AbortController();\r\n isLoadingRef.current = true;\r\n\r\n try {\r\n setError(null);\r\n const data = await entraApi.conflicts.getAll();\r\n setConflicts(Array.isArray(data) ? data : []);\r\n } catch (err: unknown) {\r\n // Ignore abort errors\r\n if (err instanceof Error && err.name === 'AbortError') {\r\n return;\r\n }\r\n // Log error type only, not the full error object (PII protection)\r\n console.error('Failed to load conflicts:', err instanceof Error ? err.message : 'Unknown error');\r\n setConflicts([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('entra:conflicts.loadError'));\r\n }\r\n } finally {\r\n isLoadingRef.current = false;\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (abortControllerRef.current) {\r\n abortControllerRef.current.abort();\r\n }\r\n };\r\n }, [loadData]);\r\n\r\n const handleResolve = useCallback(async (resolution: ResolveConflictRequest['resolution'], notes?: string) => {\r\n if (!selectedConflict || resolving) return;\r\n\r\n setResolving(true);\r\n try {\r\n await entraApi.conflicts.resolve(selectedConflict.id, {\r\n resolution,\r\n notes: notes || undefined,\r\n });\r\n setSelectedConflict(null);\r\n await loadData();\r\n } catch (err) {\r\n // Log error type only, not the full error object (PII protection)\r\n console.error('Failed to resolve conflict:', err instanceof Error ? err.message : 'Unknown error');\r\n setError(t('entra:conflicts.resolveError'));\r\n } finally {\r\n setResolving(false);\r\n }\r\n }, [selectedConflict, resolving, loadData, t]);\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 return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: t('entra.conflicts', 'Conflicts') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <AlertTriangle className=\"w-6 h-6 text-[var(--color-accent-600)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('entra:conflicts.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('entra:conflicts.subtitle', { count: conflicts.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <button\r\n onClick={loadData}\r\n disabled={loading}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] transition-colors disabled:opacity-50\"\r\n >\r\n <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\r\n {t('common:refresh')}\r\n </button>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n </div>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"text-[var(--error-text)] hover:opacity-70\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* No Conflicts - Empty State */}\r\n {conflicts.length === 0 ? (\r\n <div className=\"text-center py-16 px-6 rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)]\">\r\n <div className=\"mx-auto w-16 h-16 rounded-full bg-[var(--success-bg)] flex items-center justify-center mb-4\">\r\n <CheckCircle className=\"w-8 h-8 text-[var(--success-text)]\" />\r\n </div>\r\n <h2 className=\"text-xl font-semibold text-[var(--text-primary)] mb-2\">\r\n {t('entra:conflicts.noConflicts')}\r\n </h2>\r\n <p className=\"text-[var(--text-secondary)] max-w-md mx-auto\">\r\n {t('entra:conflicts.noConflictsDescription')}\r\n </p>\r\n </div>\r\n ) : (\r\n /* Conflicts Grid */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {conflicts.map((conflict) => (\r\n <ConflictCard\r\n key={conflict.id}\r\n conflict={conflict}\r\n onResolve={setSelectedConflict}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Resolve Modal */}\r\n {selectedConflict && (\r\n <ResolutionModal\r\n conflict={selectedConflict}\r\n onClose={() => setSelectedConflict(null)}\r\n onResolve={handleResolve}\r\n resolving={resolving}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, type ReactNode } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport type { LucideIcon } from 'lucide-react';\r\nimport {\r\n Settings,\r\n Key,\r\n Eye,\r\n EyeOff,\r\n Save,\r\n AlertTriangle,\r\n CheckCircle,\r\n ExternalLink,\r\n Shield,\r\n Clock,\r\n Loader2,\r\n TestTube,\r\n Users,\r\n Layers,\r\n Building2,\r\n Copy,\r\n Check,\r\n GitMerge,\r\n Filter,\r\n} from 'lucide-react';\r\nimport { entraApi } from '@/services/api/entraApi';\r\nimport type { TestConnectionResult, EntraConfigurationDto } from '@/services/api/entraApi';\r\n\r\ninterface EntraCredentials {\r\n tenantId: string;\r\n clientId: string;\r\n clientSecret: string;\r\n}\r\n\r\ninterface SyncSettings {\r\n syncEnabled: boolean;\r\n syncIntervalMinutes: number;\r\n useDeltaSync: boolean;\r\n defaultConflictResolution: 'ManualReview' | 'EntraWins' | 'LocalWins';\r\n autoCreateReferences: boolean;\r\n // User sync filters\r\n syncOnlyActiveUsers: boolean;\r\n syncUserTypes: string; // comma-separated: member, guest, shared, room, equipment\r\n}\r\n\r\n// Available user types for sync\r\n// Note: shared, room, equipment require mailboxSettings which is not available in bulk user listing API\r\nconst USER_TYPES = [\r\n { id: 'member', labelKey: 'userTypes.member', descriptionKey: 'userTypes.memberDescription', supported: true },\r\n { id: 'guest', labelKey: 'userTypes.guest', descriptionKey: 'userTypes.guestDescription', supported: true },\r\n { id: 'shared', labelKey: 'userTypes.shared', descriptionKey: 'userTypes.sharedDescription', supported: false },\r\n { id: 'room', labelKey: 'userTypes.room', descriptionKey: 'userTypes.roomDescription', supported: false },\r\n { id: 'equipment', labelKey: 'userTypes.equipment', descriptionKey: 'userTypes.equipmentDescription', supported: false },\r\n];\r\n\r\n// Required permissions for Microsoft Graph API\r\nconst REQUIRED_PERMISSIONS = [\r\n { code: 'User.Read.All', descriptionKey: 'userReadAll' },\r\n { code: 'Group.Read.All', descriptionKey: 'groupReadAll' },\r\n { code: 'GroupMember.Read.All', descriptionKey: 'groupMemberReadAll' },\r\n];\r\n\r\n// ============================================\r\n// Reusable Components\r\n// ============================================\r\n\r\ninterface SectionCardProps {\r\n readonly icon: LucideIcon;\r\n readonly title: string;\r\n readonly description?: string;\r\n readonly action?: ReactNode;\r\n readonly children: ReactNode;\r\n readonly className?: string;\r\n}\r\n\r\nfunction SectionCard({ icon: Icon, title, description, action, children, className = '' }: SectionCardProps) {\r\n return (\r\n <div className={`rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] shadow-sm overflow-hidden ${className}`}>\r\n {/* Header */}\r\n <div className=\"px-6 py-4 border-b border-[var(--border-subtle)] bg-[var(--bg-secondary)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30\">\r\n <Icon className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h2 className=\"text-base font-semibold text-[var(--text-primary)]\">{title}</h2>\r\n {description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">{description}</p>\r\n )}\r\n </div>\r\n </div>\r\n {action}\r\n </div>\r\n </div>\r\n {/* Content */}\r\n <div className=\"p-6\">\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\ninterface ToggleProps {\r\n readonly checked: boolean;\r\n readonly onChange: () => void;\r\n readonly label: string;\r\n readonly description?: string;\r\n}\r\n\r\nfunction Toggle({ checked, onChange, label, description }: ToggleProps) {\r\n return (\r\n <div className=\"flex items-center justify-between py-3\">\r\n <div className=\"flex-1 min-w-0 pr-4\">\r\n <label className=\"text-sm font-medium text-[var(--text-primary)]\">{label}</label>\r\n {description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">{description}</p>\r\n )}\r\n </div>\r\n <button\r\n type=\"button\"\r\n role=\"switch\"\r\n aria-checked={checked}\r\n onClick={onChange}\r\n className={`relative inline-flex h-6 w-11 flex-shrink-0 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:ring-offset-2 focus:ring-offset-[var(--bg-primary)] ${\r\n checked ? 'bg-[var(--color-accent-600)]' : 'bg-[var(--bg-tertiary)]'\r\n }`}\r\n >\r\n <span\r\n className={`inline-block h-4 w-4 transform rounded-full bg-[var(--toggle-knob)] shadow-md transition-transform ${\r\n checked ? 'translate-x-6' : 'translate-x-1'\r\n }`}\r\n />\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\n// ============================================\r\n// Validation\r\n// ============================================\r\n\r\nconst isValidGuid = (value: string): boolean => {\r\n if (!value) return true;\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 useEntraSettings = () => {\r\n const { t } = useTranslation(['entra', 'common']);\r\n const [loading, setLoading] = useState(true);\r\n const [saving, setSaving] = useState(false);\r\n const [testing, setTesting] = useState(false);\r\n const [testResult, setTestResult] = useState<TestConnectionResult | null>(null);\r\n const [showSecret, setShowSecret] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n const [hasExistingSecret, setHasExistingSecret] = useState(false);\r\n const [copiedPermission, setCopiedPermission] = useState<string | null>(null);\r\n const [validationErrors, setValidationErrors] = useState<{\r\n tenantId?: string;\r\n clientId?: string;\r\n }>({});\r\n\r\n const [credentials, setCredentials] = useState<EntraCredentials>({\r\n tenantId: '',\r\n clientId: '',\r\n clientSecret: '',\r\n });\r\n\r\n const [syncSettings, setSyncSettings] = useState<SyncSettings>({\r\n syncEnabled: false,\r\n syncIntervalMinutes: 60,\r\n useDeltaSync: true,\r\n defaultConflictResolution: 'ManualReview',\r\n autoCreateReferences: true,\r\n syncOnlyActiveUsers: true,\r\n syncUserTypes: 'member',\r\n });\r\n\r\n return {\r\n t, loading, setLoading, saving, setSaving, testing, setTesting,\r\n testResult, setTestResult, showSecret, setShowSecret, error, setError,\r\n success, setSuccess, hasExistingSecret, setHasExistingSecret,\r\n copiedPermission, setCopiedPermission, validationErrors, setValidationErrors,\r\n credentials, setCredentials, syncSettings, setSyncSettings\r\n };\r\n};\r\n\r\n// ============================================\r\n// Helpers\r\n// ============================================\r\n\r\nfunction getCheckboxCardClass(isDisabled: boolean, isChecked: boolean): string {\r\n if (isDisabled) return 'opacity-50 cursor-not-allowed border-[var(--border-color)] bg-[var(--bg-tertiary)]';\r\n if (isChecked) return 'cursor-pointer border-[var(--color-accent-500)] bg-[var(--color-accent-50)] dark:bg-[var(--color-accent-900)]/20';\r\n return 'cursor-pointer border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-tertiary)]';\r\n}\r\n\r\n// ============================================\r\n// Main Component\r\n// ============================================\r\n\r\nexport function EntraSettingsPage(): ReactElement {\r\n const state = useEntraSettings();\r\n\r\n const loadConfiguration = useCallback(async () => {\r\n try {\r\n state.setLoading(true);\r\n const config: EntraConfigurationDto = await entraApi.settings.getConfiguration();\r\n\r\n state.setCredentials({\r\n tenantId: config.tenantId || '',\r\n clientId: config.clientId || '',\r\n clientSecret: '',\r\n });\r\n state.setHasExistingSecret(config.hasClientSecret);\r\n\r\n state.setSyncSettings({\r\n syncEnabled: config.syncEnabled,\r\n syncIntervalMinutes: config.syncIntervalMinutes,\r\n useDeltaSync: config.useDeltaSync,\r\n defaultConflictResolution: config.defaultConflictResolution as SyncSettings['defaultConflictResolution'],\r\n autoCreateReferences: config.autoCreateReferences,\r\n syncOnlyActiveUsers: config.syncOnlyActiveUsers ?? true,\r\n syncUserTypes: config.syncUserTypes ?? 'member',\r\n });\r\n } catch (err) {\r\n console.error('Failed to load configuration:', err);\r\n state.setError(state.t('entra:settings.saveError'));\r\n } finally {\r\n state.setLoading(false);\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []); // React setters are stable, no need to include them in dependencies\r\n\r\n useEffect(() => {\r\n loadConfiguration();\r\n }, [loadConfiguration]);\r\n\r\n const handleCopyPermission = async (code: string) => {\r\n try {\r\n await navigator.clipboard.writeText(code);\r\n state.setCopiedPermission(code);\r\n setTimeout(() => state.setCopiedPermission(null), 2000);\r\n } catch (err) {\r\n console.error('Failed to copy:', err);\r\n }\r\n };\r\n\r\n const validateCredentialField = (field: 'tenantId' | 'clientId', value: string) => {\r\n const errorKey = isValidGuid(value) ? undefined : state.t('entra:settings.invalidGuidFormat');\r\n state.setValidationErrors(prev => ({ ...prev, [field]: errorKey }));\r\n };\r\n\r\n const handleCredentialChange = (field: keyof EntraCredentials, value: string) => {\r\n state.setCredentials(prev => ({ ...prev, [field]: value }));\r\n if (field === 'tenantId' || field === 'clientId') {\r\n validateCredentialField(field, value);\r\n }\r\n };\r\n\r\n const hasValidationErrors = Boolean(\r\n state.validationErrors.tenantId || state.validationErrors.clientId\r\n );\r\n\r\n const handleTestConnection = async () => {\r\n state.setTesting(true);\r\n state.setTestResult(null);\r\n state.setError(null);\r\n state.setSuccess(null);\r\n try {\r\n let result: TestConnectionResult;\r\n\r\n if (state.credentials.clientSecret) {\r\n result = await entraApi.settings.testConnection({\r\n tenantId: state.credentials.tenantId,\r\n clientId: state.credentials.clientId,\r\n clientSecret: state.credentials.clientSecret,\r\n });\r\n } else if (state.hasExistingSecret) {\r\n result = await entraApi.settings.testStoredConnection();\r\n } else {\r\n state.setError(state.t('entra:settings.testFailed'));\r\n state.setTesting(false);\r\n return;\r\n }\r\n\r\n state.setTestResult(result);\r\n if (result.success) {\r\n state.setSuccess(state.t('entra:settings.testSuccess'));\r\n } else {\r\n state.setError(result.errorMessage || state.t('entra:settings.testFailed'));\r\n }\r\n } catch (err) {\r\n console.error('Connection test failed:', err);\r\n state.setTestResult({ success: false, errorMessage: state.t('entra:settings.testFailed'), tenantName: null, userCount: null, groupCount: null });\r\n state.setError(state.t('entra:settings.testFailed'));\r\n } finally {\r\n state.setTesting(false);\r\n }\r\n };\r\n\r\n const handleSaveCredentials = async () => {\r\n state.setSaving(true);\r\n state.setError(null);\r\n state.setSuccess(null);\r\n try {\r\n await entraApi.settings.saveCredentials({\r\n tenantId: state.credentials.tenantId,\r\n clientId: state.credentials.clientId,\r\n clientSecret: state.credentials.clientSecret,\r\n });\r\n state.setSuccess(state.t('entra:settings.credentialsSaved'));\r\n state.setHasExistingSecret(true);\r\n state.setCredentials((prev) => ({ ...prev, clientSecret: '' }));\r\n } catch (err) {\r\n console.error('Failed to save credentials:', err);\r\n state.setError(state.t('entra:settings.saveError'));\r\n } finally {\r\n state.setSaving(false);\r\n }\r\n };\r\n\r\n const handleSaveSettings = async () => {\r\n state.setSaving(true);\r\n state.setError(null);\r\n state.setSuccess(null);\r\n try {\r\n await entraApi.settings.saveSyncSettings({\r\n syncEnabled: state.syncSettings.syncEnabled,\r\n syncIntervalMinutes: state.syncSettings.syncIntervalMinutes,\r\n useDeltaSync: state.syncSettings.useDeltaSync,\r\n defaultConflictResolution: state.syncSettings.defaultConflictResolution,\r\n autoCreateReferences: state.syncSettings.autoCreateReferences,\r\n syncOnlyActiveUsers: state.syncSettings.syncOnlyActiveUsers,\r\n syncUserTypes: state.syncSettings.syncUserTypes,\r\n });\r\n state.setSuccess(state.t('entra:settings.settingsSaved'));\r\n } catch (err) {\r\n console.error('Failed to save settings:', err);\r\n state.setError(state.t('entra:settings.saveError'));\r\n } finally {\r\n state.setSaving(false);\r\n }\r\n };\r\n\r\n if (state.loading) {\r\n return (\r\n <div className=\"flex items-center justify-center h-64\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: state.t('header.title'), href: '/administration' },\r\n { label: state.t('entra.title', 'Microsoft Entra ID'), href: '/administration/entra' },\r\n { label: state.t('entra.settings', 'Settings') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"p-3 rounded-[var(--radius-card)] bg-gradient-to-br from-[var(--color-accent-500)] to-[var(--color-accent-700)] shadow-lg\">\r\n <Settings className=\"w-7 h-7 text-white\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {state.t('entra:settings.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {state.t('entra:settings.subtitle')}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* Required Permissions Warning */}\r\n <div className=\"rounded-[var(--radius-card)] border-2 border-[var(--warning-border)] bg-[var(--warning-bg)] overflow-hidden\">\r\n <div className=\"px-5 py-4\">\r\n <div className=\"flex items-start gap-4\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--warning-border)]\">\r\n <Shield className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center justify-between gap-4 mb-2\">\r\n <h2 className=\"font-semibold text-[var(--warning-text)]\">\r\n {state.t('entra:settings.permissionsWarningTitle')}\r\n </h2>\r\n <a\r\n href=\"https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--warning-border)] text-[var(--warning-text)] hover:opacity-80 transition-opacity\"\r\n >\r\n {state.t('entra:settings.configureInAzure')}\r\n <ExternalLink className=\"w-3.5 h-3.5\" />\r\n </a>\r\n </div>\r\n <p className=\"text-sm text-[var(--warning-text)] opacity-90 mb-4\">\r\n {state.t('entra:settings.permissionsWarningDescription')}\r\n </p>\r\n\r\n {/* Copyable Permissions */}\r\n <div className=\"flex flex-wrap gap-2\">\r\n {REQUIRED_PERMISSIONS.map((perm) => (\r\n <button\r\n key={perm.code}\r\n onClick={() => handleCopyPermission(perm.code)}\r\n className=\"group inline-flex items-center gap-2 px-3 py-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)] border border-[var(--warning-border)] hover:border-[var(--warning-dot)] transition-all hover:shadow-sm\"\r\n title={state.t(`entra:settings.permissions.${perm.descriptionKey}`)}\r\n >\r\n <code className=\"text-sm font-mono font-medium text-[var(--text-primary)]\">{perm.code}</code>\r\n {state.copiedPermission === perm.code ? (\r\n <Check className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n ) : (\r\n <Copy className=\"w-4 h-4 text-[var(--warning-text)] group-hover:opacity-80\" />\r\n )}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Error/Success Messages */}\r\n {state.error && (\r\n <div className=\"flex items-center gap-3 p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <AlertTriangle className=\"w-5 h-5 text-[var(--error-text)] flex-shrink-0\" />\r\n <span className=\"text-sm text-[var(--error-text)]\">{state.error}</span>\r\n </div>\r\n )}\r\n\r\n {state.success && (\r\n <div className=\"flex items-center gap-3 p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)]\">\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)] flex-shrink-0\" />\r\n <span className=\"text-sm text-[var(--success-text)]\">{state.success}</span>\r\n </div>\r\n )}\r\n\r\n {/* Main Content Grid */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\r\n {/* ============================================ */}\r\n {/* Left Column - Credentials */}\r\n {/* ============================================ */}\r\n <SectionCard\r\n icon={Key}\r\n title={state.t('entra:settings.credentials')}\r\n description=\"Azure AD Application\"\r\n action={\r\n <a\r\n href=\"https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"inline-flex items-center gap-1.5 text-sm text-[var(--color-accent-500)] hover:text-[var(--color-accent-600)] transition-colors\"\r\n >\r\n {state.t('entra:settings.azurePortal')}\r\n <ExternalLink className=\"w-4 h-4\" />\r\n </a>\r\n }\r\n >\r\n <div className=\"space-y-5\">\r\n {/* Tenant ID */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1.5\">\r\n {state.t('entra:settings.tenantId')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={state.credentials.tenantId}\r\n onChange={(e) => handleCredentialChange('tenantId', e.target.value)}\r\n placeholder=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\r\n autoComplete=\"off\"\r\n className={`w-full px-3 py-2.5 rounded-[var(--radius-input)] border bg-[var(--bg-secondary)] text-[var(--text-primary)] font-mono text-sm focus:outline-none focus:ring-2 focus:border-transparent transition-shadow ${\r\n state.validationErrors.tenantId\r\n ? 'border-[var(--error-border)] focus:ring-[var(--error-border)]'\r\n : 'border-[var(--border-color)] focus:ring-[var(--color-accent-500)]'\r\n }`}\r\n />\r\n {state.validationErrors.tenantId ? (\r\n <p className=\"mt-1.5 text-xs text-[var(--error-text)]\">{state.validationErrors.tenantId}</p>\r\n ) : (\r\n <p className=\"mt-1.5 text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.tenantIdHelp')}</p>\r\n )}\r\n </div>\r\n\r\n {/* Client ID */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1.5\">\r\n {state.t('entra:settings.clientId')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={state.credentials.clientId}\r\n onChange={(e) => handleCredentialChange('clientId', e.target.value)}\r\n placeholder=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\r\n autoComplete=\"off\"\r\n className={`w-full px-3 py-2.5 rounded-[var(--radius-input)] border bg-[var(--bg-secondary)] text-[var(--text-primary)] font-mono text-sm focus:outline-none focus:ring-2 focus:border-transparent transition-shadow ${\r\n state.validationErrors.clientId\r\n ? 'border-[var(--error-border)] focus:ring-[var(--error-border)]'\r\n : 'border-[var(--border-color)] focus:ring-[var(--color-accent-500)]'\r\n }`}\r\n />\r\n {state.validationErrors.clientId ? (\r\n <p className=\"mt-1.5 text-xs text-[var(--error-text)]\">{state.validationErrors.clientId}</p>\r\n ) : (\r\n <p className=\"mt-1.5 text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.clientIdHelp')}</p>\r\n )}\r\n </div>\r\n\r\n {/* Client Secret */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1.5\">\r\n {state.t('entra:settings.clientSecret')}\r\n {state.hasExistingSecret && (\r\n <span className=\"ml-2 inline-flex items-center gap-1 text-xs text-[var(--success-text)]\">\r\n <CheckCircle className=\"w-3 h-3\" />\r\n {state.t('common:configured')}\r\n </span>\r\n )}\r\n </label>\r\n <div className=\"relative\">\r\n <input\r\n type={state.showSecret ? 'text' : 'password'}\r\n value={state.credentials.clientSecret}\r\n onChange={(e) => handleCredentialChange('clientSecret', e.target.value)}\r\n placeholder={state.hasExistingSecret ? '••••••••••••••••••••••••••••••••••••••••' : 'OvA8Q~xxxxxxxxxxxxxxxxxxxxxxxxxxxx'}\r\n autoComplete=\"new-password\"\r\n className=\"w-full px-3 py-2.5 pr-10 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] font-mono text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-shadow\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => state.setShowSecret(!state.showSecret)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 text-[var(--text-tertiary)] hover:text-[var(--text-primary)] transition-colors\"\r\n >\r\n {state.showSecret ? <EyeOff className=\"w-4 h-4\" /> : <Eye className=\"w-4 h-4\" />}\r\n </button>\r\n </div>\r\n <p className=\"mt-1.5 text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.clientSecretHelp')}</p>\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n <div className=\"flex items-center gap-3 pt-2\">\r\n <button\r\n onClick={handleTestConnection}\r\n disabled={state.testing || hasValidationErrors || !state.credentials.tenantId || !state.credentials.clientId || (!state.credentials.clientSecret && !state.hasExistingSecret)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-tertiary)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {state.testing && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {!state.testing && state.testResult?.success && <CheckCircle className=\"w-4 h-4 text-[var(--success-text)]\" />}\r\n {!state.testing && state.testResult && !state.testResult.success && <AlertTriangle className=\"w-4 h-4 text-[var(--error-text)]\" />}\r\n {!state.testing && !state.testResult && <TestTube className=\"w-4 h-4\" />}\r\n {state.t('entra:settings.testConnection')}\r\n </button>\r\n <button\r\n onClick={handleSaveCredentials}\r\n disabled={state.saving || hasValidationErrors || !state.credentials.tenantId || !state.credentials.clientId || !state.credentials.clientSecret}\r\n className=\"inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium 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 shadow-sm\"\r\n >\r\n {state.saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {state.t('common:save')}\r\n </button>\r\n </div>\r\n\r\n {/* Test Result Details */}\r\n {state.testResult?.success && (\r\n <div className=\"mt-4 p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)]\">\r\n <div className=\"flex items-center gap-2 mb-3\">\r\n <CheckCircle className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n <span className=\"font-medium text-[var(--success-text)]\">\r\n {state.t('entra:settings.connectionSuccessful')}\r\n </span>\r\n </div>\r\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-3\">\r\n {state.testResult.tenantName && (\r\n <div className=\"flex items-center gap-2 p-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)]\">\r\n <Building2 className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n <div className=\"min-w-0\">\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.tenantName')}</p>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">{state.testResult.tenantName}</p>\r\n </div>\r\n </div>\r\n )}\r\n {state.testResult.userCount !== null && (\r\n <div className=\"flex items-center gap-2 p-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)]\">\r\n <Users className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n <div>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.userCount')}</p>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">{state.testResult.userCount}</p>\r\n </div>\r\n </div>\r\n )}\r\n {state.testResult.groupCount !== null && (\r\n <div className=\"flex items-center gap-2 p-2 rounded-[var(--radius-button)] bg-[var(--bg-primary)]\">\r\n <Layers className=\"w-4 h-4 text-[var(--success-text)]\" />\r\n <div>\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{state.t('entra:settings.groupCount')}</p>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">{state.testResult.groupCount}</p>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </SectionCard>\r\n\r\n {/* ============================================ */}\r\n {/* Right Column - Sync Settings Stack */}\r\n {/* ============================================ */}\r\n <div className=\"space-y-6\">\r\n {/* Sync Configuration */}\r\n <SectionCard\r\n icon={Clock}\r\n title={state.t('entra:settings.syncSettings')}\r\n description=\"Scheduling & Performance\"\r\n >\r\n <div className=\"divide-y divide-[var(--border-subtle)]\">\r\n <Toggle\r\n checked={state.syncSettings.syncEnabled}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, syncEnabled: !prev.syncEnabled }))}\r\n label={state.t('entra:settings.syncEnabled')}\r\n description={state.t('entra:settings.syncEnabledHelp')}\r\n />\r\n\r\n <div className=\"py-4\">\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {state.t('entra:settings.syncInterval')}\r\n </label>\r\n <select\r\n value={state.syncSettings.syncIntervalMinutes}\r\n onChange={(e) => state.setSyncSettings((prev) => ({ ...prev, syncIntervalMinutes: Number(e.target.value) }))}\r\n className=\"w-full px-3 py-2.5 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] transition-shadow\"\r\n >\r\n <option value={15}>15 {state.t('common:minutes')}</option>\r\n <option value={30}>30 {state.t('common:minutes')}</option>\r\n <option value={60}>1 {state.t('common:hour')}</option>\r\n <option value={120}>2 {state.t('common:hours')}</option>\r\n <option value={360}>6 {state.t('common:hours')}</option>\r\n <option value={720}>12 {state.t('common:hours')}</option>\r\n <option value={1440}>24 {state.t('common:hours')}</option>\r\n </select>\r\n </div>\r\n\r\n <Toggle\r\n checked={state.syncSettings.useDeltaSync}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, useDeltaSync: !prev.useDeltaSync }))}\r\n label={state.t('entra:settings.useDeltaSync')}\r\n description={state.t('entra:settings.useDeltaSyncHelp')}\r\n />\r\n\r\n <Toggle\r\n checked={state.syncSettings.autoCreateReferences}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, autoCreateReferences: !prev.autoCreateReferences }))}\r\n label={state.t('entra:settings.autoCreateReferences')}\r\n description={state.t('entra:settings.autoCreateReferencesHelp')}\r\n />\r\n </div>\r\n </SectionCard>\r\n\r\n {/* Conflict Resolution */}\r\n <SectionCard\r\n icon={GitMerge}\r\n title={state.t('entra:settings.conflictResolution')}\r\n description=\"Data Priority\"\r\n >\r\n <div>\r\n <select\r\n value={state.syncSettings.defaultConflictResolution}\r\n onChange={(e) => state.setSyncSettings((prev) => ({ ...prev, defaultConflictResolution: e.target.value as SyncSettings['defaultConflictResolution'] }))}\r\n className=\"w-full px-3 py-2.5 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] transition-shadow\"\r\n >\r\n <option value=\"ManualReview\">{state.t('entra:settings.conflictResolutions.manualReview')}</option>\r\n <option value=\"EntraWins\">{state.t('entra:settings.conflictResolutions.entraWins')}</option>\r\n <option value=\"LocalWins\">{state.t('entra:settings.conflictResolutions.localWins')}</option>\r\n </select>\r\n <p className=\"mt-2 text-xs text-[var(--text-tertiary)]\">\r\n {state.t('entra:settings.conflictResolutionHelp')}\r\n </p>\r\n </div>\r\n </SectionCard>\r\n\r\n {/* User Filters */}\r\n <SectionCard\r\n icon={Filter}\r\n title={state.t('entra:settings.userSyncFilters')}\r\n description=\"User Types & Filters\"\r\n >\r\n <div className=\"space-y-4\">\r\n <Toggle\r\n checked={state.syncSettings.syncOnlyActiveUsers}\r\n onChange={() => state.setSyncSettings((prev) => ({ ...prev, syncOnlyActiveUsers: !prev.syncOnlyActiveUsers }))}\r\n label={state.t('entra:settings.syncOnlyActiveUsers')}\r\n description={state.t('entra:settings.syncOnlyActiveUsersHelp')}\r\n />\r\n\r\n <div className=\"pt-2 border-t border-[var(--border-subtle)]\">\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {state.t('entra:settings.syncUserTypesLabel')}\r\n </label>\r\n <p className=\"text-xs text-[var(--text-tertiary)] mb-3\">\r\n {state.t('entra:settings.syncUserTypesHelp')}\r\n </p>\r\n <div className=\"space-y-2\">\r\n {USER_TYPES.map((userType) => {\r\n const selectedTypes = state.syncSettings.syncUserTypes.split(',').map(t => t.trim()).filter(Boolean);\r\n const isChecked = selectedTypes.includes(userType.id);\r\n const isDisabled = !userType.supported;\r\n\r\n const handleToggle = () => {\r\n if (isDisabled) return;\r\n let newTypes: string[];\r\n if (isChecked) {\r\n newTypes = selectedTypes.filter(t => t !== userType.id);\r\n } else {\r\n newTypes = [...selectedTypes, userType.id];\r\n }\r\n if (newTypes.length === 0) newTypes = ['member'];\r\n state.setSyncSettings(prev => ({ ...prev, syncUserTypes: newTypes.join(',') }));\r\n };\r\n\r\n return (\r\n <label\r\n key={userType.id}\r\n className={`flex items-start gap-3 p-3 rounded-[var(--radius-button)] border transition-all ${\r\n getCheckboxCardClass(isDisabled, isChecked)\r\n }`}\r\n >\r\n <input\r\n type=\"checkbox\"\r\n checked={isChecked}\r\n onChange={handleToggle}\r\n disabled={isDisabled}\r\n className=\"mt-0.5 w-4 h-4 rounded border-[var(--border-color)] text-[var(--color-accent-600)] focus:ring-[var(--color-accent-500)] disabled:opacity-50\"\r\n />\r\n <div className=\"flex-1 min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {state.t(`entra:settings.${userType.labelKey}`)}\r\n </span>\r\n {isDisabled && (\r\n <span className=\"text-xs px-1.5 py-0.5 rounded bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n {state.t('common:comingSoon')}\r\n </span>\r\n )}\r\n </div>\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-0.5\">\r\n {state.t(`entra:settings.${userType.descriptionKey}`)}\r\n </p>\r\n </div>\r\n </label>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n </SectionCard>\r\n\r\n {/* Save Button */}\r\n <div className=\"flex justify-end\">\r\n <button\r\n onClick={handleSaveSettings}\r\n disabled={state.saving}\r\n className=\"inline-flex items-center gap-2 px-6 py-2.5 text-sm font-medium 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 shadow-sm\"\r\n >\r\n {state.saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {state.t('common:save')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["SyncStatusCard","resourceType","Icon","status","lastFullSyncAt","lastDeltaSyncAt","totalItemsSynced","pendingConflicts","lastError","syncing","canSync","onSync","formatDate","t","statusConfig","CheckCircle","XCircle","Loader2","Clock","StatusIcon","jsxs","jsx","Database","Calendar","RefreshCw","AlertCircle","Tooltip","EntraDashboardPage","useTranslation","hasPermission","useAuth","loading","setLoading","useState","refreshing","setRefreshing","syncStatus","setSyncStatus","error","setError","setSyncing","lastSyncResult","setLastSyncResult","loadData","useCallback","entraApi","err","axiosError","useEffect","handleRefresh","handleSync","type","result","handleForceFullSync","date","getResourceIcon","Users","Building2","Link2","Cloud","totalPendingConflicts","sum","s","Breadcrumb","Play","AlertTriangle","getGroupHierarchyDisplay","group","GitBranch","EntraGroupsPage","currentTenant","isGlobalView","useTenant","navigate","useNavigate","groups","setGroups","roles","setRoles","searchQuery","setSearchQuery","selectedGroup","setSelectedGroup","showAssignModal","setShowAssignModal","expandedGroupId","setExpandedGroupId","members","setMembers","loadingMembers","setLoadingMembers","viewMode","setViewMode","groupTypeFilter","setGroupTypeFilter","assigning","setAssigning","canAssign","groupsData","rolesData","adminApi","loadMembers","groupId","data","prev","reloadGroupsAndRoles","safeGroupsData","handleAssignRole","roleId","isInheritable","updatedGroup","g","handleRemoveRole","filteredGroups","matchesSearch","matchesType","X","Search","e","Filter","LayoutGrid","List","Shield","role","Plus","ChevronUp","ChevronDown","Fragment","member","Link","r","EntraUsersPage","users","setUsers","response","columns","user","Mail","ExternalLink","searchFilter","searchTerm","search","DataTable","EntraConflictsPage","conflicts","setConflicts","selectedConflict","setSelectedConflict","resolving","setResolving","abortControllerRef","useRef","isLoadingRef","handleResolve","resolution","notes","conflict","ConflictCard","ResolutionModal","USER_TYPES","REQUIRED_PERMISSIONS","SectionCard","title","description","action","children","className","Toggle","checked","onChange","label","isValidGuid","value","useEntraSettings","saving","setSaving","testing","setTesting","testResult","setTestResult","showSecret","setShowSecret","success","setSuccess","hasExistingSecret","setHasExistingSecret","copiedPermission","setCopiedPermission","validationErrors","setValidationErrors","credentials","setCredentials","syncSettings","setSyncSettings","getCheckboxCardClass","isDisabled","isChecked","EntraSettingsPage","state","loadConfiguration","config","handleCopyPermission","code","validateCredentialField","field","errorKey","handleCredentialChange","hasValidationErrors","handleTestConnection","handleSaveCredentials","handleSaveSettings","Settings","perm","Check","Copy","Key","EyeOff","Eye","TestTube","Save","Layers","GitMerge","userType","selectedTypes","handleToggle","newTypes"],"mappings":"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"}