@atlashub/smartstack 3.21.0 → 3.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js → AgentSkillsPage-BWQSCYl-.js} +2 -2
  2. package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js.map → AgentSkillsPage-BWQSCYl-.js.map} +1 -1
  3. package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js → AgentSkillsPage-IQcMnBaD.js} +2 -2
  4. package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js.map → AgentSkillsPage-IQcMnBaD.js.map} +1 -1
  5. package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js → AgentWorkloadPage-DqrjkvWL.js} +2 -2
  6. package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js.map → AgentWorkloadPage-DqrjkvWL.js.map} +1 -1
  7. package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js → AgentWorkloadPage-w-HiyFYP.js} +2 -2
  8. package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js.map → AgentWorkloadPage-w-HiyFYP.js.map} +1 -1
  9. package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js → ApiCatalogDetailPage-D3L8Yf4G.js} +3 -3
  10. package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js.map → ApiCatalogDetailPage-D3L8Yf4G.js.map} +1 -1
  11. package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js → ApiCatalogDetailPage-MPT3Kz6H.js} +2 -2
  12. package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js.map → ApiCatalogDetailPage-MPT3Kz6H.js.map} +1 -1
  13. package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js → ApiCatalogPage-D4Hg3uiS.js} +2 -2
  14. package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js.map → ApiCatalogPage-D4Hg3uiS.js.map} +1 -1
  15. package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js → ApiCatalogPage-DRg5Cz0r.js} +2 -2
  16. package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js.map → ApiCatalogPage-DRg5Cz0r.js.map} +1 -1
  17. package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js → ApplicationDetailPage-Caizuyn2.js} +2 -2
  18. package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js.map → ApplicationDetailPage-Caizuyn2.js.map} +1 -1
  19. package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js → ApplicationDetailPage-CuCW6aMB.js} +4 -4
  20. package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js.map → ApplicationDetailPage-CuCW6aMB.js.map} +1 -1
  21. package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js → ApplicationsDashboardPage-B2MW8-Kc.js} +2 -2
  22. package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js.map → ApplicationsDashboardPage-B2MW8-Kc.js.map} +1 -1
  23. package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js → ApplicationsDashboardPage-BDIjFIYZ.js} +3 -3
  24. package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js.map → ApplicationsDashboardPage-BDIjFIYZ.js.map} +1 -1
  25. package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js → ApplicationsGridPage-DV-FihKj.js} +2 -2
  26. package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js.map → ApplicationsGridPage-DV-FihKj.js.map} +1 -1
  27. package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js → ApplicationsGridPage-DXsTfXPI.js} +2 -2
  28. package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js.map → ApplicationsGridPage-DXsTfXPI.js.map} +1 -1
  29. package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js → ApplicationsListPage--CGkyBuJ.js} +2 -2
  30. package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js.map → ApplicationsListPage--CGkyBuJ.js.map} +1 -1
  31. package/dist/chunks/{ApplicationsListPage-C91v2rZt.js → ApplicationsListPage-JUX823bh.js} +2 -2
  32. package/dist/chunks/{ApplicationsListPage-C91v2rZt.js.map → ApplicationsListPage-JUX823bh.js.map} +1 -1
  33. package/dist/chunks/{ApplicationsPage-BCbgotIx.js → ApplicationsPage-6zgFye6w.js} +2 -2
  34. package/dist/chunks/{ApplicationsPage-BCbgotIx.js.map → ApplicationsPage-6zgFye6w.js.map} +1 -1
  35. package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js → ApplicationsPage-CQPuuiO6.js} +4 -4
  36. package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js.map → ApplicationsPage-CQPuuiO6.js.map} +1 -1
  37. package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js → AssignmentRulesPage-CFffeEbo.js} +2 -2
  38. package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js.map → AssignmentRulesPage-CFffeEbo.js.map} +1 -1
  39. package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js → AssignmentRulesPage-D78UeUId.js} +2 -2
  40. package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js.map → AssignmentRulesPage-D78UeUId.js.map} +1 -1
  41. package/dist/chunks/{AssignmentsPage-DmfBYQAD.js → AssignmentsPage-Cww2ifZF.js} +2 -2
  42. package/dist/chunks/{AssignmentsPage-DmfBYQAD.js.map → AssignmentsPage-Cww2ifZF.js.map} +1 -1
  43. package/dist/chunks/{AssignmentsPage-sRCCBmRc.js → AssignmentsPage-DE_QS2LO.js} +2 -2
  44. package/dist/chunks/{AssignmentsPage-sRCCBmRc.js.map → AssignmentsPage-DE_QS2LO.js.map} +1 -1
  45. package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js → AuthCallbackPage-CA2nO6DG.js} +2 -2
  46. package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js.map → AuthCallbackPage-CA2nO6DG.js.map} +1 -1
  47. package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js → AuthCallbackPage-CDUAoX-N.js} +2 -2
  48. package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js.map → AuthCallbackPage-CDUAoX-N.js.map} +1 -1
  49. package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js → ConfirmEmailPage-BqsILAYH.js} +2 -2
  50. package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js.map → ConfirmEmailPage-BqsILAYH.js.map} +1 -1
  51. package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js → ConfirmEmailPage-INeHCuMB.js} +2 -2
  52. package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js.map → ConfirmEmailPage-INeHCuMB.js.map} +1 -1
  53. package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js → CreateSupportTicketPage-BWeuV2aU.js} +2 -2
  54. package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js.map → CreateSupportTicketPage-BWeuV2aU.js.map} +1 -1
  55. package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js → CreateSupportTicketPage-OBwF4v7b.js} +2 -2
  56. package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js.map → CreateSupportTicketPage-OBwF4v7b.js.map} +1 -1
  57. package/dist/chunks/{DashboardPage-CUZ80NGV.js → DashboardPage-CKHqWrdS.js} +3 -3
  58. package/dist/chunks/{DashboardPage-CUZ80NGV.js.map → DashboardPage-CKHqWrdS.js.map} +1 -1
  59. package/dist/chunks/{DashboardPage-CaNOAstg.js → DashboardPage-COmc9b__.js} +3 -3
  60. package/dist/chunks/{DashboardPage-CaNOAstg.js.map → DashboardPage-COmc9b__.js.map} +1 -1
  61. package/dist/chunks/{DashboardPage-B48_rQFi.js → DashboardPage-CfKZHiSj.js} +2 -2
  62. package/dist/chunks/{DashboardPage-B48_rQFi.js.map → DashboardPage-CfKZHiSj.js.map} +1 -1
  63. package/dist/chunks/{DashboardPage-CUZV1J9t.js → DashboardPage-CwEZZ3jx.js} +2 -2
  64. package/dist/chunks/{DashboardPage-CUZV1J9t.js.map → DashboardPage-CwEZZ3jx.js.map} +1 -1
  65. package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js → EscalationConfigPage--7lgZ0kJ.js} +2 -2
  66. package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js.map → EscalationConfigPage--7lgZ0kJ.js.map} +1 -1
  67. package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js → EscalationConfigPage-DPyiBcqV.js} +2 -2
  68. package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js.map → EscalationConfigPage-DPyiBcqV.js.map} +1 -1
  69. package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js → ForceChangePasswordPage-BE-6umub.js} +2 -2
  70. package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js.map → ForceChangePasswordPage-BE-6umub.js.map} +1 -1
  71. package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js → ForceChangePasswordPage-CnsYoWmV.js} +2 -2
  72. package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js.map → ForceChangePasswordPage-CnsYoWmV.js.map} +1 -1
  73. package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js → ForgotPasswordPage-CSq4DnFF.js} +2 -2
  74. package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js.map → ForgotPasswordPage-CSq4DnFF.js.map} +1 -1
  75. package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js → ForgotPasswordPage-DZLVolAC.js} +2 -2
  76. package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js.map → ForgotPasswordPage-DZLVolAC.js.map} +1 -1
  77. package/dist/chunks/{GroupDetailPage-DFBvVO1S.js → GroupDetailPage-Bf9Wb_2j.js} +5 -5
  78. package/dist/chunks/{GroupDetailPage-DFBvVO1S.js.map → GroupDetailPage-Bf9Wb_2j.js.map} +1 -1
  79. package/dist/chunks/{GroupDetailPage-B2FkKrGG.js → GroupDetailPage-R-hf3rJ7.js} +2 -2
  80. package/dist/chunks/{GroupDetailPage-B2FkKrGG.js.map → GroupDetailPage-R-hf3rJ7.js.map} +1 -1
  81. package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js → MyAccessRequestsPage-BIisvWM6.js} +2 -2
  82. package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js.map → MyAccessRequestsPage-BIisvWM6.js.map} +1 -1
  83. package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js → MyAccessRequestsPage-BLSV7Tbx.js} +2 -2
  84. package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js.map → MyAccessRequestsPage-BLSV7Tbx.js.map} +1 -1
  85. package/dist/chunks/{MyTenantsPage-BEcYYdGR.js → MyTenantsPage-D-7k9CP1.js} +3 -3
  86. package/dist/chunks/{MyTenantsPage-BEcYYdGR.js.map → MyTenantsPage-D-7k9CP1.js.map} +1 -1
  87. package/dist/chunks/{MyTenantsPage-D9f85zjF.js → MyTenantsPage-DqGW6aDt.js} +2 -2
  88. package/dist/chunks/{MyTenantsPage-D9f85zjF.js.map → MyTenantsPage-DqGW6aDt.js.map} +1 -1
  89. package/dist/chunks/{MyTicketsPage-DJR8h6y1.js → MyTicketsPage--DgDsnZA.js} +2 -2
  90. package/dist/chunks/{MyTicketsPage-DJR8h6y1.js.map → MyTicketsPage--DgDsnZA.js.map} +1 -1
  91. package/dist/chunks/{MyTicketsPage-DiOUExKJ.js → MyTicketsPage-CqJ3Aqob.js} +2 -2
  92. package/dist/chunks/{MyTicketsPage-DiOUExKJ.js.map → MyTicketsPage-CqJ3Aqob.js.map} +1 -1
  93. package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js → NavigationAppsPage-Bebis_RT.js} +2 -2
  94. package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js.map → NavigationAppsPage-Bebis_RT.js.map} +1 -1
  95. package/dist/chunks/{NavigationAppsPage-If7tmCFY.js → NavigationAppsPage-THNPOAjv.js} +2 -2
  96. package/dist/chunks/{NavigationAppsPage-If7tmCFY.js.map → NavigationAppsPage-THNPOAjv.js.map} +1 -1
  97. package/dist/chunks/{NotificationsPage-C29Lln5o.js → NotificationsPage-CAbNW_Cn.js} +2 -2
  98. package/dist/chunks/{NotificationsPage-C29Lln5o.js.map → NotificationsPage-CAbNW_Cn.js.map} +1 -1
  99. package/dist/chunks/{NotificationsPage-BiaLRb0s.js → NotificationsPage-DxwizUhL.js} +2 -2
  100. package/dist/chunks/{NotificationsPage-BiaLRb0s.js.map → NotificationsPage-DxwizUhL.js.map} +1 -1
  101. package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js → OnboardingWizardPage-C6HlbJ3K.js} +2 -2
  102. package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js.map → OnboardingWizardPage-C6HlbJ3K.js.map} +1 -1
  103. package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js → OnboardingWizardPage-CyC2zONO.js} +2 -2
  104. package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js.map → OnboardingWizardPage-CyC2zONO.js.map} +1 -1
  105. package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js → PermissionDetailPage-BDHiNgky.js} +2 -2
  106. package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js.map → PermissionDetailPage-BDHiNgky.js.map} +1 -1
  107. package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js → PermissionDetailPage-C5K17ydY.js} +2 -2
  108. package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js.map → PermissionDetailPage-C5K17ydY.js.map} +1 -1
  109. package/dist/chunks/{PermissionsPage-l0PnY-EE.js → PermissionsPage-COI5LJPo.js} +2 -2
  110. package/dist/chunks/{PermissionsPage-l0PnY-EE.js.map → PermissionsPage-COI5LJPo.js.map} +1 -1
  111. package/dist/chunks/{PermissionsPage-DLy9U3P3.js → PermissionsPage-CkOwH2_d.js} +2 -2
  112. package/dist/chunks/{PermissionsPage-DLy9U3P3.js.map → PermissionsPage-CkOwH2_d.js.map} +1 -1
  113. package/dist/chunks/{PortalDashboardPage-DFBx38-x.js → PortalDashboardPage-CoEC4CmC.js} +2 -2
  114. package/dist/chunks/{PortalDashboardPage-DFBx38-x.js.map → PortalDashboardPage-CoEC4CmC.js.map} +1 -1
  115. package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js → PortalDashboardPage-DrYymEf-.js} +2 -2
  116. package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js.map → PortalDashboardPage-DrYymEf-.js.map} +1 -1
  117. package/dist/chunks/{PreferencesPage-BBu8yZQB.js → PreferencesPage-CJRaU3ba.js} +2 -2
  118. package/dist/chunks/{PreferencesPage-BBu8yZQB.js.map → PreferencesPage-CJRaU3ba.js.map} +1 -1
  119. package/dist/chunks/{PreferencesPage-B81MsNV1.js → PreferencesPage-Cqr9mAab.js} +2 -2
  120. package/dist/chunks/{PreferencesPage-B81MsNV1.js.map → PreferencesPage-Cqr9mAab.js.map} +1 -1
  121. package/dist/chunks/{ProfilePage-DDrl10zj.js → ProfilePage-BZVpg6-l.js} +2 -2
  122. package/dist/chunks/{ProfilePage-DDrl10zj.js.map → ProfilePage-BZVpg6-l.js.map} +1 -1
  123. package/dist/chunks/{ProfilePage-DPoXwdnc.js → ProfilePage-Cu_FITeL.js} +2 -2
  124. package/dist/chunks/{ProfilePage-DPoXwdnc.js.map → ProfilePage-Cu_FITeL.js.map} +1 -1
  125. package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js → ReferencesManagementPage-DUlVk9Ps.js} +3 -3
  126. package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js.map → ReferencesManagementPage-DUlVk9Ps.js.map} +1 -1
  127. package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js → ReferencesManagementPage-ZCuYtqd7.js} +2 -2
  128. package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js.map → ReferencesManagementPage-ZCuYtqd7.js.map} +1 -1
  129. package/dist/chunks/{RegisterPage-CiQib3-6.js → RegisterPage-C4xmVwh9.js} +2 -2
  130. package/dist/chunks/{RegisterPage-CiQib3-6.js.map → RegisterPage-C4xmVwh9.js.map} +1 -1
  131. package/dist/chunks/{RegisterPage-bXCcJD88.js → RegisterPage-DGyzoIHT.js} +2 -2
  132. package/dist/chunks/{RegisterPage-bXCcJD88.js.map → RegisterPage-DGyzoIHT.js.map} +1 -1
  133. package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js → ResetPasswordPage-DqDD6VPR.js} +2 -2
  134. package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js.map → ResetPasswordPage-DqDD6VPR.js.map} +1 -1
  135. package/dist/chunks/{ResetPasswordPage-CubPG3yv.js → ResetPasswordPage-Glu-aeqv.js} +2 -2
  136. package/dist/chunks/{ResetPasswordPage-CubPG3yv.js.map → ResetPasswordPage-Glu-aeqv.js.map} +1 -1
  137. package/dist/chunks/{ResolutionModal-Bg7XZmR1.js → ResolutionModal-CxjANAOP.js} +2 -2
  138. package/dist/chunks/{ResolutionModal-Bg7XZmR1.js.map → ResolutionModal-CxjANAOP.js.map} +1 -1
  139. package/dist/chunks/{ResolutionModal-DqRk_T0n.js → ResolutionModal-Duat18qV.js} +2 -2
  140. package/dist/chunks/{ResolutionModal-DqRk_T0n.js.map → ResolutionModal-Duat18qV.js.map} +1 -1
  141. package/dist/chunks/{RoleDetailPage-Blau6_4c.js → RoleDetailPage-BQffUSnt.js} +3 -3
  142. package/dist/chunks/{RoleDetailPage-Blau6_4c.js.map → RoleDetailPage-BQffUSnt.js.map} +1 -1
  143. package/dist/chunks/{RoleDetailPage-CiRVxxIP.js → RoleDetailPage-JTm5lD1_.js} +2 -2
  144. package/dist/chunks/{RoleDetailPage-CiRVxxIP.js.map → RoleDetailPage-JTm5lD1_.js.map} +1 -1
  145. package/dist/chunks/{RolesPage-Pm-RN3lP.js → RolesPage-B9rRzciI.js} +2 -2
  146. package/dist/chunks/{RolesPage-Pm-RN3lP.js.map → RolesPage-B9rRzciI.js.map} +1 -1
  147. package/dist/chunks/{RolesPage-Cb8joqdJ.js → RolesPage-BN8_zMOC.js} +2 -2
  148. package/dist/chunks/{RolesPage-Cb8joqdJ.js.map → RolesPage-BN8_zMOC.js.map} +1 -1
  149. package/dist/chunks/{SlaConfigPage-B86McKM6.js → SlaConfigPage-B7kZNig4.js} +2 -2
  150. package/dist/chunks/{SlaConfigPage-B86McKM6.js.map → SlaConfigPage-B7kZNig4.js.map} +1 -1
  151. package/dist/chunks/{SlaConfigPage-BY7gvYU6.js → SlaConfigPage-okvZfA_K.js} +2 -2
  152. package/dist/chunks/{SlaConfigPage-BY7gvYU6.js.map → SlaConfigPage-okvZfA_K.js.map} +1 -1
  153. package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js → SupportPermissionsPage-DGAPqJbl.js} +2 -2
  154. package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js.map → SupportPermissionsPage-DGAPqJbl.js.map} +1 -1
  155. package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js → SupportPermissionsPage-Dg_wLOme.js} +2 -2
  156. package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js.map → SupportPermissionsPage-Dg_wLOme.js.map} +1 -1
  157. package/dist/chunks/{TemplatesPage-BDguJ401.js → TemplatesPage-DT9fhlAU.js} +2 -2
  158. package/dist/chunks/{TemplatesPage-BDguJ401.js.map → TemplatesPage-DT9fhlAU.js.map} +1 -1
  159. package/dist/chunks/{TemplatesPage-DdnGgioU.js → TemplatesPage-DiEk538p.js} +2 -2
  160. package/dist/chunks/{TemplatesPage-DdnGgioU.js.map → TemplatesPage-DiEk538p.js.map} +1 -1
  161. package/dist/chunks/{TenantCard-ffwWsgFQ.js → TenantCard-BbSYk9_Z.js} +2 -2
  162. package/dist/chunks/{TenantCard-ffwWsgFQ.js.map → TenantCard-BbSYk9_Z.js.map} +1 -1
  163. package/dist/chunks/{TenantCard-CUjb6og9.js → TenantCard-CEkiKxcZ.js} +2 -2
  164. package/dist/chunks/{TenantCard-CUjb6og9.js.map → TenantCard-CEkiKxcZ.js.map} +1 -1
  165. package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js → TenantScopeSelector-BWfYxvEa.js} +2 -2
  166. package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js.map → TenantScopeSelector-BWfYxvEa.js.map} +1 -1
  167. package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js → TenantScopeSelector-D-BKgQPV.js} +2 -2
  168. package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js.map → TenantScopeSelector-D-BKgQPV.js.map} +1 -1
  169. package/dist/chunks/{TicketDetailPage-GOh9GX7E.js → TicketDetailPage-C1mNS9Up.js} +2 -2
  170. package/dist/chunks/{TicketDetailPage-GOh9GX7E.js.map → TicketDetailPage-C1mNS9Up.js.map} +1 -1
  171. package/dist/chunks/{TicketDetailPage-Du8WMyqf.js → TicketDetailPage-ieVDRh42.js} +2 -2
  172. package/dist/chunks/{TicketDetailPage-Du8WMyqf.js.map → TicketDetailPage-ieVDRh42.js.map} +1 -1
  173. package/dist/chunks/{TicketsPage-Bqd6moQy.js → TicketsPage-CnuWsnIW.js} +2 -2
  174. package/dist/chunks/{TicketsPage-Bqd6moQy.js.map → TicketsPage-CnuWsnIW.js.map} +1 -1
  175. package/dist/chunks/{TicketsPage-WdU4Bb7M.js → TicketsPage-jjyY15_D.js} +2 -2
  176. package/dist/chunks/{TicketsPage-WdU4Bb7M.js.map → TicketsPage-jjyY15_D.js.map} +1 -1
  177. package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js → UserCreateTicketPage-B8Tvf-ag.js} +2 -2
  178. package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js.map → UserCreateTicketPage-B8Tvf-ag.js.map} +1 -1
  179. package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js → UserCreateTicketPage-DnOsDlfO.js} +2 -2
  180. package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js.map → UserCreateTicketPage-DnOsDlfO.js.map} +1 -1
  181. package/dist/chunks/{UserDashboardPage-BP5WeXPS.js → UserDashboardPage-BrtkJ-NB.js} +2 -2
  182. package/dist/chunks/{UserDashboardPage-BP5WeXPS.js.map → UserDashboardPage-BrtkJ-NB.js.map} +1 -1
  183. package/dist/chunks/{UserDashboardPage-B53C8fUq.js → UserDashboardPage-KLB5CQP5.js} +2 -2
  184. package/dist/chunks/{UserDashboardPage-B53C8fUq.js.map → UserDashboardPage-KLB5CQP5.js.map} +1 -1
  185. package/dist/chunks/{UserDetailPage-B110bmGX.js → UserDetailPage-U7smBQoF.js} +5 -5
  186. package/dist/chunks/{UserDetailPage-B110bmGX.js.map → UserDetailPage-U7smBQoF.js.map} +1 -1
  187. package/dist/chunks/{UserDetailPage-CV2VCE46.js → UserDetailPage-_J6lcKAU.js} +2 -2
  188. package/dist/chunks/{UserDetailPage-CV2VCE46.js.map → UserDetailPage-_J6lcKAU.js.map} +1 -1
  189. package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js → UserTicketDetailPage-CWoYQgH-.js} +2 -2
  190. package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js.map → UserTicketDetailPage-CWoYQgH-.js.map} +1 -1
  191. package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js → UserTicketDetailPage-DkufSlvZ.js} +2 -2
  192. package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js.map → UserTicketDetailPage-DkufSlvZ.js.map} +1 -1
  193. package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js → UsersGroupsPage-C38s2-Rq.js} +3 -3
  194. package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js.map → UsersGroupsPage-C38s2-Rq.js.map} +1 -1
  195. package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js → UsersGroupsPage-Dq3rAteo.js} +2 -2
  196. package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js.map → UsersGroupsPage-Dq3rAteo.js.map} +1 -1
  197. package/dist/chunks/{UsersPage-Bg7033pp.js → UsersPage-B5C5KEUR.js} +2 -2
  198. package/dist/chunks/{UsersPage-Bg7033pp.js.map → UsersPage-B5C5KEUR.js.map} +1 -1
  199. package/dist/chunks/{UsersPage-TYAfwPY1.js → UsersPage-CXC9Hvq6.js} +2 -2
  200. package/dist/chunks/{UsersPage-TYAfwPY1.js.map → UsersPage-CXC9Hvq6.js.map} +1 -1
  201. package/dist/chunks/{accessRequestsApi-DZeDvzwv.js → accessRequestsApi-B-4TJ5_U.js} +2 -2
  202. package/dist/chunks/{accessRequestsApi-DZeDvzwv.js.map → accessRequestsApi-B-4TJ5_U.js.map} +1 -1
  203. package/dist/chunks/{accessRequestsApi-ZXFPCid2.js → accessRequestsApi-DZSfThpd.js} +2 -2
  204. package/dist/chunks/{accessRequestsApi-ZXFPCid2.js.map → accessRequestsApi-DZSfThpd.js.map} +1 -1
  205. package/dist/chunks/{aiApi-CsH8DXgs.js → aiApi-B20Teu2v.js} +2 -2
  206. package/dist/chunks/{aiApi-CsH8DXgs.js.map → aiApi-B20Teu2v.js.map} +1 -1
  207. package/dist/chunks/{aiApi-CVPzFTXa.js → aiApi-DMGz-RPM.js} +2 -2
  208. package/dist/chunks/{aiApi-CVPzFTXa.js.map → aiApi-DMGz-RPM.js.map} +1 -1
  209. package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js → applicationAnalyticsApi-Bwa75Fzd.js} +2 -2
  210. package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js.map → applicationAnalyticsApi-Bwa75Fzd.js.map} +1 -1
  211. package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js → applicationAnalyticsApi-CLBqRPfN.js} +2 -2
  212. package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js.map → applicationAnalyticsApi-CLBqRPfN.js.map} +1 -1
  213. package/dist/chunks/{groupsApi-BgCk2fsp.js → groupsApi-QzXI-5xu.js} +2 -2
  214. package/dist/chunks/{groupsApi-BgCk2fsp.js.map → groupsApi-QzXI-5xu.js.map} +1 -1
  215. package/dist/chunks/{groupsApi-BIbG665N.js → groupsApi-hB9kSWEd.js} +2 -2
  216. package/dist/chunks/{groupsApi-BIbG665N.js.map → groupsApi-hB9kSWEd.js.map} +1 -1
  217. package/dist/chunks/{index-Cb3LotuT.js → index--NGcBYUu.js} +3 -3
  218. package/dist/chunks/{index-Cb3LotuT.js.map → index--NGcBYUu.js.map} +1 -1
  219. package/dist/chunks/{index-C33zcyF4.js → index--aPwOFjF.js} +2 -2
  220. package/dist/chunks/{index-C33zcyF4.js.map → index--aPwOFjF.js.map} +1 -1
  221. package/dist/chunks/{index-sMr9qND_.js → index-0VrOtwP0.js} +2 -2
  222. package/dist/chunks/{index-sMr9qND_.js.map → index-0VrOtwP0.js.map} +1 -1
  223. package/dist/chunks/{index-DDKetfKq.js → index-37U271aw.js} +2 -2
  224. package/dist/chunks/{index-DDKetfKq.js.map → index-37U271aw.js.map} +1 -1
  225. package/dist/chunks/{index-B9fS7ir6.js → index-B7qZTuQ-.js} +2 -2
  226. package/dist/chunks/{index-B9fS7ir6.js.map → index-B7qZTuQ-.js.map} +1 -1
  227. package/dist/chunks/{index-CdjBY7L8.js → index-Bedzmqr-.js} +2 -2
  228. package/dist/chunks/{index-CdjBY7L8.js.map → index-Bedzmqr-.js.map} +1 -1
  229. package/dist/chunks/{index-CHG_O1fS.js → index-Betxo5g5.js} +2 -2
  230. package/dist/chunks/{index-CHG_O1fS.js.map → index-Betxo5g5.js.map} +1 -1
  231. package/dist/chunks/{index-jiGu-H8x.js → index-BmaJz475.js} +2 -2
  232. package/dist/chunks/{index-jiGu-H8x.js.map → index-BmaJz475.js.map} +1 -1
  233. package/dist/chunks/{index-C53JoVNk.js → index-Buhqag3v.js} +2 -2
  234. package/dist/chunks/{index-C53JoVNk.js.map → index-Buhqag3v.js.map} +1 -1
  235. package/dist/chunks/{index-DO0Rw7hX.js → index-C3VxlfKq.js} +2 -2
  236. package/dist/chunks/{index-DO0Rw7hX.js.map → index-C3VxlfKq.js.map} +1 -1
  237. package/dist/chunks/{index-CSQ60fpG.js → index-CgpRo8Oe.js} +2 -2
  238. package/dist/chunks/{index-CSQ60fpG.js.map → index-CgpRo8Oe.js.map} +1 -1
  239. package/dist/chunks/{index-B-e-ELsf.js → index-DOY0w8Iu.js} +8 -8
  240. package/dist/chunks/{index-B-e-ELsf.js.map → index-DOY0w8Iu.js.map} +1 -1
  241. package/dist/chunks/{index-D2REDIRX.js → index-DwuvIOrQ.js} +2 -2
  242. package/dist/chunks/{index-D2REDIRX.js.map → index-DwuvIOrQ.js.map} +1 -1
  243. package/dist/chunks/{index-DCcl7Qof.js → index-DzedSLdI.js} +2 -2
  244. package/dist/chunks/{index-DCcl7Qof.js.map → index-DzedSLdI.js.map} +1 -1
  245. package/dist/chunks/{index-2wUhd9Lu.js → index-IgLVXPg8.js} +10 -10
  246. package/dist/chunks/index-IgLVXPg8.js.map +1 -0
  247. package/dist/chunks/{index-CwSaRXXg.js → index-lpIzhufD.js} +1916 -1900
  248. package/dist/chunks/index-lpIzhufD.js.map +1 -0
  249. package/dist/chunks/{index-Cuwn2q-f.js → index-mLUKwbGl.js} +4 -4
  250. package/dist/chunks/{index-Cuwn2q-f.js.map → index-mLUKwbGl.js.map} +1 -1
  251. package/dist/chunks/{index-B0mk2tNY.js → index-tO6MMIFB.js} +2 -2
  252. package/dist/chunks/{index-B0mk2tNY.js.map → index-tO6MMIFB.js.map} +1 -1
  253. package/dist/chunks/{tenantIconMap-BpNANQ5s.js → tenantIconMap-BQD9byc8.js} +2 -2
  254. package/dist/chunks/{tenantIconMap-BpNANQ5s.js.map → tenantIconMap-BQD9byc8.js.map} +1 -1
  255. package/dist/chunks/{tenantIconMap-DtdUgvJO.js → tenantIconMap-CTMuSt18.js} +2 -2
  256. package/dist/chunks/{tenantIconMap-DtdUgvJO.js.map → tenantIconMap-CTMuSt18.js.map} +1 -1
  257. package/dist/chunks/{ticketingApi-Bu4rKwLl.js → ticketingApi-BNIdox5t.js} +2 -2
  258. package/dist/chunks/{ticketingApi-Bu4rKwLl.js.map → ticketingApi-BNIdox5t.js.map} +1 -1
  259. package/dist/chunks/{ticketingApi-r4Avm9iS.js → ticketingApi-J0vC_t7r.js} +2 -2
  260. package/dist/chunks/{ticketingApi-r4Avm9iS.js.map → ticketingApi-J0vC_t7r.js.map} +1 -1
  261. package/dist/chunks/{useAccessRequests-B9bF4swg.js → useAccessRequests-DCNNLnxk.js} +3 -3
  262. package/dist/chunks/{useAccessRequests-B9bF4swg.js.map → useAccessRequests-DCNNLnxk.js.map} +1 -1
  263. package/dist/chunks/{useAccessRequests-JyPUX3Om.js → useAccessRequests-DT7X4FAK.js} +2 -2
  264. package/dist/chunks/{useAccessRequests-JyPUX3Om.js.map → useAccessRequests-DT7X4FAK.js.map} +1 -1
  265. package/dist/chunks/{useUserAccessRequests-DjPQenC2.js → useUserAccessRequests-BYbmG4c7.js} +2 -2
  266. package/dist/chunks/{useUserAccessRequests-DjPQenC2.js.map → useUserAccessRequests-BYbmG4c7.js.map} +1 -1
  267. package/dist/chunks/{useUserAccessRequests-BB6FHW14.js → useUserAccessRequests-CylKxRN6.js} +2 -2
  268. package/dist/chunks/{useUserAccessRequests-BB6FHW14.js.map → useUserAccessRequests-CylKxRN6.js.map} +1 -1
  269. package/dist/hooks/useCollapsibleState.d.ts +5 -2
  270. package/dist/hooks/useCollapsibleState.d.ts.map +1 -1
  271. package/dist/i18n/config.d.ts +1 -0
  272. package/dist/i18n/config.d.ts.map +1 -1
  273. package/dist/main.d.ts +0 -1
  274. package/dist/main.d.ts.map +1 -1
  275. package/dist/smartstack.cjs +1 -1
  276. package/dist/smartstack.js +1 -1
  277. package/dist/utils/permissions.d.ts.map +1 -1
  278. package/package.json +1 -1
  279. package/dist/chunks/index-2wUhd9Lu.js.map +0 -1
  280. package/dist/chunks/index-CwSaRXXg.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ApplicationDetailPage-BYJ2YMPq.js","sources":["../../src/utils/renderLucideIcon.tsx","../../src/hooks/useApplicationDetail.ts","../../src/hooks/useApplicationModules.ts","../../src/hooks/useApplicationPermissions.ts","../../src/hooks/useApplicationPublication.ts","../../src/components/platform/administration/applications/ApplicationInfoTab.tsx","../../src/components/ui/SortableList.tsx","../../src/components/platform/administration/applications/ApplicationModulesTab.tsx","../../src/components/platform/administration/applications/ApplicationPermissionsTab.tsx","../../src/components/platform/administration/applications/ApplicationAccessTab.tsx","../../src/components/platform/administration/applications/ApplicationPublicationTab.tsx","../../src/pages/platform/administration/applications/ApplicationDetailPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport * as LucideIcons from 'lucide-react';\r\nimport type { LucideIcon } from 'lucide-react';\r\n\r\n/**\r\n * Renders a Lucide icon by name string or LucideIcon component.\r\n * Returns null if the icon name is invalid or null.\r\n */\r\nexport function renderLucideIcon(\r\n icon: LucideIcon | string | null | undefined,\r\n className = 'w-4 h-4',\r\n): ReactElement | null {\r\n if (!icon) return null;\r\n\r\n if (typeof icon === 'string') {\r\n const icons = LucideIcons as unknown as Record<string, LucideIcon>;\r\n const IconComponent = icons[icon];\r\n if (!IconComponent) return null;\r\n return <IconComponent className={className} />;\r\n }\r\n\r\n const Icon = icon;\r\n return <Icon className={className} />;\r\n}\r\n","import { useState, useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n adminApi,\r\n type ApplicationDetailDto,\r\n type UpdateApplicationRequest,\r\n} from '@/services/api/adminApi';\r\n\r\nexport interface ApplicationFormData {\r\n label: string;\r\n description: string;\r\n icon: string;\r\n route: string;\r\n displayOrder: number;\r\n}\r\n\r\nexport interface UseApplicationDetailReturn {\r\n application: ApplicationDetailDto | null;\r\n loading: boolean;\r\n saving: boolean;\r\n error: string | null;\r\n success: string | null;\r\n formData: ApplicationFormData;\r\n setFormData: React.Dispatch<React.SetStateAction<ApplicationFormData>>;\r\n setError: (error: string | null) => void;\r\n setSuccess: (success: string | null) => void;\r\n loadApplication: (appId: string) => Promise<void>;\r\n handleSaveInfo: (appId: string, data: ApplicationFormData) => Promise<void>;\r\n handleToggleStatus: (appId: string) => Promise<void>;\r\n}\r\n\r\nexport function useApplicationDetail(): UseApplicationDetailReturn {\r\n const { t } = useTranslation('admin');\r\n\r\n const [application, setApplication] = useState<ApplicationDetailDto | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n const [saving, setSaving] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n\r\n const [formData, setFormData] = useState<ApplicationFormData>({\r\n label: '',\r\n description: '',\r\n icon: '',\r\n route: '',\r\n displayOrder: 0,\r\n });\r\n\r\n const loadApplication = useCallback(async (appId: string) => {\r\n if (!appId) return;\r\n\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const data = await adminApi.applications.getById(appId);\r\n setApplication(data);\r\n setFormData({\r\n label: data.label,\r\n description: data.description || '',\r\n icon: data.icon || '',\r\n route: data.route || '',\r\n displayOrder: data.displayOrder,\r\n });\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('applicationDetail.errors.loadFailed'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n const handleSaveInfo = useCallback(async (appId: string, data: ApplicationFormData) => {\r\n if (!appId || !application) return;\r\n\r\n setSaving(true);\r\n setError(null);\r\n setSuccess(null);\r\n\r\n try {\r\n const updateData: UpdateApplicationRequest = {\r\n label: data.label,\r\n description: data.description || undefined,\r\n icon: data.icon || undefined,\r\n route: data.route || undefined,\r\n displayOrder: data.displayOrder,\r\n };\r\n\r\n await adminApi.applications.update(appId, updateData);\r\n setSuccess(t('applicationDetail.success.saved'));\r\n await loadApplication(appId);\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('applicationDetail.errors.saveFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [application, t, loadApplication]);\r\n\r\n const handleToggleStatus = useCallback(async (appId: string) => {\r\n if (!appId || !application) return;\r\n\r\n setSaving(true);\r\n setError(null);\r\n setSuccess(null);\r\n\r\n try {\r\n if (application.isActive) {\r\n await adminApi.applications.deactivate(appId);\r\n } else {\r\n await adminApi.applications.activate(appId);\r\n }\r\n\r\n setSuccess(\r\n application.isActive\r\n ? t('applicationDetail.success.deactivated')\r\n : t('applicationDetail.success.activated')\r\n );\r\n await loadApplication(appId);\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('applicationDetail.errors.toggleFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [application, t, loadApplication]);\r\n\r\n return {\r\n application,\r\n loading,\r\n saving,\r\n error,\r\n success,\r\n formData,\r\n setFormData,\r\n setError,\r\n setSuccess,\r\n loadApplication,\r\n handleSaveInfo,\r\n handleToggleStatus,\r\n };\r\n}\r\n","import { useState, useCallback } from 'react';\r\nimport {\r\n adminApi,\r\n type ApplicationModuleDto,\r\n type ModuleSectionDto,\r\n} from '@/services/api/adminApi';\r\n\r\nexport interface ModuleFormData {\r\n code: string;\r\n label: string;\r\n description: string;\r\n icon: string;\r\n route: string;\r\n displayOrder: number;\r\n}\r\n\r\nexport interface UseApplicationModulesReturn {\r\n expandedModules: Set<string>;\r\n moduleSections: Map<string, ModuleSectionDto[]>;\r\n loadingSections: Set<string>;\r\n reordering: boolean;\r\n editingModule: ApplicationModuleDto | null;\r\n moduleFormData: ModuleFormData;\r\n showModuleForm: boolean;\r\n toggleModuleExpand: (appId: string, moduleId: string) => Promise<void>;\r\n handleSaveModule: (appId: string, moduleId: string, data: ModuleFormData) => Promise<void>;\r\n handleModulesReorder: (appId: string, modules: (ApplicationModuleDto & { id: string })[]) => Promise<void>;\r\n handleSectionsReorder: (appId: string, moduleId: string, sections: ModuleSectionDto[]) => Promise<void>;\r\n startEditModule: (module: ApplicationModuleDto) => void;\r\n resetModuleForm: (moduleCount?: number) => void;\r\n setShowModuleForm: (show: boolean) => void;\r\n setEditingModule: (module: ApplicationModuleDto | null) => void;\r\n setModuleFormData: (data: ModuleFormData) => void;\r\n}\r\n\r\nexport function useApplicationModules(): UseApplicationModulesReturn {\r\n const [expandedModules, setExpandedModules] = useState<Set<string>>(new Set());\r\n const [moduleSections, setModuleSections] = useState<Map<string, ModuleSectionDto[]>>(new Map());\r\n const [loadingSections, setLoadingSections] = useState<Set<string>>(new Set());\r\n const [reordering, setReordering] = useState(false);\r\n\r\n const [editingModule, setEditingModule] = useState<ApplicationModuleDto | null>(null);\r\n const [moduleFormData, setModuleFormData] = useState<ModuleFormData>({\r\n code: '',\r\n label: '',\r\n description: '',\r\n icon: '',\r\n route: '',\r\n displayOrder: 0,\r\n });\r\n const [showModuleForm, setShowModuleForm] = useState(false);\r\n\r\n const toggleModuleExpand = useCallback(async (appId: string, moduleId: string) => {\r\n const isExpanding = !expandedModules.has(moduleId);\r\n\r\n setExpandedModules(prev => {\r\n const newSet = new Set(prev);\r\n if (newSet.has(moduleId)) {\r\n newSet.delete(moduleId);\r\n } else {\r\n newSet.add(moduleId);\r\n }\r\n return newSet;\r\n });\r\n\r\n // Load sections if expanding and not already loaded\r\n if (isExpanding && !moduleSections.has(moduleId)) {\r\n setLoadingSections(prev => new Set(prev).add(moduleId));\r\n try {\r\n const sections = await adminApi.applications.getModuleSections(appId, moduleId);\r\n setModuleSections(prev => new Map(prev).set(moduleId, sections));\r\n } catch (err) {\r\n console.error('Failed to load sections:', err);\r\n } finally {\r\n setLoadingSections(prev => {\r\n const newSet = new Set(prev);\r\n newSet.delete(moduleId);\r\n return newSet;\r\n });\r\n }\r\n }\r\n }, [expandedModules, moduleSections]);\r\n\r\n const handleSaveModule = useCallback(async (appId: string, moduleId: string, data: ModuleFormData) => {\r\n try {\r\n await adminApi.applications.updateModule(appId, moduleId, {\r\n label: data.label,\r\n description: data.description || undefined,\r\n icon: data.icon || undefined,\r\n route: data.route || undefined,\r\n displayOrder: data.displayOrder,\r\n });\r\n setShowModuleForm(false);\r\n setEditingModule(null);\r\n resetModuleForm();\r\n } catch (err) {\r\n console.error('Failed to save module:', err);\r\n throw err;\r\n }\r\n }, []);\r\n\r\n const handleModulesReorder = useCallback(async (appId: string, reorderedModules: (ApplicationModuleDto & { id: string })[]) => {\r\n // Optimistic update\r\n const newModules = reorderedModules.map((m, index) => ({ ...m, displayOrder: index }));\r\n\r\n setReordering(true);\r\n try {\r\n await adminApi.applications.reorderModules(appId, newModules.map((m, index) => ({ id: m.id, displayOrder: index })));\r\n } catch (err) {\r\n console.error('Failed to reorder modules:', err);\r\n throw err;\r\n } finally {\r\n setReordering(false);\r\n }\r\n }, []);\r\n\r\n const handleSectionsReorder = useCallback(async (appId: string, moduleId: string, reorderedSections: ModuleSectionDto[]) => {\r\n // Optimistic update\r\n const newSections = reorderedSections.map((s, index) => ({ ...s, displayOrder: index }));\r\n setModuleSections(prev => new Map(prev).set(moduleId, newSections));\r\n\r\n setReordering(true);\r\n try {\r\n await adminApi.applications.reorderSections(appId, moduleId, newSections.map((s, index) => ({ id: s.id, displayOrder: index })));\r\n } catch (err) {\r\n console.error('Failed to reorder sections:', err);\r\n // Reload sections on error\r\n try {\r\n const sections = await adminApi.applications.getModuleSections(appId, moduleId);\r\n setModuleSections(prev => new Map(prev).set(moduleId, sections));\r\n } catch (reloadErr) {\r\n console.error('Failed to reload sections:', reloadErr);\r\n }\r\n throw err;\r\n } finally {\r\n setReordering(false);\r\n }\r\n }, []);\r\n\r\n const startEditModule = useCallback((module: ApplicationModuleDto) => {\r\n setEditingModule(module);\r\n setModuleFormData({\r\n code: module.code,\r\n label: module.label,\r\n description: module.description || '',\r\n icon: module.icon || '',\r\n route: module.route || '',\r\n displayOrder: module.displayOrder,\r\n });\r\n setShowModuleForm(true);\r\n }, []);\r\n\r\n const resetModuleForm = useCallback((moduleCount?: number) => {\r\n setModuleFormData({\r\n code: '',\r\n label: '',\r\n description: '',\r\n icon: '',\r\n route: '',\r\n displayOrder: moduleCount || 0,\r\n });\r\n }, []);\r\n\r\n return {\r\n expandedModules,\r\n moduleSections,\r\n loadingSections,\r\n reordering,\r\n editingModule,\r\n moduleFormData,\r\n showModuleForm,\r\n toggleModuleExpand,\r\n handleSaveModule,\r\n handleModulesReorder,\r\n handleSectionsReorder,\r\n startEditModule,\r\n resetModuleForm,\r\n setShowModuleForm,\r\n setEditingModule,\r\n setModuleFormData,\r\n };\r\n}\r\n","import { useState, useCallback, useMemo } from 'react';\r\nimport { adminApi, type PermissionListDto, type RoleListDto, type MatrixRoleDto, type ApplicationDetailDto } from '@/services/api/adminApi';\r\n\r\nexport interface PermissionWithRoles {\r\n permission: PermissionListDto;\r\n roles: RoleListDto[];\r\n}\r\n\r\nexport interface RoleWithPermissions {\r\n role: RoleListDto;\r\n permissions: PermissionListDto[];\r\n}\r\n\r\nconst getPermissionWithRoles = (\r\n perm: PermissionListDto,\r\n matrixRoles: MatrixRoleDto[],\r\n allRoles: RoleListDto[]\r\n): PermissionWithRoles => {\r\n const rolesWithPerm = matrixRoles\r\n .filter(mr => mr.permissionIds.includes(perm.id))\r\n .map(mr => allRoles.find(r => r.id === mr.id)!)\r\n .filter(Boolean);\r\n return { permission: perm, roles: rolesWithPerm };\r\n};\r\n\r\nexport interface UseApplicationPermissionsReturn {\r\n roles: RoleListDto[];\r\n permissions: PermissionListDto[];\r\n permissionsWithRoles: PermissionWithRoles[];\r\n rolesWithAppAccess: RoleWithPermissions[];\r\n\r\n loadPermissionsData: (application: ApplicationDetailDto) => Promise<void>;\r\n loadRolesData: () => Promise<void>;\r\n}\r\n\r\nexport function useApplicationPermissions(): UseApplicationPermissionsReturn {\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [permissionsWithRoles, setPermissionsWithRoles] = useState<PermissionWithRoles[]>([]);\r\n\r\n const loadPermissionsData = useCallback(async (application: ApplicationDetailDto) => {\r\n try {\r\n const [matrix, allRoles] = await Promise.all([\r\n adminApi.permissions.getMatrix(),\r\n adminApi.roles.getAll(),\r\n ]);\r\n\r\n const appPermissionPrefix = `${application.code}.`.toLowerCase();\r\n const appPermissions = matrix.permissions.filter(p =>\r\n p.path.toLowerCase().startsWith(appPermissionPrefix)\r\n );\r\n\r\n setPermissions(appPermissions);\r\n setRoles(allRoles);\r\n\r\n const permWithRoles: PermissionWithRoles[] = appPermissions.map(perm =>\r\n getPermissionWithRoles(perm, matrix.roles, allRoles)\r\n );\r\n\r\n setPermissionsWithRoles(permWithRoles);\r\n } catch (err) {\r\n console.error('Failed to load permissions data:', err);\r\n throw err;\r\n }\r\n }, []);\r\n\r\n const loadRolesData = useCallback(async () => {\r\n try {\r\n const allRoles = await adminApi.roles.getAll();\r\n setRoles(allRoles);\r\n } catch (err) {\r\n console.error('Failed to load roles:', err);\r\n throw err;\r\n }\r\n }, []);\r\n\r\n const rolesWithAppAccess = useMemo<RoleWithPermissions[]>(() => {\r\n if (permissionsWithRoles.length === 0) return [];\r\n\r\n const roleAccessMap = new Map<string, { role: RoleListDto; permissions: PermissionListDto[] }>();\r\n\r\n permissionsWithRoles.forEach(({ permission, roles: permRoles }) => {\r\n permRoles.forEach(role => {\r\n if (!roleAccessMap.has(role.id)) {\r\n roleAccessMap.set(role.id, { role, permissions: [] });\r\n }\r\n roleAccessMap.get(role.id)!.permissions.push(permission);\r\n });\r\n });\r\n\r\n return Array.from(roleAccessMap.values()).sort((a, b) =>\r\n b.permissions.length - a.permissions.length\r\n );\r\n }, [permissionsWithRoles]);\r\n\r\n return {\r\n roles,\r\n permissions,\r\n permissionsWithRoles,\r\n rolesWithAppAccess,\r\n loadPermissionsData,\r\n loadRolesData,\r\n };\r\n}\r\n","import React, { useState, useCallback } from 'react';\r\nimport { adminApi } from '@/services/api/adminApi';\r\nimport type {\r\n ApplicationTenantDto,\r\n AvailableTenantForAppDto,\r\n ApplicationAccessLevel,\r\n BulkAssignTenantsRequest,\r\n} from '@/services/api/adminApi';\r\n\r\nconst updateModuleAssignment = (module: BulkModuleNode, moduleId: string): BulkModuleNode => {\r\n if (module.id !== moduleId) return module;\r\n const newIsAssigned = !module.isAssigned;\r\n return {\r\n ...module,\r\n isAssigned: newIsAssigned,\r\n sections: module.sections.map(s => ({ ...s, isAssigned: newIsAssigned })),\r\n };\r\n};\r\n\r\nconst updateSectionAssignment = (module: BulkModuleNode, moduleId: string, sectionId: string): BulkModuleNode => {\r\n if (module.id !== moduleId) return module;\r\n const newSections = module.sections.map(s =>\r\n s.id === sectionId ? { ...s, isAssigned: !s.isAssigned } : s\r\n );\r\n const allSectionsAssigned = newSections.every(s => s.isAssigned);\r\n return {\r\n ...module,\r\n isAssigned: allSectionsAssigned,\r\n sections: newSections,\r\n };\r\n};\r\n\r\nconst assignAllSections = (module: BulkModuleNode): BulkModuleNode => ({\r\n ...module,\r\n isAssigned: true,\r\n sections: module.sections.map(s => ({ ...s, isAssigned: true })),\r\n});\r\n\r\nconst clearAllSections = (module: BulkModuleNode): BulkModuleNode => ({\r\n ...module,\r\n isAssigned: false,\r\n sections: module.sections.map(s => ({ ...s, isAssigned: false })),\r\n});\r\n\r\n// Bulk operation interfaces\r\nexport interface BulkModuleNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n sections: BulkSectionNode[];\r\n}\r\n\r\nexport interface BulkSectionNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n}\r\n\r\nexport type BulkAccessMode = 'full' | 'custom';\r\n\r\nexport interface UseApplicationPublicationReturn {\r\n // State\r\n assignedTenants: ApplicationTenantDto[];\r\n availableTenants: AvailableTenantForAppDto[];\r\n showAssignModal: boolean;\r\n selectedTenantIds: string[];\r\n selectedAccessLevel: ApplicationAccessLevel;\r\n tenantSearch: string;\r\n showCustomizeDrawer: boolean;\r\n customizingTenant: ApplicationTenantDto | null;\r\n bulkAccessMode: BulkAccessMode;\r\n bulkModules: BulkModuleNode[];\r\n bulkExpandedModules: Set<string>;\r\n loadingBulkModules: boolean;\r\n isUpdateMode: boolean;\r\n updateMergeMode: 'merge' | 'replace';\r\n showConfirmRemovalDialog: boolean;\r\n pendingRemovals: { modules: number; sections: number };\r\n includePersonalTenants: boolean;\r\n isInDefaultPersonalTemplate: boolean;\r\n\r\n // Setters\r\n setAssignedTenants: React.Dispatch<React.SetStateAction<ApplicationTenantDto[]>>;\r\n setAvailableTenants: React.Dispatch<React.SetStateAction<AvailableTenantForAppDto[]>>;\r\n setShowAssignModal: React.Dispatch<React.SetStateAction<boolean>>;\r\n setSelectedTenantIds: React.Dispatch<React.SetStateAction<string[]>>;\r\n setSelectedAccessLevel: React.Dispatch<React.SetStateAction<ApplicationAccessLevel>>;\r\n setTenantSearch: React.Dispatch<React.SetStateAction<string>>;\r\n setShowCustomizeDrawer: React.Dispatch<React.SetStateAction<boolean>>;\r\n setCustomizingTenant: React.Dispatch<React.SetStateAction<ApplicationTenantDto | null>>;\r\n setBulkAccessMode: React.Dispatch<React.SetStateAction<BulkAccessMode>>;\r\n setBulkModules: React.Dispatch<React.SetStateAction<BulkModuleNode[]>>;\r\n setBulkExpandedModules: React.Dispatch<React.SetStateAction<Set<string>>>;\r\n setIsUpdateMode: React.Dispatch<React.SetStateAction<boolean>>;\r\n setUpdateMergeMode: React.Dispatch<React.SetStateAction<'merge' | 'replace'>>;\r\n setShowConfirmRemovalDialog: React.Dispatch<React.SetStateAction<boolean>>;\r\n setPendingRemovals: React.Dispatch<React.SetStateAction<{ modules: number; sections: number }>>;\r\n setIncludePersonalTenants: React.Dispatch<React.SetStateAction<boolean>>;\r\n\r\n // Publication operations\r\n loadPublicationData: (appId: string) => Promise<void>;\r\n loadBulkModules: (appId: string) => Promise<void>;\r\n\r\n // Bulk module operations\r\n toggleBulkModuleExpand: (moduleId: string) => void;\r\n toggleBulkModule: (moduleId: string) => void;\r\n toggleBulkSection: (moduleId: string, sectionId: string) => void;\r\n getBulkModuleCheckState: (module: BulkModuleNode) => 'checked' | 'unchecked' | 'indeterminate';\r\n getBulkStats: () => { totalModules: number; assignedModules: number; totalSections: number; assignedSections: number };\r\n selectAllBulkModules: () => void;\r\n clearBulkModules: () => void;\r\n\r\n // Tenant assignment operations\r\n toggleTenantSelection: (tenantId: string) => void;\r\n selectAllFilteredTenants: () => void;\r\n clearTenantSelection: () => void;\r\n\r\n // API operations\r\n handleAssignTenants: (appId: string, onSuccess?: () => void) => Promise<void>;\r\n handleUpdateTenants: (appId: string, onSuccess?: () => void) => Promise<void>;\r\n executeUpdateTenants: (appId: string, onSuccess?: () => void) => Promise<void>;\r\n handleRemoveTenant: (appId: string, tenantId: string, onSuccess?: () => void) => Promise<void>;\r\n handleUpdateAccessLevel: (appId: string, tenantId: string, accessLevel: ApplicationAccessLevel, onSuccess?: () => void) => Promise<void>;\r\n}\r\n\r\nexport function useApplicationPublication(): UseApplicationPublicationReturn {\r\n // Publication state\r\n const [assignedTenants, setAssignedTenants] = useState<ApplicationTenantDto[]>([]);\r\n const [availableTenants, setAvailableTenants] = useState<AvailableTenantForAppDto[]>([]);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [selectedTenantIds, setSelectedTenantIds] = useState<string[]>([]);\r\n const [selectedAccessLevel, setSelectedAccessLevel] = useState<ApplicationAccessLevel>('FullAccess');\r\n const [tenantSearch, setTenantSearch] = useState('');\r\n\r\n // Customize access drawer state\r\n const [showCustomizeDrawer, setShowCustomizeDrawer] = useState(false);\r\n const [customizingTenant, setCustomizingTenant] = useState<ApplicationTenantDto | null>(null);\r\n\r\n // Bulk customization state\r\n const [bulkAccessMode, setBulkAccessMode] = useState<BulkAccessMode>('full');\r\n const [bulkModules, setBulkModules] = useState<BulkModuleNode[]>([]);\r\n const [bulkExpandedModules, setBulkExpandedModules] = useState<Set<string>>(new Set());\r\n const [loadingBulkModules, setLoadingBulkModules] = useState(false);\r\n\r\n // Update mode state\r\n const [isUpdateMode, setIsUpdateMode] = useState(false);\r\n const [updateMergeMode, setUpdateMergeMode] = useState<'merge' | 'replace'>('merge');\r\n const [showConfirmRemovalDialog, setShowConfirmRemovalDialog] = useState(false);\r\n const [pendingRemovals, setPendingRemovals] = useState<{ modules: number; sections: number }>({ modules: 0, sections: 0 });\r\n\r\n // Personal tenant filter state\r\n const [includePersonalTenants, setIncludePersonalTenants] = useState(false);\r\n const [isInDefaultPersonalTemplate, setIsInDefaultPersonalTemplate] = useState(false);\r\n\r\n // Publication data loading\r\n const loadPublicationData = useCallback(async (appId: string) => {\r\n try {\r\n const [assigned, availableResponse] = await Promise.all([\r\n adminApi.applications.getTenants(appId),\r\n adminApi.applications.getAvailableTenants(appId),\r\n ]);\r\n setAssignedTenants(assigned);\r\n setAvailableTenants(availableResponse.tenants);\r\n setIsInDefaultPersonalTemplate(availableResponse.isInDefaultPersonalTemplate);\r\n } catch (err) {\r\n console.error('Failed to load publication data:', err);\r\n }\r\n }, []);\r\n\r\n // Load bulk modules for custom access mode\r\n const loadBulkModules = useCallback(async (appId: string) => {\r\n setLoadingBulkModules(true);\r\n try {\r\n const appModules = await adminApi.applications.getModules(appId);\r\n const moduleNodes: BulkModuleNode[] = [];\r\n\r\n for (const appModule of appModules) {\r\n const sections = await adminApi.applications.getModuleSections(appId, appModule.id);\r\n const sectionNodes: BulkSectionNode[] = sections.map(section => ({\r\n id: section.id,\r\n label: section.label,\r\n code: section.code,\r\n icon: section.icon,\r\n isAssigned: true,\r\n }));\r\n\r\n moduleNodes.push({\r\n id: appModule.id,\r\n label: appModule.label,\r\n code: appModule.code,\r\n icon: appModule.icon,\r\n isAssigned: true,\r\n sections: sectionNodes,\r\n });\r\n }\r\n\r\n setBulkModules(moduleNodes);\r\n } catch (err) {\r\n console.error('Failed to load bulk modules:', err);\r\n } finally {\r\n setLoadingBulkModules(false);\r\n }\r\n }, []);\r\n\r\n // Toggle bulk module expansion\r\n const toggleBulkModuleExpand = useCallback((moduleId: string) => {\r\n setBulkExpandedModules(prev => {\r\n const newSet = new Set(prev);\r\n if (newSet.has(moduleId)) {\r\n newSet.delete(moduleId);\r\n } else {\r\n newSet.add(moduleId);\r\n }\r\n return newSet;\r\n });\r\n }, []);\r\n\r\n // Toggle entire bulk module (all sections)\r\n const toggleBulkModule = useCallback((moduleId: string) => {\r\n setBulkModules(prev => prev.map(m => updateModuleAssignment(m, moduleId)));\r\n }, []);\r\n\r\n // Toggle bulk section within module\r\n const toggleBulkSection = useCallback((moduleId: string, sectionId: string) => {\r\n setBulkModules(prev => prev.map(m => updateSectionAssignment(m, moduleId, sectionId)));\r\n }, []);\r\n\r\n // Get checkbox state for bulk module (checked, unchecked, or indeterminate)\r\n const getBulkModuleCheckState = useCallback((module: BulkModuleNode): 'checked' | 'unchecked' | 'indeterminate' => {\r\n const assignedCount = module.sections.filter(s => s.isAssigned).length;\r\n if (assignedCount === 0) return 'unchecked';\r\n if (assignedCount === module.sections.length) return 'checked';\r\n return 'indeterminate';\r\n }, []);\r\n\r\n // Get statistics for bulk selection\r\n const getBulkStats = useCallback(() => {\r\n const totalModules = bulkModules.length;\r\n const assignedModules = bulkModules.filter(m => m.isAssigned || m.sections.some(s => s.isAssigned)).length;\r\n const totalSections = bulkModules.reduce((sum, m) => sum + m.sections.length, 0);\r\n const assignedSections = bulkModules.reduce((sum, m) => sum + m.sections.filter(s => s.isAssigned).length, 0);\r\n return { totalModules, assignedModules, totalSections, assignedSections };\r\n }, [bulkModules]);\r\n\r\n // Select all bulk modules\r\n const selectAllBulkModules = useCallback(() => {\r\n setBulkModules(prev => prev.map(m => assignAllSections(m)));\r\n }, []);\r\n\r\n // Clear all bulk module selections\r\n const clearBulkModules = useCallback(() => {\r\n setBulkModules(prev => prev.map(m => clearAllSections(m)));\r\n }, []);\r\n\r\n // Toggle tenant selection\r\n const toggleTenantSelection = useCallback((tenantId: string) => {\r\n setSelectedTenantIds(prev =>\r\n prev.includes(tenantId)\r\n ? prev.filter(id => id !== tenantId)\r\n : [...prev, tenantId]\r\n );\r\n }, []);\r\n\r\n // Select all filtered tenants (based on search and personal filter)\r\n const selectAllFilteredTenants = useCallback(() => {\r\n if (isUpdateMode) {\r\n const filteredIds = assignedTenants\r\n .filter(t => {\r\n const matchesSearch =\r\n t.tenantName.toLowerCase().includes(tenantSearch.toLowerCase()) ||\r\n t.tenantSlug.toLowerCase().includes(tenantSearch.toLowerCase());\r\n const matchesType = includePersonalTenants || t.tenantType !== 'Personal';\r\n return matchesSearch && matchesType;\r\n })\r\n .map(t => t.tenantId);\r\n setSelectedTenantIds(filteredIds);\r\n } else {\r\n const filteredIds = availableTenants\r\n .filter(t => {\r\n const matchesSearch =\r\n t.name.toLowerCase().includes(tenantSearch.toLowerCase()) ||\r\n t.slug.toLowerCase().includes(tenantSearch.toLowerCase());\r\n const matchesType = includePersonalTenants || t.type !== 'Personal';\r\n return matchesSearch && matchesType;\r\n })\r\n .map(t => t.id);\r\n setSelectedTenantIds(filteredIds);\r\n }\r\n }, [isUpdateMode, assignedTenants, availableTenants, tenantSearch, includePersonalTenants]);\r\n\r\n // Clear tenant selection\r\n const clearTenantSelection = useCallback(() => {\r\n setSelectedTenantIds([]);\r\n }, []);\r\n\r\n // Execute the actual update operation\r\n const executeUpdateTenants = useCallback(\r\n async (appId: string, onSuccess?: () => void) => {\r\n if (!appId || selectedTenantIds.length === 0) return;\r\n\r\n try {\r\n const request: BulkAssignTenantsRequest = {\r\n tenantIds: selectedTenantIds,\r\n accessLevel: selectedAccessLevel,\r\n accessMode: bulkAccessMode,\r\n mergeMode: updateMergeMode,\r\n };\r\n\r\n if (bulkAccessMode === 'custom') {\r\n request.moduleIds = bulkModules.filter(m => m.isAssigned).map(m => m.id);\r\n request.sectionIds = bulkModules.flatMap(m =>\r\n m.sections.filter(s => s.isAssigned).map(s => s.id)\r\n );\r\n }\r\n\r\n await adminApi.applications.bulkAssignTenants(appId, request);\r\n\r\n // Reset state\r\n setShowAssignModal(false);\r\n setSelectedTenantIds([]);\r\n setSelectedAccessLevel('FullAccess');\r\n setBulkAccessMode('full');\r\n setTenantSearch('');\r\n setIsUpdateMode(false);\r\n setUpdateMergeMode('merge');\r\n setShowConfirmRemovalDialog(false);\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to update tenant assignments:', err);\r\n throw err;\r\n }\r\n },\r\n [selectedTenantIds, selectedAccessLevel, bulkAccessMode, updateMergeMode, bulkModules, loadPublicationData]\r\n );\r\n\r\n // Assign application to tenants\r\n const handleAssignTenants = useCallback(\r\n async (appId: string, onSuccess?: () => void) => {\r\n if (!appId || selectedTenantIds.length === 0) return;\r\n\r\n try {\r\n const request: BulkAssignTenantsRequest = {\r\n tenantIds: selectedTenantIds,\r\n accessLevel: selectedAccessLevel,\r\n accessMode: bulkAccessMode,\r\n };\r\n\r\n if (bulkAccessMode === 'custom') {\r\n request.moduleIds = bulkModules.filter(m => m.isAssigned).map(m => m.id);\r\n request.sectionIds = bulkModules.flatMap(m =>\r\n m.sections.filter(s => s.isAssigned).map(s => s.id)\r\n );\r\n }\r\n\r\n await adminApi.applications.bulkAssignTenants(appId, request);\r\n\r\n // Reset state\r\n setShowAssignModal(false);\r\n setSelectedTenantIds([]);\r\n setSelectedAccessLevel('FullAccess');\r\n setBulkAccessMode('full');\r\n setTenantSearch('');\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to assign tenants:', err);\r\n throw err;\r\n }\r\n },\r\n [selectedTenantIds, selectedAccessLevel, bulkAccessMode, bulkModules, loadPublicationData]\r\n );\r\n\r\n // Update existing tenant assignments (with confirmation for replace mode)\r\n const handleUpdateTenants = useCallback(\r\n async (appId: string, onSuccess?: () => void) => {\r\n if (!appId || selectedTenantIds.length === 0) return;\r\n\r\n // Calculate potential removals in replace mode\r\n if (updateMergeMode === 'replace' && bulkAccessMode === 'custom') {\r\n let removedModulesCount = 0;\r\n let removedSectionsCount = 0;\r\n\r\n // Get current assignments for selected tenants and calculate diff\r\n for (const tenantId of selectedTenantIds) {\r\n try {\r\n const currentModules = await adminApi.tenants.getModules(tenantId);\r\n const currentSections = await adminApi.tenants.getSections(tenantId);\r\n\r\n const targetModuleIds = new Set(bulkModules.filter(m => m.isAssigned).map(m => m.id));\r\n const targetSectionIds = new Set(bulkModules.flatMap(m => m.sections.filter(s => s.isAssigned).map(s => s.id)));\r\n\r\n removedModulesCount += currentModules.filter(m => !targetModuleIds.has(m.moduleId)).length;\r\n removedSectionsCount += currentSections.filter(s => !targetSectionIds.has(s.sectionId)).length;\r\n } catch {\r\n // Ignore errors fetching current state\r\n }\r\n }\r\n\r\n // If there are removals, show confirmation dialog\r\n if (removedModulesCount > 0 || removedSectionsCount > 0) {\r\n setPendingRemovals({ modules: removedModulesCount, sections: removedSectionsCount });\r\n setShowConfirmRemovalDialog(true);\r\n return;\r\n }\r\n }\r\n\r\n await executeUpdateTenants(appId, onSuccess);\r\n },\r\n [\r\n selectedTenantIds,\r\n updateMergeMode,\r\n bulkAccessMode,\r\n bulkModules,\r\n executeUpdateTenants,\r\n ]\r\n );\r\n\r\n // Remove application from tenant\r\n const handleRemoveTenant = useCallback(\r\n async (appId: string, tenantId: string, onSuccess?: () => void) => {\r\n if (!appId) return;\r\n\r\n try {\r\n await adminApi.applications.removeFromTenant(appId, tenantId);\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to remove tenant:', err);\r\n throw err;\r\n }\r\n },\r\n [loadPublicationData]\r\n );\r\n\r\n // Update tenant access level\r\n const handleUpdateAccessLevel = useCallback(\r\n async (appId: string, tenantId: string, accessLevel: ApplicationAccessLevel, onSuccess?: () => void) => {\r\n if (!appId) return;\r\n\r\n try {\r\n await adminApi.applications.updateTenantAccessLevel(appId, tenantId, accessLevel);\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to update access level:', err);\r\n throw err;\r\n }\r\n },\r\n [loadPublicationData]\r\n );\r\n\r\n return {\r\n // State\r\n assignedTenants,\r\n availableTenants,\r\n showAssignModal,\r\n selectedTenantIds,\r\n selectedAccessLevel,\r\n tenantSearch,\r\n showCustomizeDrawer,\r\n customizingTenant,\r\n bulkAccessMode,\r\n bulkModules,\r\n bulkExpandedModules,\r\n loadingBulkModules,\r\n isUpdateMode,\r\n updateMergeMode,\r\n showConfirmRemovalDialog,\r\n pendingRemovals,\r\n includePersonalTenants,\r\n isInDefaultPersonalTemplate,\r\n\r\n // Setters\r\n setAssignedTenants,\r\n setAvailableTenants,\r\n setShowAssignModal,\r\n setSelectedTenantIds,\r\n setSelectedAccessLevel,\r\n setTenantSearch,\r\n setShowCustomizeDrawer,\r\n setCustomizingTenant,\r\n setBulkAccessMode,\r\n setBulkModules,\r\n setBulkExpandedModules,\r\n setIsUpdateMode,\r\n setUpdateMergeMode,\r\n setShowConfirmRemovalDialog,\r\n setPendingRemovals,\r\n setIncludePersonalTenants,\r\n\r\n // Operations\r\n loadPublicationData,\r\n loadBulkModules,\r\n toggleBulkModuleExpand,\r\n toggleBulkModule,\r\n toggleBulkSection,\r\n getBulkModuleCheckState,\r\n getBulkStats,\r\n selectAllBulkModules,\r\n clearBulkModules,\r\n toggleTenantSelection,\r\n selectAllFilteredTenants,\r\n clearTenantSelection,\r\n handleAssignTenants,\r\n handleUpdateTenants,\r\n executeUpdateTenants,\r\n handleRemoveTenant,\r\n handleUpdateAccessLevel,\r\n };\r\n}\r\n","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Save, Loader2 } from 'lucide-react';\r\nimport type { ApplicationDetailDto } from '@/services/api/adminApi';\r\n\r\ninterface ApplicationInfoTabProps {\r\n readonly formData: {\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n };\r\n readonly setFormData: React.Dispatch<\r\n React.SetStateAction<{\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n }>\r\n >;\r\n readonly application: ApplicationDetailDto;\r\n readonly saving: boolean;\r\n readonly onSubmit: (e: React.FormEvent) => Promise<void>;\r\n}\r\n\r\nexport function ApplicationInfoTab({\r\n formData,\r\n setFormData,\r\n application,\r\n saving,\r\n onSubmit,\r\n}: ApplicationInfoTabProps): React.ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <form onSubmit={onSubmit} className=\"space-y-6\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.code')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={application.code}\r\n disabled\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-tertiary)] border border-[var(--border-color)] text-[var(--text-muted)] cursor-not-allowed\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.label')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={formData.label}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, label: e.target.value }))\r\n }\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n required\r\n />\r\n </div>\r\n <div className=\"md:col-span-2\">\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.description')}\r\n </label>\r\n <textarea\r\n value={formData.description}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, description: e.target.value }))\r\n }\r\n rows={3}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.icon')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={formData.icon}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, icon: e.target.value }))\r\n }\r\n placeholder={t('applicationDetail.fields.icon')}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.route')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={formData.route}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, route: e.target.value }))\r\n }\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.displayOrder')}\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={formData.displayOrder}\r\n onChange={e =>\r\n setFormData(prev => ({\r\n ...prev,\r\n displayOrder: parseInt(e.target.value) || 0,\r\n }))\r\n }\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.zone', 'Zone')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={application.zone || ''}\r\n disabled\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-tertiary)] border border-[var(--border-color)] text-[var(--text-muted)] cursor-not-allowed\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex justify-end\">\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"flex items-center gap-2 px-6 py-2 rounded-[var(--radius-button)] font-medium bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50\"\r\n >\r\n {saving ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Save className=\"w-4 h-4\" />\r\n )}\r\n {t('applicationDetail.actions.save')}\r\n </button>\r\n </div>\r\n </form>\r\n );\r\n}\r\n","import { useState, type ReactNode } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport {\r\n DndContext,\r\n closestCenter,\r\n KeyboardSensor,\r\n PointerSensor,\r\n useSensor,\r\n useSensors,\r\n type DragEndEvent,\r\n} from '@dnd-kit/core';\r\nimport {\r\n arrayMove,\r\n SortableContext,\r\n sortableKeyboardCoordinates,\r\n useSortable,\r\n verticalListSortingStrategy,\r\n} from '@dnd-kit/sortable';\r\nimport { CSS } from '@dnd-kit/utilities';\r\nimport { GripVertical } from 'lucide-react';\r\n\r\nexport interface SortableItem {\r\n id: string;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface SortableListProps<T extends SortableItem> {\r\n readonly items: T[];\r\n readonly onReorder: (items: T[]) => void;\r\n readonly renderItem: (item: T, dragHandle: ReactNode) => ReactNode;\r\n readonly disabled?: boolean;\r\n}\r\n\r\ninterface SortableItemWrapperProps {\r\n readonly id: string;\r\n readonly disabled?: boolean;\r\n readonly children: (dragHandle: ReactNode) => ReactNode;\r\n}\r\n\r\nfunction SortableItemWrapper({ id, disabled, children }: SortableItemWrapperProps) {\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n } = useSortable({ id, disabled });\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.5 : 1,\r\n zIndex: isDragging ? 1 : 0,\r\n };\r\n\r\n const dragHandle = !disabled ? (\r\n <button\r\n type=\"button\"\r\n className=\"p-1.5 rounded hover:bg-[var(--bg-hover)] cursor-grab active:cursor-grabbing text-[var(--text-muted)] hover:text-[var(--text-secondary)] transition-colors\"\r\n {...attributes}\r\n {...listeners}\r\n >\r\n <GripVertical className=\"w-4 h-4\" />\r\n </button>\r\n ) : null;\r\n\r\n return (\r\n <div ref={setNodeRef} style={style}>\r\n {children(dragHandle)}\r\n </div>\r\n );\r\n}\r\n\r\nexport function SortableList<T extends SortableItem>({\r\n items,\r\n onReorder,\r\n renderItem,\r\n disabled = false,\r\n}: SortableListProps<T>): ReactElement {\r\n const [, setActiveId] = useState<string | null>(null);\r\n\r\n const sensors = useSensors(\r\n useSensor(PointerSensor, {\r\n activationConstraint: {\r\n distance: 8,\r\n },\r\n }),\r\n useSensor(KeyboardSensor, {\r\n coordinateGetter: sortableKeyboardCoordinates,\r\n })\r\n );\r\n\r\n const handleDragEnd = (event: DragEndEvent) => {\r\n const { active, over } = event;\r\n setActiveId(null);\r\n\r\n if (over && active.id !== over.id) {\r\n const oldIndex = items.findIndex((item) => item.id === active.id);\r\n const newIndex = items.findIndex((item) => item.id === over.id);\r\n const newItems = arrayMove(items, oldIndex, newIndex);\r\n onReorder(newItems);\r\n }\r\n };\r\n\r\n return (\r\n <DndContext\r\n sensors={sensors}\r\n collisionDetection={closestCenter}\r\n onDragStart={(event) => setActiveId(event.active.id as string)}\r\n onDragEnd={handleDragEnd}\r\n >\r\n <SortableContext\r\n items={items.map((item) => item.id)}\r\n strategy={verticalListSortingStrategy}\r\n disabled={disabled}\r\n >\r\n <div className=\"space-y-2\">\r\n {items.map((item) => (\r\n <SortableItemWrapper key={item.id} id={item.id} disabled={disabled}>\r\n {(dragHandle) => renderItem(item, dragHandle)}\r\n </SortableItemWrapper>\r\n ))}\r\n </div>\r\n </SortableContext>\r\n </DndContext>\r\n );\r\n}\r\n\r\nexport default SortableList;\r\n","import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { ChevronDown, ChevronRight, Edit, Layers, Loader2, Save } from 'lucide-react';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\nimport { SortableList } from '@/components/ui/SortableList';\r\nimport { renderLucideIcon } from '@/utils/renderLucideIcon';\r\nimport type {\r\n ApplicationDetailDto,\r\n ApplicationModuleDto,\r\n ModuleSectionDto,\r\n} from '@/services/api/adminApi';\r\n\r\ninterface ApplicationModulesTabProps {\r\n readonly application: ApplicationDetailDto;\r\n readonly expandedModules: Set<string>;\r\n readonly moduleSections: Map<string, ModuleSectionDto[]>;\r\n readonly loadingSections: Set<string>;\r\n readonly reordering: boolean;\r\n readonly editingModule: ApplicationModuleDto | null;\r\n readonly moduleFormData: {\r\n readonly code: string;\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n };\r\n readonly showModuleForm: boolean;\r\n readonly saving: boolean;\r\n readonly onToggleExpand: (moduleId: string) => void;\r\n readonly onStartEdit: (module: ApplicationModuleDto) => void;\r\n readonly onSaveModule: (e: React.FormEvent) => Promise<void>;\r\n readonly onCancelEdit: () => void;\r\n readonly onModulesReorder: (modules: (ApplicationModuleDto & { id: string })[]) => Promise<void>;\r\n readonly onSectionsReorder: (moduleId: string, sections: ModuleSectionDto[]) => Promise<void>;\r\n readonly setModuleFormData: React.Dispatch<\r\n React.SetStateAction<{\r\n readonly code: string;\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n }>\r\n >;\r\n}\r\n\r\n\r\nconst renderModuleSections = (moduleId: string, loadingSections: Set<string>, moduleSections: Map<string, ModuleSectionDto[]>, onSectionsReorder: (moduleId: string, sections: ModuleSectionDto[]) => Promise<void>, reordering: boolean, t: TFunction) => {\r\n if (loadingSections.has(moduleId)) {\r\n return (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-muted)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (moduleSections.get(moduleId)?.length === 0) {\r\n return (\r\n <p className=\"text-sm text-[var(--text-muted)] py-2\">\r\n {t('applicationDetail.modules.noSections', 'No sections')}\r\n </p>\r\n );\r\n }\r\n\r\n if (moduleSections.get(moduleId)) {\r\n return (\r\n <SortableList\r\n items={moduleSections.get(moduleId)!.map((s) => ({ ...s, id: s.id }))}\r\n onReorder={(sections) => onSectionsReorder(moduleId, sections)}\r\n disabled={reordering}\r\n renderItem={(section, sectionDragHandle) => (\r\n <div className=\"flex items-center gap-2 p-2 rounded bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n {sectionDragHandle}\r\n <div className=\"p-1 rounded bg-[var(--bg-tertiary)]\">\r\n {renderLucideIcon(section.icon, 'w-3 h-3') || (\r\n <Layers className=\"w-3 h-3 text-[var(--text-muted)]\" />\r\n )}\r\n </div>\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {section.label}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">{section.code}</p>\r\n </div>\r\n <span\r\n className={`px-2 py-0.5 text-xs rounded-full ${\r\n section.isActive\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n : 'bg-[var(--error-bg)] text-[var(--error-text)]'\r\n }`}\r\n >\r\n {section.isActive ? t('common:active') : t('common:inactive')}\r\n </span>\r\n </div>\r\n )}\r\n />\r\n );\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport function ApplicationModulesTab({\r\n application,\r\n expandedModules,\r\n moduleSections,\r\n loadingSections,\r\n reordering,\r\n editingModule,\r\n moduleFormData,\r\n showModuleForm,\r\n saving,\r\n onToggleExpand,\r\n onStartEdit,\r\n onSaveModule,\r\n onCancelEdit,\r\n onModulesReorder,\r\n onSectionsReorder,\r\n setModuleFormData,\r\n}: ApplicationModulesTabProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.modules.title')} ({application.modules.length})\r\n </h3>\r\n\r\n {showModuleForm && editingModule && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h4 className=\"text-md font-semibold text-[var(--text-primary)] mb-4\">\r\n {t('applicationDetail.modules.edit')}\r\n </h4>\r\n <form onSubmit={onSaveModule} className=\"space-y-4\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.code')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.code}\r\n disabled\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-tertiary)] border border-[var(--border-color)] text-[var(--text-muted)] cursor-not-allowed\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.label')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.label}\r\n onChange={(e) => setModuleFormData((prev) => ({ ...prev, label: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n required\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.icon')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.icon}\r\n onChange={(e) => setModuleFormData((prev) => ({ ...prev, icon: e.target.value }))}\r\n placeholder=\"Users\"\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.route')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.route}\r\n onChange={(e) => setModuleFormData((prev) => ({ ...prev, route: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div className=\"md:col-span-2\">\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.description')}\r\n </label>\r\n <textarea\r\n value={moduleFormData.description}\r\n onChange={(e) =>\r\n setModuleFormData((prev) => ({ ...prev, description: e.target.value }))\r\n }\r\n rows={2}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n type=\"button\"\r\n onClick={onCancelEdit}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]\"\r\n >\r\n {t('common:cancel')}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50\"\r\n >\r\n {saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {t('common:save')}\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n )}\r\n\r\n {application.modules.length === 0 ? (\r\n <p className=\"text-center py-8 text-[var(--text-muted)]\">\r\n {t('applicationDetail.modules.empty')}\r\n </p>\r\n ) : (\r\n <SortableList\r\n items={application.modules.map((m) => ({ ...m, id: m.id }))}\r\n onReorder={onModulesReorder}\r\n disabled={reordering}\r\n renderItem={(module, dragHandle) => (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--item-color-border)] hover:border-[var(--color-accent-600)] transition-colors\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n {dragHandle}\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)]\">\r\n {renderLucideIcon(module.icon, 'w-4 h-4') || (\r\n <Layers className=\"w-4 h-4 text-[var(--text-muted)]\" />\r\n )}\r\n </div>\r\n <button\r\n onClick={() => onToggleExpand(module.id)}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)]\"\r\n aria-expanded={expandedModules.has(module.id)}\r\n aria-label={t('applicationDetail.modules.toggleExpand', 'Toggle sections')}\r\n >\r\n {expandedModules.has(module.id) ? (\r\n <ChevronDown className=\"w-4 h-4 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-4 h-4 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n <div>\r\n <p className=\"font-medium text-[var(--text-primary)]\">{module.label}</p>\r\n <p className=\"text-sm text-[var(--text-muted)]\">{module.code}</p>\r\n </div>\r\n <span\r\n className={`ml-2 px-2 py-0.5 text-xs font-medium rounded-full ${\r\n module.isActive\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n : 'bg-[var(--error-bg)] text-[var(--error-text)]'\r\n }`}\r\n >\r\n {module.isActive ? t('common:active') : t('common:inactive')}\r\n </span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-muted)]\">\r\n {module.sectionsCount} {t('applicationDetail.modules.sections', 'sections')}\r\n </span>\r\n <button\r\n onClick={() => onStartEdit(module)}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)]\"\r\n aria-label={t('applicationDetail.modules.edit')}\r\n >\r\n <Edit className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n {expandedModules.has(module.id) && (\r\n <div className=\"mt-3 pl-10 pt-3 border-t border-[var(--border-color)]\">\r\n <div className=\"grid grid-cols-2 gap-4 text-sm mb-4\">\r\n <div>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {t('applicationDetail.fields.description')}:\r\n </span>\r\n <p className=\"text-[var(--text-primary)]\">{module.description || '-'}</p>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {t('applicationDetail.fields.route')}:\r\n </span>\r\n <p className=\"text-[var(--text-primary)] font-mono\">{module.route || '-'}</p>\r\n </div>\r\n </div>\r\n {/* Sections */}\r\n <div className=\"mt-4\">\r\n <h5 className=\"text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.modules.sections', 'Sections')} ({module.sectionsCount})\r\n </h5>\r\n {renderModuleSections(module.id, loadingSections, moduleSections, onSectionsReorder, reordering, t)}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n","import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport type { ApplicationDetailDto, PermissionListDto, RoleListDto } from '@/services/api/adminApi';\r\n\r\nexport interface PermissionWithRoles {\r\n permission: PermissionListDto;\r\n roles: RoleListDto[];\r\n}\r\n\r\nexport interface ApplicationPermissionsTabProps {\r\n readonly application: ApplicationDetailDto;\r\n readonly permissions: PermissionListDto[];\r\n readonly permissionsWithRoles: PermissionWithRoles[];\r\n}\r\n\r\nexport function ApplicationPermissionsTab({\r\n application,\r\n permissions,\r\n permissionsWithRoles,\r\n}: ApplicationPermissionsTabProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.permissions.title')} ({permissions.length})\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {t('applicationDetail.permissions.description', {\r\n path: `${application.code}.*`,\r\n })}\r\n </p>\r\n\r\n {permissions.length === 0 ? (\r\n <p className=\"text-center py-8 text-[var(--text-muted)]\">\r\n {t('applicationDetail.permissions.empty')}\r\n </p>\r\n ) : (\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"border-b border-[var(--border-color)]\">\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.path')}\r\n </th>\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.action')}\r\n </th>\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.type')}\r\n </th>\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.roles')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {permissionsWithRoles.map(({ permission, roles: permRoles }) => (\r\n <tr\r\n key={permission.id}\r\n className=\"border-b border-[var(--border-color)] hover:bg-[var(--bg-hover)]\"\r\n >\r\n <td className=\"py-3 px-4 font-mono text-sm text-[var(--text-primary)]\">\r\n {permission.path}\r\n </td>\r\n <td className=\"py-3 px-4\">\r\n {permission.action ? (\r\n <span className=\"px-2 py-1 text-xs font-medium rounded-full bg-[var(--accent-bg)] text-[var(--accent-text)]\">\r\n {permission.action}\r\n </span>\r\n ) : (\r\n '-'\r\n )}\r\n </td>\r\n <td className=\"py-3 px-4\">\r\n {permission.isWildcard ? (\r\n <span className=\"px-2 py-1 text-xs font-medium rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)]\">\r\n {t('applicationDetail.permissions.wildcard', 'Wildcard')}\r\n </span>\r\n ) : (\r\n <span className=\"px-2 py-1 text-xs font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-muted)]\">\r\n {t('applicationDetail.permissions.specific', 'Specific')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"py-3 px-4\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {permRoles.length === 0 ? (\r\n <span className=\"text-[var(--text-muted)] text-sm\">-</span>\r\n ) : (\r\n permRoles.slice(0, 3).map(role => (\r\n <span\r\n key={role.id}\r\n className=\"px-2 py-0.5 text-xs font-medium rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)]\"\r\n >\r\n {role.name}\r\n </span>\r\n ))\r\n )}\r\n {permRoles.length > 3 && (\r\n <span className=\"px-2 py-0.5 text-xs font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-muted)]\">\r\n +{permRoles.length - 3}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import type { ReactElement } from 'react';\nimport { Shield, Eye } from 'lucide-react';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nexport interface RoleListDto {\r\n id: string;\r\n name: string;\r\n isSystem: boolean;\r\n usersCount: number;\r\n}\r\n\r\nexport interface PermissionListDto {\r\n id: string;\r\n path: string;\r\n isWildcard: boolean;\r\n}\r\n\r\nexport interface RoleWithPermissions {\r\n role: RoleListDto;\r\n permissions: PermissionListDto[];\r\n}\r\n\r\nexport interface ApplicationAccessTabProps {\r\n readonly rolesWithAppAccess: RoleWithPermissions[];\r\n readonly onNavigateToRole: (roleId: string) => void;\r\n}\r\n\r\nexport function ApplicationAccessTab({\r\n rolesWithAppAccess,\r\n onNavigateToRole,\r\n}: ApplicationAccessTabProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.roles.title')} ({rolesWithAppAccess.length})\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {t('applicationDetail.roles.description')}\r\n </p>\r\n\r\n {rolesWithAppAccess.length === 0 ? (\r\n <p className=\"text-center py-8 text-[var(--text-muted)]\">\r\n {t('applicationDetail.roles.empty')}\r\n </p>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n {rolesWithAppAccess.map(({ role, permissions: rolePermissions }) => (\r\n <div\r\n key={role.id}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--item-color-border)] hover:border-[var(--color-accent-600)] transition-colors\"\r\n >\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)]\">\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.isSystem && (\r\n <span className=\"px-2 py-0.5 text-xs font-medium rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)]\">\r\n {t('applicationDetail.roles.system', 'System')}\r\n </span>\r\n )}\r\n </div>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {role.usersCount} {t('applicationDetail.roles.users')} • {rolePermissions.length}{' '}\r\n {t('applicationDetail.roles.permissions')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => onNavigateToRole(role.id)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-[var(--radius-button)] text-sm font-medium text-[var(--color-accent-600)] hover:bg-[var(--color-accent-100)]\"\r\n >\r\n <Eye className=\"w-4 h-4\" />\r\n {t('applicationDetail.roles.viewRole')}\r\n </button>\r\n </div>\r\n </div>\r\n <div className=\"mt-3 flex flex-wrap gap-1\">\r\n {rolePermissions.slice(0, 5).map(perm => (\r\n <span\r\n key={perm.id}\r\n className=\"px-2 py-0.5 text-xs font-mono rounded bg-[var(--bg-tertiary)] text-[var(--text-muted)]\"\r\n >\r\n {perm.path.split('.').pop()}\r\n {perm.isWildcard && '.*'}\r\n </span>\r\n ))}\r\n {rolePermissions.length > 5 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded bg-[var(--bg-tertiary)] text-[var(--text-muted)]\">\r\n +{rolePermissions.length - 5} {t('applicationDetail.roles.more', 'more')}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","'use client';\r\n\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n Globe,\r\n} from 'lucide-react';\r\nimport type {\r\n ApplicationDetailDto,\r\n ApplicationTenantDto,\r\n ApplicationAccessLevel,\r\n AvailableTenantForAppDto,\r\n} from '@/services/api/adminApi';\r\nimport { useTenantTypeSettings } from '@/hooks/useTenantTypeSettings';\r\nimport { getLucideIcon, getColorClasses } from '@/utils/tenantIconMap';\r\n\r\nexport interface BulkModuleNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n sections: BulkSectionNode[];\r\n}\r\n\r\nexport interface BulkSectionNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n}\r\n\r\nexport interface ApplicationPublicationTabProps {\r\n readonly application: ApplicationDetailDto;\r\n readonly assignedTenants: ApplicationTenantDto[];\r\n readonly availableTenants: AvailableTenantForAppDto[];\r\n readonly showAssignModal: boolean;\r\n readonly selectedTenantIds: string[];\r\n readonly selectedAccessLevel: ApplicationAccessLevel;\r\n readonly tenantSearch: string;\r\n readonly showCustomizeDrawer: boolean;\r\n readonly customizingTenant: ApplicationTenantDto | null;\r\n readonly bulkAccessMode: 'full' | 'custom';\r\n readonly bulkModules: BulkModuleNode[];\r\n readonly bulkExpandedModules: Set<string>;\r\n readonly loadingBulkModules: boolean;\r\n readonly isUpdateMode: boolean;\r\n readonly updateMergeMode: 'merge' | 'replace';\r\n readonly showConfirmRemovalDialog: boolean;\r\n readonly pendingRemovals: { modules: number; sections: number };\r\n readonly saving: boolean;\r\n readonly includePersonalTenants: boolean;\r\n readonly isInDefaultPersonalTemplate: boolean;\r\n readonly onAddTenant: () => void;\r\n readonly onRemoveTenant: (tenantId: string) => Promise<void>;\r\n readonly onUpdateAccessLevel: (tenantId: string, accessLevel: ApplicationAccessLevel) => Promise<void>;\r\n readonly onCustomizeTenant: (tenant: ApplicationTenantDto) => void;\r\n readonly onCloseCustomizeDrawer: () => void;\r\n readonly onAssignTenants: () => Promise<void>;\r\n readonly onUpdateTenants: () => Promise<void>;\r\n readonly onExecuteUpdateTenants: () => Promise<void>;\r\n readonly onCancelRemovalDialog: () => void;\r\n readonly setShowAssignModal: (show: boolean) => void;\r\n readonly setSelectedTenantIds: React.Dispatch<React.SetStateAction<string[]>>;\r\n readonly setSelectedAccessLevel: React.Dispatch<React.SetStateAction<ApplicationAccessLevel>>;\r\n readonly setTenantSearch: (search: string) => void;\r\n readonly setBulkAccessMode: React.Dispatch<React.SetStateAction<'full' | 'custom'>>;\r\n readonly setIsUpdateMode: (mode: boolean) => void;\r\n readonly setUpdateMergeMode: React.Dispatch<React.SetStateAction<'merge' | 'replace'>>;\r\n readonly onToggleTenantSelection: (tenantId: string) => void;\r\n readonly onSelectAllFilteredTenants: () => void;\r\n readonly onClearTenantSelection: () => void;\r\n readonly setIncludePersonalTenants: (value: boolean) => void;\r\n readonly onLoadBulkModules: () => Promise<void>;\r\n readonly onToggleBulkModuleExpand: (moduleId: string) => void;\r\n readonly onToggleBulkModule: (moduleId: string) => void;\r\n readonly onToggleBulkSection: (moduleId: string, sectionId: string) => void;\r\n readonly onGetBulkModuleCheckState: (module: BulkModuleNode) => 'checked' | 'unchecked' | 'indeterminate';\r\n readonly onGetBulkStats: () => { totalModules: number; assignedModules: number; totalSections: number; assignedSections: number };\r\n readonly onSelectAllBulkModules: () => void;\r\n readonly onClearBulkModules: () => void;\r\n readonly appId: string;\r\n}\r\n\r\n// Helper: Get CSS classes for access level indicator color\r\nconst getAccessLevelColorClass = (accessLevel: ApplicationAccessLevel): string => {\r\n switch (accessLevel) {\r\n case 'FullAccess':\r\n return 'bg-green-500';\r\n case 'RequestAccess':\r\n return 'bg-amber-500';\r\n case 'Disabled':\r\n return 'bg-gray-400';\r\n default:\r\n return 'bg-gray-400';\r\n }\r\n};\r\n\r\n// Helper: Get access level label key\r\nconst getLabelKey = (level: ApplicationAccessLevel): string => {\r\n switch (level) {\r\n case 'FullAccess':\r\n return 'fullAccess';\r\n case 'RequestAccess':\r\n return 'requestAccess';\r\n case 'Disabled':\r\n return 'disabled';\r\n default:\r\n return 'disabled';\r\n }\r\n};\r\n\r\n// Helper: Get tenant icon and color from settings\r\nconst useTenantIconForType = () => {\r\n const { getIconForType } = useTenantTypeSettings();\r\n return (tenantType: string) => {\r\n const typeInfo = getIconForType(tenantType);\r\n const Icon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return { Icon, bgClass: colors.bg, colorClass: colors.text };\r\n };\r\n};\r\n\r\nexport const ApplicationPublicationTab: React.FC<ApplicationPublicationTabProps> = ({\r\n assignedTenants,\r\n}) => {\r\n const { t } = useTranslation('admin');\r\n const getTenantIconInfo = useTenantIconForType();\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Header Section */}\r\n <div>\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.title', 'Tenant Publication')} ({assignedTenants.length})\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.description', 'Manage which tenants have access to this application')}\r\n </p>\r\n </div>\r\n\r\n {/* Access Levels Legend */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3 p-4 rounded-[var(--radius-card)] bg-[var(--bg-tertiary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"w-3 h-3 mt-1 rounded-full bg-green-500 flex-shrink-0\" />\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.accessLevels.fullAccess', 'Full Access')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.accessLevels.fullAccessDesc', 'Users can use all features')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"w-3 h-3 mt-1 rounded-full bg-amber-500 flex-shrink-0\" />\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.accessLevels.requestAccess', 'Request Access')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.accessLevels.requestAccessDesc', 'Requires access request')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"w-3 h-3 mt-1 rounded-full bg-gray-400 flex-shrink-0\" />\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.accessLevels.disabled', 'Disabled')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.accessLevels.disabledDesc', 'Not visible for tenant')}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Assigned Tenants List or Empty State */}\r\n {assignedTenants.length === 0 ? (\r\n <div className=\"text-center py-12\">\r\n <Globe className=\"w-12 h-12 mx-auto text-[var(--text-muted)] mb-4\" />\r\n <p className=\"text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.empty', 'No tenants have access to this application yet')}\r\n </p>\r\n </div>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n {assignedTenants.map(tenant => {\r\n const { Icon, bgClass, colorClass } = getTenantIconInfo(tenant.tenantType);\r\n const statusBgClass = tenant.tenantStatus === 'Active'\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n : 'bg-[var(--warning-bg)] text-[var(--warning-text)]';\r\n\r\n return (\r\n <div\r\n key={tenant.tenantId}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--item-color-border)] hover:border-[var(--color-accent-600)] transition-colors\"\r\n >\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)] ${bgClass}`}>\r\n <Icon className={`w-5 h-5 ${colorClass}`} />\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <p className=\"font-medium text-[var(--text-primary)]\">{tenant.tenantName}</p>\r\n <span className={`px-2 py-0.5 text-xs font-medium rounded-full ${statusBgClass}`}>\r\n {tenant.tenantStatus}\r\n </span>\r\n </div>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {tenant.tenantSlug} • {tenant.tenantType}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <div className={`w-2.5 h-2.5 rounded-full ${getAccessLevelColorClass(tenant.accessLevel as ApplicationAccessLevel)}`} />\r\n <span className=\"px-3 py-1.5 rounded-[var(--radius-input)] bg-[var(--bg-secondary)] border border-[var(--border-color)] text-sm text-[var(--text-primary)]\">\r\n {t(`applicationDetail.publication.accessLevels.${getLabelKey(tenant.accessLevel as ApplicationAccessLevel)}`, tenant.accessLevel)}\r\n </span>\r\n </div>\r\n </div>\r\n <div className=\"mt-2 text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.assignedAt', 'Assigned')}: {new Date(tenant.assignedAt).toLocaleDateString()}\r\n {tenant.assignedBy && ` ${t('applicationDetail.publication.by', 'by')} ${tenant.assignedBy}`}\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import { useEffect, useMemo} from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useParams, useNavigate } from 'react-router-dom';\r\nimport { useTabNavigation } from '@/hooks/useTabNavigation';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n ArrowLeft,\r\n Settings,\r\n Layers,\r\n Shield,\r\n Users,\r\n Loader2,\r\n AlertTriangle,\r\n CheckCircle,\r\n Power,\r\n PowerOff,\r\n Globe,\r\n AlertCircle,\r\n Inbox,\r\n} from 'lucide-react';\r\nimport { renderLucideIcon } from '@/utils/renderLucideIcon';\r\nimport { useApplicationDetail } from '@/hooks/useApplicationDetail';\r\nimport { useApplicationModules } from '@/hooks/useApplicationModules';\r\nimport { useApplicationPermissions } from '@/hooks/useApplicationPermissions';\r\nimport { useApplicationPublication } from '@/hooks/useApplicationPublication';\r\nimport {\r\n ApplicationInfoTab,\r\n ApplicationModulesTab,\r\n ApplicationPermissionsTab,\r\n ApplicationAccessTab,\r\n ApplicationPublicationTab,\r\n} from '@/components/platform/administration/applications';\r\nimport { AccessRequestsListTab } from '@/components/platform/administration/access-requests';\r\nimport { useAccessRequests } from '@/hooks/useAccessRequests';\r\n\r\nconst VALID_TABS = ['info', 'modules', 'permissions', 'roles', 'publication', 'requests'] as const;\r\ntype TabId = typeof VALID_TABS[number];\r\n\r\nexport default function ApplicationDetailPage(): ReactElement {\r\n const { id: appId } = useParams<{ id: string }>();\r\n const navigate = useNavigate();\r\n const { t } = useTranslation('admin');\r\n const { hasPermission } = useAuth();\r\n\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const canToggleStatus = hasPermission('administration.applications.execute');\r\n const { activeTab, setActiveTab } = useTabNavigation<TabId>('info', VALID_TABS);\r\n\r\n // Use all hooks\r\n const applicationDetail = useApplicationDetail();\r\n const applicationModules = useApplicationModules();\r\n const applicationPermissions = useApplicationPermissions();\r\n const applicationPublication = useApplicationPublication();\r\n const accessRequests = useAccessRequests('application', appId!);\r\n\r\n // Filter tenants based on current tenant context\r\n // When scoped to a specific tenant, only show that tenant in the publication modal\r\n const filteredAvailableTenants = useMemo(() => {\r\n if (isGlobalView || !currentTenant) return applicationPublication.availableTenants;\r\n return applicationPublication.availableTenants.filter(t => t.slug === currentTenant.slug);\r\n }, [applicationPublication.availableTenants, isGlobalView, currentTenant]);\r\n\r\n const filteredAssignedTenants = useMemo(() => {\r\n if (isGlobalView || !currentTenant) return applicationPublication.assignedTenants;\r\n return applicationPublication.assignedTenants.filter(t => t.tenantSlug === currentTenant.slug);\r\n }, [applicationPublication.assignedTenants, isGlobalView, currentTenant]);\r\n\r\n // Load data on mount\r\n useEffect(() => {\r\n if (appId) {\r\n applicationDetail.loadApplication(appId);\r\n }\r\n }, [appId]);\r\n\r\n // Load tab-specific data (lazy loading per tab)\r\n useEffect(() => {\r\n if (!applicationDetail.application) return;\r\n\r\n if (\r\n (activeTab === 'permissions' || activeTab === 'roles') &&\r\n applicationPermissions.permissions.length === 0\r\n ) {\r\n applicationPermissions.loadPermissionsData(applicationDetail.application);\r\n }\r\n if (\r\n activeTab === 'publication' &&\r\n applicationPublication.assignedTenants.length === 0\r\n ) {\r\n applicationPublication.loadPublicationData(appId!);\r\n }\r\n if (activeTab === 'requests') {\r\n accessRequests.loadRequests();\r\n }\r\n }, [\r\n activeTab,\r\n applicationDetail.application,\r\n applicationPublication.assignedTenants.length,\r\n ]);\r\n\r\n const tabs = [\r\n { id: 'info' as const, label: t('applicationDetail.tabs.info'), icon: Settings },\r\n { id: 'modules' as const, label: t('applicationDetail.tabs.modules'), icon: Layers },\r\n { id: 'permissions' as const, label: t('applicationDetail.tabs.permissions'), icon: Shield },\r\n { id: 'roles' as const, label: t('applicationDetail.tabs.roles'), icon: Users },\r\n { id: 'publication' as const, label: t('applicationDetail.tabs.publication'), icon: Globe },\r\n { id: 'requests' as const, label: t('applicationDetail.tabs.requests'), icon: Inbox },\r\n ];\r\n\r\n // Loading state\r\n if (applicationDetail.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 // Error or not found\r\n if (applicationDetail.error || !applicationDetail.application) {\r\n return (\r\n <div className=\"text-center py-12\">\r\n <AlertCircle className=\"w-12 h-12 text-[var(--error-text)] mx-auto mb-4\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {applicationDetail.error || t('applicationDetail.notFound')}\r\n </p>\r\n <button\r\n onClick={() => navigate('/administration/applications')}\r\n className=\"mt-4 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)]\"\r\n >\r\n {t('applicationDetail.backToList')}\r\n </button>\r\n </div>\r\n );\r\n }\r\n\r\n const permissionsLoaded = applicationPermissions.permissions.length > 0 || activeTab === 'permissions' || activeTab === 'roles';\r\n const publicationLoaded = applicationPublication.assignedTenants.length > 0 || activeTab === 'publication';\r\n\r\n const statsCards = [\r\n {\r\n label: t('applicationDetail.stats.modules'),\r\n value: applicationDetail.application.modules?.length || 0,\r\n color: 'blue' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.permissions'),\r\n value: permissionsLoaded ? applicationPermissions.permissions.length : '—',\r\n color: 'green' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.rolesWithAccess'),\r\n value: permissionsLoaded ? applicationPermissions.rolesWithAppAccess.length : '—',\r\n color: 'purple' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.assignedTenants'),\r\n value: publicationLoaded ? filteredAssignedTenants.length : '—',\r\n color: 'yellow' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.status'),\r\n value: applicationDetail.application.isActive ? t('common:active') : t('common:inactive'),\r\n color: applicationDetail.application.isActive ? 'green' : 'neutral',\r\n },\r\n ];\r\n\r\n const colorClasses: Record<string, string> = {\r\n blue: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n green: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n yellow: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n red: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\r\n purple: 'bg-[var(--accent-bg)] text-[var(--accent-text)] border-[var(--color-accent-300)]',\r\n neutral: 'bg-[var(--bg-secondary)] text-[var(--text-primary)] border-[var(--border-color)]',\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('breadcrumb.admin', { ns: 'navigation' }), href: '/administration' },\r\n { label: t('applications.title'), href: '/administration/applications' },\r\n { label: applicationDetail.application.label },\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center gap-4\">\r\n <button\r\n onClick={() => navigate('/administration/applications')}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n aria-label={t('common:back')}\r\n >\r\n <ArrowLeft className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n <div className=\"flex items-center gap-3\">\r\n {renderLucideIcon(applicationDetail.application.icon, 'w-5 h-5')}\r\n <div className=\"flex-1\">\r\n <h1 className=\"text-xl sm:text-2xl font-bold text-[var(--text-primary)]\">\r\n {applicationDetail.application.label}\r\n </h1>\r\n {applicationDetail.application.description && (\r\n <p className=\"text-sm sm:text-base text-[var(--text-secondary)]\">\r\n {applicationDetail.application.description}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 ml-auto\">\r\n <span\r\n className={`px-3 py-1 rounded-[var(--radius-badge)] text-sm font-medium ${\r\n applicationDetail.application.isActive\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)]'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)] border border-[var(--border-color)]'\r\n }`}\r\n >\r\n {applicationDetail.application.isActive ? t('common:active') : t('common:inactive')}\r\n </span>\r\n {canToggleStatus && (\r\n <button\r\n onClick={() => applicationDetail.handleToggleStatus(appId!)}\r\n disabled={applicationDetail.saving}\r\n className={`inline-flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-colors ${\r\n applicationDetail.application.isActive\r\n ? 'bg-[var(--error-bg)] text-[var(--error-text)] border border-[var(--error-border)] hover:bg-[var(--error-border)]'\r\n : 'bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)] hover:bg-[var(--success-border)]'\r\n } disabled:opacity-50`}\r\n >\r\n {applicationDetail.saving && (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n )}\r\n {!applicationDetail.saving && applicationDetail.application.isActive && (\r\n <PowerOff className=\"w-4 h-4\" />\r\n )}\r\n {!applicationDetail.saving && !applicationDetail.application.isActive && (\r\n <Power className=\"w-4 h-4\" />\r\n )}\r\n {applicationDetail.application.isActive\r\n ? t('applicationDetail.deactivate')\r\n : t('applicationDetail.activate')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Alerts */}\r\n {applicationDetail.error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] text-[var(--error-text)] flex items-center gap-2\">\r\n <AlertTriangle className=\"w-5 h-5 flex-shrink-0\" />\r\n {applicationDetail.error}\r\n </div>\r\n )}\r\n {applicationDetail.success && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)] text-[var(--success-text)] flex items-center gap-2\">\r\n <CheckCircle className=\"w-5 h-5 flex-shrink-0\" />\r\n {applicationDetail.success}\r\n </div>\r\n )}\r\n\r\n {/* Stats cards */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4\">\r\n {statsCards.map((stat) => (\r\n <div\r\n key={stat.label}\r\n className={`rounded-[var(--radius-card)] p-4 text-center border ${colorClasses[stat.color]}`}\r\n >\r\n <div className=\"text-2xl font-bold\">{stat.value}</div>\r\n <div className=\"text-sm opacity-80\">{stat.label}</div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {/* Tabs */}\r\n <div\r\n className=\"flex gap-1 p-1 overflow-x-auto bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)]\"\r\n role=\"tablist\"\r\n aria-label={t('applicationDetail.tabs.label', 'Application tabs')}\r\n >\r\n {tabs.map((tab) => {\r\n const Icon = tab.icon;\r\n const isActive = activeTab === tab.id;\r\n return (\r\n <button\r\n key={tab.id}\r\n role=\"tab\"\r\n aria-selected={isActive}\r\n aria-controls={`tabpanel-${tab.id}`}\r\n onClick={() => setActiveTab(tab.id)}\r\n className={`flex items-center gap-2 px-4 py-2 whitespace-nowrap rounded-[var(--radius-button)] font-medium transition-colors ${\r\n isActive\r\n ? 'bg-[var(--color-accent-600)] text-white'\r\n : 'text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <Icon className=\"w-4 h-4\" />\r\n {tab.label}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n\r\n {/* Tab content */}\r\n <div\r\n className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4 sm:p-6\"\r\n role=\"tabpanel\"\r\n id={`tabpanel-${activeTab}`}\r\n aria-labelledby={activeTab}\r\n >\r\n {/* Info Tab */}\r\n {activeTab === 'info' && (\r\n <ApplicationInfoTab\r\n formData={applicationDetail.formData}\r\n setFormData={applicationDetail.setFormData}\r\n application={applicationDetail.application!}\r\n saving={applicationDetail.saving}\r\n onSubmit={() =>\r\n applicationDetail.handleSaveInfo(appId!, applicationDetail.formData)\r\n }\r\n />\r\n )}\r\n\r\n {/* Modules Tab */}\r\n {activeTab === 'modules' && (\r\n <ApplicationModulesTab\r\n application={applicationDetail.application!}\r\n expandedModules={applicationModules.expandedModules}\r\n moduleSections={applicationModules.moduleSections}\r\n loadingSections={applicationModules.loadingSections}\r\n reordering={applicationModules.reordering}\r\n editingModule={applicationModules.editingModule}\r\n moduleFormData={applicationModules.moduleFormData}\r\n showModuleForm={applicationModules.showModuleForm}\r\n saving={applicationDetail.saving}\r\n onToggleExpand={(moduleId) =>\r\n applicationModules.toggleModuleExpand(appId!, moduleId)\r\n }\r\n onStartEdit={applicationModules.startEditModule}\r\n onSaveModule={async () => {\r\n await applicationModules.handleSaveModule(\r\n appId!,\r\n applicationModules.editingModule!.id,\r\n applicationModules.moduleFormData\r\n );\r\n applicationDetail.setSuccess(t('applicationDetail.success.moduleUpdated'));\r\n await applicationDetail.loadApplication(appId!);\r\n }}\r\n onCancelEdit={() => {\r\n applicationModules.setShowModuleForm(false);\r\n applicationModules.setEditingModule(null);\r\n }}\r\n onModulesReorder={async (modules) => {\r\n await applicationModules.handleModulesReorder(appId!, modules);\r\n await applicationDetail.loadApplication(appId!);\r\n }}\r\n onSectionsReorder={(moduleId, sections) =>\r\n applicationModules.handleSectionsReorder(appId!, moduleId, sections)\r\n }\r\n setModuleFormData={(value) => applicationModules.setModuleFormData(typeof value === 'function' ? value(applicationModules.moduleFormData) : value)}\r\n />\r\n )}\r\n\r\n {/* Permissions Tab */}\r\n {activeTab === 'permissions' && (\r\n <ApplicationPermissionsTab\r\n application={applicationDetail.application!}\r\n permissions={applicationPermissions.permissions}\r\n permissionsWithRoles={applicationPermissions.permissionsWithRoles}\r\n />\r\n )}\r\n\r\n {/* Roles Tab */}\r\n {activeTab === 'roles' && (\r\n <ApplicationAccessTab\r\n rolesWithAppAccess={applicationPermissions.rolesWithAppAccess}\r\n onNavigateToRole={(roleId) =>\r\n navigate(`/administration/permissions/roles/${roleId}`)\r\n }\r\n />\r\n )}\r\n\r\n {/* Publication Tab */}\r\n {activeTab === 'publication' && (\r\n <ApplicationPublicationTab\r\n application={applicationDetail.application!}\r\n assignedTenants={filteredAssignedTenants}\r\n availableTenants={filteredAvailableTenants}\r\n showAssignModal={applicationPublication.showAssignModal}\r\n selectedTenantIds={applicationPublication.selectedTenantIds}\r\n selectedAccessLevel={applicationPublication.selectedAccessLevel}\r\n tenantSearch={applicationPublication.tenantSearch}\r\n showCustomizeDrawer={applicationPublication.showCustomizeDrawer}\r\n customizingTenant={applicationPublication.customizingTenant}\r\n bulkAccessMode={applicationPublication.bulkAccessMode}\r\n bulkModules={applicationPublication.bulkModules}\r\n bulkExpandedModules={applicationPublication.bulkExpandedModules}\r\n loadingBulkModules={applicationPublication.loadingBulkModules}\r\n isUpdateMode={applicationPublication.isUpdateMode}\r\n updateMergeMode={applicationPublication.updateMergeMode}\r\n showConfirmRemovalDialog={applicationPublication.showConfirmRemovalDialog}\r\n pendingRemovals={applicationPublication.pendingRemovals}\r\n saving={applicationDetail.saving}\r\n includePersonalTenants={applicationPublication.includePersonalTenants}\r\n isInDefaultPersonalTemplate={applicationPublication.isInDefaultPersonalTemplate}\r\n onAddTenant={() => {\r\n applicationPublication.loadPublicationData(appId!);\r\n applicationPublication.setShowAssignModal(true);\r\n }}\r\n onRemoveTenant={(tenantId) =>\r\n applicationPublication.handleRemoveTenant(appId!, tenantId, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.removed'));\r\n })\r\n }\r\n onUpdateAccessLevel={(tenantId, accessLevel) =>\r\n applicationPublication.handleUpdateAccessLevel(appId!, tenantId, accessLevel, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.updated'));\r\n })\r\n }\r\n onCustomizeTenant={(tenant) => {\r\n applicationPublication.setCustomizingTenant(tenant);\r\n applicationPublication.setShowCustomizeDrawer(true);\r\n }}\r\n onCloseCustomizeDrawer={() => {\r\n applicationPublication.setShowCustomizeDrawer(false);\r\n applicationPublication.setCustomizingTenant(null);\r\n applicationPublication.loadPublicationData(appId!);\r\n }}\r\n onAssignTenants={() =>\r\n applicationPublication.handleAssignTenants(appId!, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.assigned'));\r\n applicationPublication.loadPublicationData(appId!);\r\n })\r\n }\r\n onUpdateTenants={() =>\r\n applicationPublication.handleUpdateTenants(appId!, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.updated'));\r\n applicationPublication.loadPublicationData(appId!);\r\n })\r\n }\r\n onExecuteUpdateTenants={() =>\r\n applicationPublication.executeUpdateTenants(appId!, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.updated'));\r\n applicationPublication.loadPublicationData(appId!);\r\n })\r\n }\r\n onCancelRemovalDialog={() => {\r\n applicationPublication.setShowConfirmRemovalDialog(false);\r\n applicationPublication.setUpdateMergeMode('merge');\r\n }}\r\n setShowAssignModal={applicationPublication.setShowAssignModal}\r\n setSelectedTenantIds={applicationPublication.setSelectedTenantIds}\r\n setSelectedAccessLevel={applicationPublication.setSelectedAccessLevel}\r\n setTenantSearch={applicationPublication.setTenantSearch}\r\n setBulkAccessMode={applicationPublication.setBulkAccessMode}\r\n setIsUpdateMode={applicationPublication.setIsUpdateMode}\r\n setUpdateMergeMode={applicationPublication.setUpdateMergeMode}\r\n onToggleTenantSelection={applicationPublication.toggleTenantSelection}\r\n onSelectAllFilteredTenants={applicationPublication.selectAllFilteredTenants}\r\n onClearTenantSelection={applicationPublication.clearTenantSelection}\r\n setIncludePersonalTenants={applicationPublication.setIncludePersonalTenants}\r\n onLoadBulkModules={() => applicationPublication.loadBulkModules(appId!)}\r\n onToggleBulkModuleExpand={applicationPublication.toggleBulkModuleExpand}\r\n onToggleBulkModule={applicationPublication.toggleBulkModule}\r\n onToggleBulkSection={applicationPublication.toggleBulkSection}\r\n onGetBulkModuleCheckState={applicationPublication.getBulkModuleCheckState}\r\n onGetBulkStats={applicationPublication.getBulkStats}\r\n onSelectAllBulkModules={applicationPublication.selectAllBulkModules}\r\n onClearBulkModules={applicationPublication.clearBulkModules}\r\n appId={appId!}\r\n />\r\n )}\r\n\r\n {/* Access Requests Tab */}\r\n {activeTab === 'requests' && (\r\n <AccessRequestsListTab\r\n requests={accessRequests.requests}\r\n loading={accessRequests.loading}\r\n onReload={() => accessRequests.loadRequests()}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["renderLucideIcon","icon","className","IconComponent","LucideIcons","jsx","Icon","useApplicationDetail","useTranslation","application","setApplication","useState","loading","setLoading","saving","setSaving","error","setError","success","setSuccess","formData","setFormData","loadApplication","useCallback","appId","data","adminApi","err","handleSaveInfo","updateData","handleToggleStatus","useApplicationModules","expandedModules","setExpandedModules","moduleSections","setModuleSections","loadingSections","setLoadingSections","reordering","setReordering","editingModule","setEditingModule","moduleFormData","setModuleFormData","showModuleForm","setShowModuleForm","toggleModuleExpand","moduleId","isExpanding","prev","newSet","sections","handleSaveModule","resetModuleForm","handleModulesReorder","reorderedModules","newModules","m","index","handleSectionsReorder","reorderedSections","newSections","s","reloadErr","startEditModule","module","moduleCount","getPermissionWithRoles","perm","matrixRoles","allRoles","rolesWithPerm","mr","r","useApplicationPermissions","roles","setRoles","permissions","setPermissions","permissionsWithRoles","setPermissionsWithRoles","loadPermissionsData","matrix","appPermissionPrefix","appPermissions","p","permWithRoles","loadRolesData","rolesWithAppAccess","useMemo","roleAccessMap","permission","permRoles","role","a","b","updateModuleAssignment","newIsAssigned","updateSectionAssignment","sectionId","allSectionsAssigned","assignAllSections","clearAllSections","useApplicationPublication","assignedTenants","setAssignedTenants","availableTenants","setAvailableTenants","showAssignModal","setShowAssignModal","selectedTenantIds","setSelectedTenantIds","selectedAccessLevel","setSelectedAccessLevel","tenantSearch","setTenantSearch","showCustomizeDrawer","setShowCustomizeDrawer","customizingTenant","setCustomizingTenant","bulkAccessMode","setBulkAccessMode","bulkModules","setBulkModules","bulkExpandedModules","setBulkExpandedModules","loadingBulkModules","setLoadingBulkModules","isUpdateMode","setIsUpdateMode","updateMergeMode","setUpdateMergeMode","showConfirmRemovalDialog","setShowConfirmRemovalDialog","pendingRemovals","setPendingRemovals","includePersonalTenants","setIncludePersonalTenants","isInDefaultPersonalTemplate","setIsInDefaultPersonalTemplate","loadPublicationData","assigned","availableResponse","loadBulkModules","appModules","moduleNodes","appModule","sectionNodes","section","toggleBulkModuleExpand","toggleBulkModule","toggleBulkSection","getBulkModuleCheckState","assignedCount","getBulkStats","totalModules","assignedModules","totalSections","sum","assignedSections","selectAllBulkModules","clearBulkModules","toggleTenantSelection","tenantId","id","selectAllFilteredTenants","filteredIds","t","matchesSearch","matchesType","clearTenantSelection","executeUpdateTenants","onSuccess","request","handleAssignTenants","handleUpdateTenants","removedModulesCount","removedSectionsCount","currentModules","currentSections","targetModuleIds","targetSectionIds","handleRemoveTenant","handleUpdateAccessLevel","accessLevel","ApplicationInfoTab","onSubmit","jsxs","e","Loader2","Save","SortableItemWrapper","disabled","children","attributes","listeners","setNodeRef","transform","transition","isDragging","useSortable","style","CSS","dragHandle","GripVertical","SortableList","items","onReorder","renderItem","setActiveId","sensors","useSensors","useSensor","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","handleDragEnd","event","active","over","oldIndex","item","newIndex","newItems","arrayMove","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","renderModuleSections","onSectionsReorder","sectionDragHandle","Layers","ApplicationModulesTab","onToggleExpand","onStartEdit","onSaveModule","onCancelEdit","onModulesReorder","ChevronDown","ChevronRight","Edit","ApplicationPermissionsTab","ApplicationAccessTab","onNavigateToRole","rolePermissions","Shield","Eye","getAccessLevelColorClass","getLabelKey","level","useTenantIconForType","getIconForType","useTenantTypeSettings","tenantType","typeInfo","getLucideIcon","colors","getColorClasses","ApplicationPublicationTab","getTenantIconInfo","Globe","tenant","bgClass","colorClass","statusBgClass","VALID_TABS","ApplicationDetailPage","useParams","navigate","useNavigate","hasPermission","useAuth","currentTenant","isGlobalView","useTenant","canToggleStatus","activeTab","setActiveTab","useTabNavigation","applicationDetail","applicationModules","applicationPermissions","applicationPublication","accessRequests","useAccessRequests","filteredAvailableTenants","filteredAssignedTenants","useEffect","tabs","Settings","Users","Inbox","AlertCircle","permissionsLoaded","publicationLoaded","statsCards","colorClasses","Breadcrumb","ArrowLeft","PowerOff","Power","AlertTriangle","CheckCircle","stat","tab","isActive","modules","value","roleId","AccessRequestsListTab"],"mappings":"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"}
1
+ {"version":3,"file":"ApplicationDetailPage-Caizuyn2.js","sources":["../../src/utils/renderLucideIcon.tsx","../../src/hooks/useApplicationDetail.ts","../../src/hooks/useApplicationModules.ts","../../src/hooks/useApplicationPermissions.ts","../../src/hooks/useApplicationPublication.ts","../../src/components/platform/administration/applications/ApplicationInfoTab.tsx","../../src/components/ui/SortableList.tsx","../../src/components/platform/administration/applications/ApplicationModulesTab.tsx","../../src/components/platform/administration/applications/ApplicationPermissionsTab.tsx","../../src/components/platform/administration/applications/ApplicationAccessTab.tsx","../../src/components/platform/administration/applications/ApplicationPublicationTab.tsx","../../src/pages/platform/administration/applications/ApplicationDetailPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport * as LucideIcons from 'lucide-react';\r\nimport type { LucideIcon } from 'lucide-react';\r\n\r\n/**\r\n * Renders a Lucide icon by name string or LucideIcon component.\r\n * Returns null if the icon name is invalid or null.\r\n */\r\nexport function renderLucideIcon(\r\n icon: LucideIcon | string | null | undefined,\r\n className = 'w-4 h-4',\r\n): ReactElement | null {\r\n if (!icon) return null;\r\n\r\n if (typeof icon === 'string') {\r\n const icons = LucideIcons as unknown as Record<string, LucideIcon>;\r\n const IconComponent = icons[icon];\r\n if (!IconComponent) return null;\r\n return <IconComponent className={className} />;\r\n }\r\n\r\n const Icon = icon;\r\n return <Icon className={className} />;\r\n}\r\n","import { useState, useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n adminApi,\r\n type ApplicationDetailDto,\r\n type UpdateApplicationRequest,\r\n} from '@/services/api/adminApi';\r\n\r\nexport interface ApplicationFormData {\r\n label: string;\r\n description: string;\r\n icon: string;\r\n route: string;\r\n displayOrder: number;\r\n}\r\n\r\nexport interface UseApplicationDetailReturn {\r\n application: ApplicationDetailDto | null;\r\n loading: boolean;\r\n saving: boolean;\r\n error: string | null;\r\n success: string | null;\r\n formData: ApplicationFormData;\r\n setFormData: React.Dispatch<React.SetStateAction<ApplicationFormData>>;\r\n setError: (error: string | null) => void;\r\n setSuccess: (success: string | null) => void;\r\n loadApplication: (appId: string) => Promise<void>;\r\n handleSaveInfo: (appId: string, data: ApplicationFormData) => Promise<void>;\r\n handleToggleStatus: (appId: string) => Promise<void>;\r\n}\r\n\r\nexport function useApplicationDetail(): UseApplicationDetailReturn {\r\n const { t } = useTranslation('admin');\r\n\r\n const [application, setApplication] = useState<ApplicationDetailDto | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n const [saving, setSaving] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState<string | null>(null);\r\n\r\n const [formData, setFormData] = useState<ApplicationFormData>({\r\n label: '',\r\n description: '',\r\n icon: '',\r\n route: '',\r\n displayOrder: 0,\r\n });\r\n\r\n const loadApplication = useCallback(async (appId: string) => {\r\n if (!appId) return;\r\n\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const data = await adminApi.applications.getById(appId);\r\n setApplication(data);\r\n setFormData({\r\n label: data.label,\r\n description: data.description || '',\r\n icon: data.icon || '',\r\n route: data.route || '',\r\n displayOrder: data.displayOrder,\r\n });\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('applicationDetail.errors.loadFailed'));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n const handleSaveInfo = useCallback(async (appId: string, data: ApplicationFormData) => {\r\n if (!appId || !application) return;\r\n\r\n setSaving(true);\r\n setError(null);\r\n setSuccess(null);\r\n\r\n try {\r\n const updateData: UpdateApplicationRequest = {\r\n label: data.label,\r\n description: data.description || undefined,\r\n icon: data.icon || undefined,\r\n route: data.route || undefined,\r\n displayOrder: data.displayOrder,\r\n };\r\n\r\n await adminApi.applications.update(appId, updateData);\r\n setSuccess(t('applicationDetail.success.saved'));\r\n await loadApplication(appId);\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('applicationDetail.errors.saveFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [application, t, loadApplication]);\r\n\r\n const handleToggleStatus = useCallback(async (appId: string) => {\r\n if (!appId || !application) return;\r\n\r\n setSaving(true);\r\n setError(null);\r\n setSuccess(null);\r\n\r\n try {\r\n if (application.isActive) {\r\n await adminApi.applications.deactivate(appId);\r\n } else {\r\n await adminApi.applications.activate(appId);\r\n }\r\n\r\n setSuccess(\r\n application.isActive\r\n ? t('applicationDetail.success.deactivated')\r\n : t('applicationDetail.success.activated')\r\n );\r\n await loadApplication(appId);\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : t('applicationDetail.errors.toggleFailed'));\r\n } finally {\r\n setSaving(false);\r\n }\r\n }, [application, t, loadApplication]);\r\n\r\n return {\r\n application,\r\n loading,\r\n saving,\r\n error,\r\n success,\r\n formData,\r\n setFormData,\r\n setError,\r\n setSuccess,\r\n loadApplication,\r\n handleSaveInfo,\r\n handleToggleStatus,\r\n };\r\n}\r\n","import { useState, useCallback } from 'react';\r\nimport {\r\n adminApi,\r\n type ApplicationModuleDto,\r\n type ModuleSectionDto,\r\n} from '@/services/api/adminApi';\r\n\r\nexport interface ModuleFormData {\r\n code: string;\r\n label: string;\r\n description: string;\r\n icon: string;\r\n route: string;\r\n displayOrder: number;\r\n}\r\n\r\nexport interface UseApplicationModulesReturn {\r\n expandedModules: Set<string>;\r\n moduleSections: Map<string, ModuleSectionDto[]>;\r\n loadingSections: Set<string>;\r\n reordering: boolean;\r\n editingModule: ApplicationModuleDto | null;\r\n moduleFormData: ModuleFormData;\r\n showModuleForm: boolean;\r\n toggleModuleExpand: (appId: string, moduleId: string) => Promise<void>;\r\n handleSaveModule: (appId: string, moduleId: string, data: ModuleFormData) => Promise<void>;\r\n handleModulesReorder: (appId: string, modules: (ApplicationModuleDto & { id: string })[]) => Promise<void>;\r\n handleSectionsReorder: (appId: string, moduleId: string, sections: ModuleSectionDto[]) => Promise<void>;\r\n startEditModule: (module: ApplicationModuleDto) => void;\r\n resetModuleForm: (moduleCount?: number) => void;\r\n setShowModuleForm: (show: boolean) => void;\r\n setEditingModule: (module: ApplicationModuleDto | null) => void;\r\n setModuleFormData: (data: ModuleFormData) => void;\r\n}\r\n\r\nexport function useApplicationModules(): UseApplicationModulesReturn {\r\n const [expandedModules, setExpandedModules] = useState<Set<string>>(new Set());\r\n const [moduleSections, setModuleSections] = useState<Map<string, ModuleSectionDto[]>>(new Map());\r\n const [loadingSections, setLoadingSections] = useState<Set<string>>(new Set());\r\n const [reordering, setReordering] = useState(false);\r\n\r\n const [editingModule, setEditingModule] = useState<ApplicationModuleDto | null>(null);\r\n const [moduleFormData, setModuleFormData] = useState<ModuleFormData>({\r\n code: '',\r\n label: '',\r\n description: '',\r\n icon: '',\r\n route: '',\r\n displayOrder: 0,\r\n });\r\n const [showModuleForm, setShowModuleForm] = useState(false);\r\n\r\n const toggleModuleExpand = useCallback(async (appId: string, moduleId: string) => {\r\n const isExpanding = !expandedModules.has(moduleId);\r\n\r\n setExpandedModules(prev => {\r\n const newSet = new Set(prev);\r\n if (newSet.has(moduleId)) {\r\n newSet.delete(moduleId);\r\n } else {\r\n newSet.add(moduleId);\r\n }\r\n return newSet;\r\n });\r\n\r\n // Load sections if expanding and not already loaded\r\n if (isExpanding && !moduleSections.has(moduleId)) {\r\n setLoadingSections(prev => new Set(prev).add(moduleId));\r\n try {\r\n const sections = await adminApi.applications.getModuleSections(appId, moduleId);\r\n setModuleSections(prev => new Map(prev).set(moduleId, sections));\r\n } catch (err) {\r\n console.error('Failed to load sections:', err);\r\n } finally {\r\n setLoadingSections(prev => {\r\n const newSet = new Set(prev);\r\n newSet.delete(moduleId);\r\n return newSet;\r\n });\r\n }\r\n }\r\n }, [expandedModules, moduleSections]);\r\n\r\n const handleSaveModule = useCallback(async (appId: string, moduleId: string, data: ModuleFormData) => {\r\n try {\r\n await adminApi.applications.updateModule(appId, moduleId, {\r\n label: data.label,\r\n description: data.description || undefined,\r\n icon: data.icon || undefined,\r\n route: data.route || undefined,\r\n displayOrder: data.displayOrder,\r\n });\r\n setShowModuleForm(false);\r\n setEditingModule(null);\r\n resetModuleForm();\r\n } catch (err) {\r\n console.error('Failed to save module:', err);\r\n throw err;\r\n }\r\n }, []);\r\n\r\n const handleModulesReorder = useCallback(async (appId: string, reorderedModules: (ApplicationModuleDto & { id: string })[]) => {\r\n // Optimistic update\r\n const newModules = reorderedModules.map((m, index) => ({ ...m, displayOrder: index }));\r\n\r\n setReordering(true);\r\n try {\r\n await adminApi.applications.reorderModules(appId, newModules.map((m, index) => ({ id: m.id, displayOrder: index })));\r\n } catch (err) {\r\n console.error('Failed to reorder modules:', err);\r\n throw err;\r\n } finally {\r\n setReordering(false);\r\n }\r\n }, []);\r\n\r\n const handleSectionsReorder = useCallback(async (appId: string, moduleId: string, reorderedSections: ModuleSectionDto[]) => {\r\n // Optimistic update\r\n const newSections = reorderedSections.map((s, index) => ({ ...s, displayOrder: index }));\r\n setModuleSections(prev => new Map(prev).set(moduleId, newSections));\r\n\r\n setReordering(true);\r\n try {\r\n await adminApi.applications.reorderSections(appId, moduleId, newSections.map((s, index) => ({ id: s.id, displayOrder: index })));\r\n } catch (err) {\r\n console.error('Failed to reorder sections:', err);\r\n // Reload sections on error\r\n try {\r\n const sections = await adminApi.applications.getModuleSections(appId, moduleId);\r\n setModuleSections(prev => new Map(prev).set(moduleId, sections));\r\n } catch (reloadErr) {\r\n console.error('Failed to reload sections:', reloadErr);\r\n }\r\n throw err;\r\n } finally {\r\n setReordering(false);\r\n }\r\n }, []);\r\n\r\n const startEditModule = useCallback((module: ApplicationModuleDto) => {\r\n setEditingModule(module);\r\n setModuleFormData({\r\n code: module.code,\r\n label: module.label,\r\n description: module.description || '',\r\n icon: module.icon || '',\r\n route: module.route || '',\r\n displayOrder: module.displayOrder,\r\n });\r\n setShowModuleForm(true);\r\n }, []);\r\n\r\n const resetModuleForm = useCallback((moduleCount?: number) => {\r\n setModuleFormData({\r\n code: '',\r\n label: '',\r\n description: '',\r\n icon: '',\r\n route: '',\r\n displayOrder: moduleCount || 0,\r\n });\r\n }, []);\r\n\r\n return {\r\n expandedModules,\r\n moduleSections,\r\n loadingSections,\r\n reordering,\r\n editingModule,\r\n moduleFormData,\r\n showModuleForm,\r\n toggleModuleExpand,\r\n handleSaveModule,\r\n handleModulesReorder,\r\n handleSectionsReorder,\r\n startEditModule,\r\n resetModuleForm,\r\n setShowModuleForm,\r\n setEditingModule,\r\n setModuleFormData,\r\n };\r\n}\r\n","import { useState, useCallback, useMemo } from 'react';\r\nimport { adminApi, type PermissionListDto, type RoleListDto, type MatrixRoleDto, type ApplicationDetailDto } from '@/services/api/adminApi';\r\n\r\nexport interface PermissionWithRoles {\r\n permission: PermissionListDto;\r\n roles: RoleListDto[];\r\n}\r\n\r\nexport interface RoleWithPermissions {\r\n role: RoleListDto;\r\n permissions: PermissionListDto[];\r\n}\r\n\r\nconst getPermissionWithRoles = (\r\n perm: PermissionListDto,\r\n matrixRoles: MatrixRoleDto[],\r\n allRoles: RoleListDto[]\r\n): PermissionWithRoles => {\r\n const rolesWithPerm = matrixRoles\r\n .filter(mr => mr.permissionIds.includes(perm.id))\r\n .map(mr => allRoles.find(r => r.id === mr.id)!)\r\n .filter(Boolean);\r\n return { permission: perm, roles: rolesWithPerm };\r\n};\r\n\r\nexport interface UseApplicationPermissionsReturn {\r\n roles: RoleListDto[];\r\n permissions: PermissionListDto[];\r\n permissionsWithRoles: PermissionWithRoles[];\r\n rolesWithAppAccess: RoleWithPermissions[];\r\n\r\n loadPermissionsData: (application: ApplicationDetailDto) => Promise<void>;\r\n loadRolesData: () => Promise<void>;\r\n}\r\n\r\nexport function useApplicationPermissions(): UseApplicationPermissionsReturn {\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [permissionsWithRoles, setPermissionsWithRoles] = useState<PermissionWithRoles[]>([]);\r\n\r\n const loadPermissionsData = useCallback(async (application: ApplicationDetailDto) => {\r\n try {\r\n const [matrix, allRoles] = await Promise.all([\r\n adminApi.permissions.getMatrix(),\r\n adminApi.roles.getAll(),\r\n ]);\r\n\r\n const appPermissionPrefix = `${application.code}.`.toLowerCase();\r\n const appPermissions = matrix.permissions.filter(p =>\r\n p.path.toLowerCase().startsWith(appPermissionPrefix)\r\n );\r\n\r\n setPermissions(appPermissions);\r\n setRoles(allRoles);\r\n\r\n const permWithRoles: PermissionWithRoles[] = appPermissions.map(perm =>\r\n getPermissionWithRoles(perm, matrix.roles, allRoles)\r\n );\r\n\r\n setPermissionsWithRoles(permWithRoles);\r\n } catch (err) {\r\n console.error('Failed to load permissions data:', err);\r\n throw err;\r\n }\r\n }, []);\r\n\r\n const loadRolesData = useCallback(async () => {\r\n try {\r\n const allRoles = await adminApi.roles.getAll();\r\n setRoles(allRoles);\r\n } catch (err) {\r\n console.error('Failed to load roles:', err);\r\n throw err;\r\n }\r\n }, []);\r\n\r\n const rolesWithAppAccess = useMemo<RoleWithPermissions[]>(() => {\r\n if (permissionsWithRoles.length === 0) return [];\r\n\r\n const roleAccessMap = new Map<string, { role: RoleListDto; permissions: PermissionListDto[] }>();\r\n\r\n permissionsWithRoles.forEach(({ permission, roles: permRoles }) => {\r\n permRoles.forEach(role => {\r\n if (!roleAccessMap.has(role.id)) {\r\n roleAccessMap.set(role.id, { role, permissions: [] });\r\n }\r\n roleAccessMap.get(role.id)!.permissions.push(permission);\r\n });\r\n });\r\n\r\n return Array.from(roleAccessMap.values()).sort((a, b) =>\r\n b.permissions.length - a.permissions.length\r\n );\r\n }, [permissionsWithRoles]);\r\n\r\n return {\r\n roles,\r\n permissions,\r\n permissionsWithRoles,\r\n rolesWithAppAccess,\r\n loadPermissionsData,\r\n loadRolesData,\r\n };\r\n}\r\n","import React, { useState, useCallback } from 'react';\r\nimport { adminApi } from '@/services/api/adminApi';\r\nimport type {\r\n ApplicationTenantDto,\r\n AvailableTenantForAppDto,\r\n ApplicationAccessLevel,\r\n BulkAssignTenantsRequest,\r\n} from '@/services/api/adminApi';\r\n\r\nconst updateModuleAssignment = (module: BulkModuleNode, moduleId: string): BulkModuleNode => {\r\n if (module.id !== moduleId) return module;\r\n const newIsAssigned = !module.isAssigned;\r\n return {\r\n ...module,\r\n isAssigned: newIsAssigned,\r\n sections: module.sections.map(s => ({ ...s, isAssigned: newIsAssigned })),\r\n };\r\n};\r\n\r\nconst updateSectionAssignment = (module: BulkModuleNode, moduleId: string, sectionId: string): BulkModuleNode => {\r\n if (module.id !== moduleId) return module;\r\n const newSections = module.sections.map(s =>\r\n s.id === sectionId ? { ...s, isAssigned: !s.isAssigned } : s\r\n );\r\n const allSectionsAssigned = newSections.every(s => s.isAssigned);\r\n return {\r\n ...module,\r\n isAssigned: allSectionsAssigned,\r\n sections: newSections,\r\n };\r\n};\r\n\r\nconst assignAllSections = (module: BulkModuleNode): BulkModuleNode => ({\r\n ...module,\r\n isAssigned: true,\r\n sections: module.sections.map(s => ({ ...s, isAssigned: true })),\r\n});\r\n\r\nconst clearAllSections = (module: BulkModuleNode): BulkModuleNode => ({\r\n ...module,\r\n isAssigned: false,\r\n sections: module.sections.map(s => ({ ...s, isAssigned: false })),\r\n});\r\n\r\n// Bulk operation interfaces\r\nexport interface BulkModuleNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n sections: BulkSectionNode[];\r\n}\r\n\r\nexport interface BulkSectionNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n}\r\n\r\nexport type BulkAccessMode = 'full' | 'custom';\r\n\r\nexport interface UseApplicationPublicationReturn {\r\n // State\r\n assignedTenants: ApplicationTenantDto[];\r\n availableTenants: AvailableTenantForAppDto[];\r\n showAssignModal: boolean;\r\n selectedTenantIds: string[];\r\n selectedAccessLevel: ApplicationAccessLevel;\r\n tenantSearch: string;\r\n showCustomizeDrawer: boolean;\r\n customizingTenant: ApplicationTenantDto | null;\r\n bulkAccessMode: BulkAccessMode;\r\n bulkModules: BulkModuleNode[];\r\n bulkExpandedModules: Set<string>;\r\n loadingBulkModules: boolean;\r\n isUpdateMode: boolean;\r\n updateMergeMode: 'merge' | 'replace';\r\n showConfirmRemovalDialog: boolean;\r\n pendingRemovals: { modules: number; sections: number };\r\n includePersonalTenants: boolean;\r\n isInDefaultPersonalTemplate: boolean;\r\n\r\n // Setters\r\n setAssignedTenants: React.Dispatch<React.SetStateAction<ApplicationTenantDto[]>>;\r\n setAvailableTenants: React.Dispatch<React.SetStateAction<AvailableTenantForAppDto[]>>;\r\n setShowAssignModal: React.Dispatch<React.SetStateAction<boolean>>;\r\n setSelectedTenantIds: React.Dispatch<React.SetStateAction<string[]>>;\r\n setSelectedAccessLevel: React.Dispatch<React.SetStateAction<ApplicationAccessLevel>>;\r\n setTenantSearch: React.Dispatch<React.SetStateAction<string>>;\r\n setShowCustomizeDrawer: React.Dispatch<React.SetStateAction<boolean>>;\r\n setCustomizingTenant: React.Dispatch<React.SetStateAction<ApplicationTenantDto | null>>;\r\n setBulkAccessMode: React.Dispatch<React.SetStateAction<BulkAccessMode>>;\r\n setBulkModules: React.Dispatch<React.SetStateAction<BulkModuleNode[]>>;\r\n setBulkExpandedModules: React.Dispatch<React.SetStateAction<Set<string>>>;\r\n setIsUpdateMode: React.Dispatch<React.SetStateAction<boolean>>;\r\n setUpdateMergeMode: React.Dispatch<React.SetStateAction<'merge' | 'replace'>>;\r\n setShowConfirmRemovalDialog: React.Dispatch<React.SetStateAction<boolean>>;\r\n setPendingRemovals: React.Dispatch<React.SetStateAction<{ modules: number; sections: number }>>;\r\n setIncludePersonalTenants: React.Dispatch<React.SetStateAction<boolean>>;\r\n\r\n // Publication operations\r\n loadPublicationData: (appId: string) => Promise<void>;\r\n loadBulkModules: (appId: string) => Promise<void>;\r\n\r\n // Bulk module operations\r\n toggleBulkModuleExpand: (moduleId: string) => void;\r\n toggleBulkModule: (moduleId: string) => void;\r\n toggleBulkSection: (moduleId: string, sectionId: string) => void;\r\n getBulkModuleCheckState: (module: BulkModuleNode) => 'checked' | 'unchecked' | 'indeterminate';\r\n getBulkStats: () => { totalModules: number; assignedModules: number; totalSections: number; assignedSections: number };\r\n selectAllBulkModules: () => void;\r\n clearBulkModules: () => void;\r\n\r\n // Tenant assignment operations\r\n toggleTenantSelection: (tenantId: string) => void;\r\n selectAllFilteredTenants: () => void;\r\n clearTenantSelection: () => void;\r\n\r\n // API operations\r\n handleAssignTenants: (appId: string, onSuccess?: () => void) => Promise<void>;\r\n handleUpdateTenants: (appId: string, onSuccess?: () => void) => Promise<void>;\r\n executeUpdateTenants: (appId: string, onSuccess?: () => void) => Promise<void>;\r\n handleRemoveTenant: (appId: string, tenantId: string, onSuccess?: () => void) => Promise<void>;\r\n handleUpdateAccessLevel: (appId: string, tenantId: string, accessLevel: ApplicationAccessLevel, onSuccess?: () => void) => Promise<void>;\r\n}\r\n\r\nexport function useApplicationPublication(): UseApplicationPublicationReturn {\r\n // Publication state\r\n const [assignedTenants, setAssignedTenants] = useState<ApplicationTenantDto[]>([]);\r\n const [availableTenants, setAvailableTenants] = useState<AvailableTenantForAppDto[]>([]);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [selectedTenantIds, setSelectedTenantIds] = useState<string[]>([]);\r\n const [selectedAccessLevel, setSelectedAccessLevel] = useState<ApplicationAccessLevel>('FullAccess');\r\n const [tenantSearch, setTenantSearch] = useState('');\r\n\r\n // Customize access drawer state\r\n const [showCustomizeDrawer, setShowCustomizeDrawer] = useState(false);\r\n const [customizingTenant, setCustomizingTenant] = useState<ApplicationTenantDto | null>(null);\r\n\r\n // Bulk customization state\r\n const [bulkAccessMode, setBulkAccessMode] = useState<BulkAccessMode>('full');\r\n const [bulkModules, setBulkModules] = useState<BulkModuleNode[]>([]);\r\n const [bulkExpandedModules, setBulkExpandedModules] = useState<Set<string>>(new Set());\r\n const [loadingBulkModules, setLoadingBulkModules] = useState(false);\r\n\r\n // Update mode state\r\n const [isUpdateMode, setIsUpdateMode] = useState(false);\r\n const [updateMergeMode, setUpdateMergeMode] = useState<'merge' | 'replace'>('merge');\r\n const [showConfirmRemovalDialog, setShowConfirmRemovalDialog] = useState(false);\r\n const [pendingRemovals, setPendingRemovals] = useState<{ modules: number; sections: number }>({ modules: 0, sections: 0 });\r\n\r\n // Personal tenant filter state\r\n const [includePersonalTenants, setIncludePersonalTenants] = useState(false);\r\n const [isInDefaultPersonalTemplate, setIsInDefaultPersonalTemplate] = useState(false);\r\n\r\n // Publication data loading\r\n const loadPublicationData = useCallback(async (appId: string) => {\r\n try {\r\n const [assigned, availableResponse] = await Promise.all([\r\n adminApi.applications.getTenants(appId),\r\n adminApi.applications.getAvailableTenants(appId),\r\n ]);\r\n setAssignedTenants(assigned);\r\n setAvailableTenants(availableResponse.tenants);\r\n setIsInDefaultPersonalTemplate(availableResponse.isInDefaultPersonalTemplate);\r\n } catch (err) {\r\n console.error('Failed to load publication data:', err);\r\n }\r\n }, []);\r\n\r\n // Load bulk modules for custom access mode\r\n const loadBulkModules = useCallback(async (appId: string) => {\r\n setLoadingBulkModules(true);\r\n try {\r\n const appModules = await adminApi.applications.getModules(appId);\r\n const moduleNodes: BulkModuleNode[] = [];\r\n\r\n for (const appModule of appModules) {\r\n const sections = await adminApi.applications.getModuleSections(appId, appModule.id);\r\n const sectionNodes: BulkSectionNode[] = sections.map(section => ({\r\n id: section.id,\r\n label: section.label,\r\n code: section.code,\r\n icon: section.icon,\r\n isAssigned: true,\r\n }));\r\n\r\n moduleNodes.push({\r\n id: appModule.id,\r\n label: appModule.label,\r\n code: appModule.code,\r\n icon: appModule.icon,\r\n isAssigned: true,\r\n sections: sectionNodes,\r\n });\r\n }\r\n\r\n setBulkModules(moduleNodes);\r\n } catch (err) {\r\n console.error('Failed to load bulk modules:', err);\r\n } finally {\r\n setLoadingBulkModules(false);\r\n }\r\n }, []);\r\n\r\n // Toggle bulk module expansion\r\n const toggleBulkModuleExpand = useCallback((moduleId: string) => {\r\n setBulkExpandedModules(prev => {\r\n const newSet = new Set(prev);\r\n if (newSet.has(moduleId)) {\r\n newSet.delete(moduleId);\r\n } else {\r\n newSet.add(moduleId);\r\n }\r\n return newSet;\r\n });\r\n }, []);\r\n\r\n // Toggle entire bulk module (all sections)\r\n const toggleBulkModule = useCallback((moduleId: string) => {\r\n setBulkModules(prev => prev.map(m => updateModuleAssignment(m, moduleId)));\r\n }, []);\r\n\r\n // Toggle bulk section within module\r\n const toggleBulkSection = useCallback((moduleId: string, sectionId: string) => {\r\n setBulkModules(prev => prev.map(m => updateSectionAssignment(m, moduleId, sectionId)));\r\n }, []);\r\n\r\n // Get checkbox state for bulk module (checked, unchecked, or indeterminate)\r\n const getBulkModuleCheckState = useCallback((module: BulkModuleNode): 'checked' | 'unchecked' | 'indeterminate' => {\r\n const assignedCount = module.sections.filter(s => s.isAssigned).length;\r\n if (assignedCount === 0) return 'unchecked';\r\n if (assignedCount === module.sections.length) return 'checked';\r\n return 'indeterminate';\r\n }, []);\r\n\r\n // Get statistics for bulk selection\r\n const getBulkStats = useCallback(() => {\r\n const totalModules = bulkModules.length;\r\n const assignedModules = bulkModules.filter(m => m.isAssigned || m.sections.some(s => s.isAssigned)).length;\r\n const totalSections = bulkModules.reduce((sum, m) => sum + m.sections.length, 0);\r\n const assignedSections = bulkModules.reduce((sum, m) => sum + m.sections.filter(s => s.isAssigned).length, 0);\r\n return { totalModules, assignedModules, totalSections, assignedSections };\r\n }, [bulkModules]);\r\n\r\n // Select all bulk modules\r\n const selectAllBulkModules = useCallback(() => {\r\n setBulkModules(prev => prev.map(m => assignAllSections(m)));\r\n }, []);\r\n\r\n // Clear all bulk module selections\r\n const clearBulkModules = useCallback(() => {\r\n setBulkModules(prev => prev.map(m => clearAllSections(m)));\r\n }, []);\r\n\r\n // Toggle tenant selection\r\n const toggleTenantSelection = useCallback((tenantId: string) => {\r\n setSelectedTenantIds(prev =>\r\n prev.includes(tenantId)\r\n ? prev.filter(id => id !== tenantId)\r\n : [...prev, tenantId]\r\n );\r\n }, []);\r\n\r\n // Select all filtered tenants (based on search and personal filter)\r\n const selectAllFilteredTenants = useCallback(() => {\r\n if (isUpdateMode) {\r\n const filteredIds = assignedTenants\r\n .filter(t => {\r\n const matchesSearch =\r\n t.tenantName.toLowerCase().includes(tenantSearch.toLowerCase()) ||\r\n t.tenantSlug.toLowerCase().includes(tenantSearch.toLowerCase());\r\n const matchesType = includePersonalTenants || t.tenantType !== 'Personal';\r\n return matchesSearch && matchesType;\r\n })\r\n .map(t => t.tenantId);\r\n setSelectedTenantIds(filteredIds);\r\n } else {\r\n const filteredIds = availableTenants\r\n .filter(t => {\r\n const matchesSearch =\r\n t.name.toLowerCase().includes(tenantSearch.toLowerCase()) ||\r\n t.slug.toLowerCase().includes(tenantSearch.toLowerCase());\r\n const matchesType = includePersonalTenants || t.type !== 'Personal';\r\n return matchesSearch && matchesType;\r\n })\r\n .map(t => t.id);\r\n setSelectedTenantIds(filteredIds);\r\n }\r\n }, [isUpdateMode, assignedTenants, availableTenants, tenantSearch, includePersonalTenants]);\r\n\r\n // Clear tenant selection\r\n const clearTenantSelection = useCallback(() => {\r\n setSelectedTenantIds([]);\r\n }, []);\r\n\r\n // Execute the actual update operation\r\n const executeUpdateTenants = useCallback(\r\n async (appId: string, onSuccess?: () => void) => {\r\n if (!appId || selectedTenantIds.length === 0) return;\r\n\r\n try {\r\n const request: BulkAssignTenantsRequest = {\r\n tenantIds: selectedTenantIds,\r\n accessLevel: selectedAccessLevel,\r\n accessMode: bulkAccessMode,\r\n mergeMode: updateMergeMode,\r\n };\r\n\r\n if (bulkAccessMode === 'custom') {\r\n request.moduleIds = bulkModules.filter(m => m.isAssigned).map(m => m.id);\r\n request.sectionIds = bulkModules.flatMap(m =>\r\n m.sections.filter(s => s.isAssigned).map(s => s.id)\r\n );\r\n }\r\n\r\n await adminApi.applications.bulkAssignTenants(appId, request);\r\n\r\n // Reset state\r\n setShowAssignModal(false);\r\n setSelectedTenantIds([]);\r\n setSelectedAccessLevel('FullAccess');\r\n setBulkAccessMode('full');\r\n setTenantSearch('');\r\n setIsUpdateMode(false);\r\n setUpdateMergeMode('merge');\r\n setShowConfirmRemovalDialog(false);\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to update tenant assignments:', err);\r\n throw err;\r\n }\r\n },\r\n [selectedTenantIds, selectedAccessLevel, bulkAccessMode, updateMergeMode, bulkModules, loadPublicationData]\r\n );\r\n\r\n // Assign application to tenants\r\n const handleAssignTenants = useCallback(\r\n async (appId: string, onSuccess?: () => void) => {\r\n if (!appId || selectedTenantIds.length === 0) return;\r\n\r\n try {\r\n const request: BulkAssignTenantsRequest = {\r\n tenantIds: selectedTenantIds,\r\n accessLevel: selectedAccessLevel,\r\n accessMode: bulkAccessMode,\r\n };\r\n\r\n if (bulkAccessMode === 'custom') {\r\n request.moduleIds = bulkModules.filter(m => m.isAssigned).map(m => m.id);\r\n request.sectionIds = bulkModules.flatMap(m =>\r\n m.sections.filter(s => s.isAssigned).map(s => s.id)\r\n );\r\n }\r\n\r\n await adminApi.applications.bulkAssignTenants(appId, request);\r\n\r\n // Reset state\r\n setShowAssignModal(false);\r\n setSelectedTenantIds([]);\r\n setSelectedAccessLevel('FullAccess');\r\n setBulkAccessMode('full');\r\n setTenantSearch('');\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to assign tenants:', err);\r\n throw err;\r\n }\r\n },\r\n [selectedTenantIds, selectedAccessLevel, bulkAccessMode, bulkModules, loadPublicationData]\r\n );\r\n\r\n // Update existing tenant assignments (with confirmation for replace mode)\r\n const handleUpdateTenants = useCallback(\r\n async (appId: string, onSuccess?: () => void) => {\r\n if (!appId || selectedTenantIds.length === 0) return;\r\n\r\n // Calculate potential removals in replace mode\r\n if (updateMergeMode === 'replace' && bulkAccessMode === 'custom') {\r\n let removedModulesCount = 0;\r\n let removedSectionsCount = 0;\r\n\r\n // Get current assignments for selected tenants and calculate diff\r\n for (const tenantId of selectedTenantIds) {\r\n try {\r\n const currentModules = await adminApi.tenants.getModules(tenantId);\r\n const currentSections = await adminApi.tenants.getSections(tenantId);\r\n\r\n const targetModuleIds = new Set(bulkModules.filter(m => m.isAssigned).map(m => m.id));\r\n const targetSectionIds = new Set(bulkModules.flatMap(m => m.sections.filter(s => s.isAssigned).map(s => s.id)));\r\n\r\n removedModulesCount += currentModules.filter(m => !targetModuleIds.has(m.moduleId)).length;\r\n removedSectionsCount += currentSections.filter(s => !targetSectionIds.has(s.sectionId)).length;\r\n } catch {\r\n // Ignore errors fetching current state\r\n }\r\n }\r\n\r\n // If there are removals, show confirmation dialog\r\n if (removedModulesCount > 0 || removedSectionsCount > 0) {\r\n setPendingRemovals({ modules: removedModulesCount, sections: removedSectionsCount });\r\n setShowConfirmRemovalDialog(true);\r\n return;\r\n }\r\n }\r\n\r\n await executeUpdateTenants(appId, onSuccess);\r\n },\r\n [\r\n selectedTenantIds,\r\n updateMergeMode,\r\n bulkAccessMode,\r\n bulkModules,\r\n executeUpdateTenants,\r\n ]\r\n );\r\n\r\n // Remove application from tenant\r\n const handleRemoveTenant = useCallback(\r\n async (appId: string, tenantId: string, onSuccess?: () => void) => {\r\n if (!appId) return;\r\n\r\n try {\r\n await adminApi.applications.removeFromTenant(appId, tenantId);\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to remove tenant:', err);\r\n throw err;\r\n }\r\n },\r\n [loadPublicationData]\r\n );\r\n\r\n // Update tenant access level\r\n const handleUpdateAccessLevel = useCallback(\r\n async (appId: string, tenantId: string, accessLevel: ApplicationAccessLevel, onSuccess?: () => void) => {\r\n if (!appId) return;\r\n\r\n try {\r\n await adminApi.applications.updateTenantAccessLevel(appId, tenantId, accessLevel);\r\n await loadPublicationData(appId);\r\n\r\n if (onSuccess) onSuccess();\r\n } catch (err) {\r\n console.error('Failed to update access level:', err);\r\n throw err;\r\n }\r\n },\r\n [loadPublicationData]\r\n );\r\n\r\n return {\r\n // State\r\n assignedTenants,\r\n availableTenants,\r\n showAssignModal,\r\n selectedTenantIds,\r\n selectedAccessLevel,\r\n tenantSearch,\r\n showCustomizeDrawer,\r\n customizingTenant,\r\n bulkAccessMode,\r\n bulkModules,\r\n bulkExpandedModules,\r\n loadingBulkModules,\r\n isUpdateMode,\r\n updateMergeMode,\r\n showConfirmRemovalDialog,\r\n pendingRemovals,\r\n includePersonalTenants,\r\n isInDefaultPersonalTemplate,\r\n\r\n // Setters\r\n setAssignedTenants,\r\n setAvailableTenants,\r\n setShowAssignModal,\r\n setSelectedTenantIds,\r\n setSelectedAccessLevel,\r\n setTenantSearch,\r\n setShowCustomizeDrawer,\r\n setCustomizingTenant,\r\n setBulkAccessMode,\r\n setBulkModules,\r\n setBulkExpandedModules,\r\n setIsUpdateMode,\r\n setUpdateMergeMode,\r\n setShowConfirmRemovalDialog,\r\n setPendingRemovals,\r\n setIncludePersonalTenants,\r\n\r\n // Operations\r\n loadPublicationData,\r\n loadBulkModules,\r\n toggleBulkModuleExpand,\r\n toggleBulkModule,\r\n toggleBulkSection,\r\n getBulkModuleCheckState,\r\n getBulkStats,\r\n selectAllBulkModules,\r\n clearBulkModules,\r\n toggleTenantSelection,\r\n selectAllFilteredTenants,\r\n clearTenantSelection,\r\n handleAssignTenants,\r\n handleUpdateTenants,\r\n executeUpdateTenants,\r\n handleRemoveTenant,\r\n handleUpdateAccessLevel,\r\n };\r\n}\r\n","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Save, Loader2 } from 'lucide-react';\r\nimport type { ApplicationDetailDto } from '@/services/api/adminApi';\r\n\r\ninterface ApplicationInfoTabProps {\r\n readonly formData: {\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n };\r\n readonly setFormData: React.Dispatch<\r\n React.SetStateAction<{\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n }>\r\n >;\r\n readonly application: ApplicationDetailDto;\r\n readonly saving: boolean;\r\n readonly onSubmit: (e: React.FormEvent) => Promise<void>;\r\n}\r\n\r\nexport function ApplicationInfoTab({\r\n formData,\r\n setFormData,\r\n application,\r\n saving,\r\n onSubmit,\r\n}: ApplicationInfoTabProps): React.ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <form onSubmit={onSubmit} className=\"space-y-6\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.code')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={application.code}\r\n disabled\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-tertiary)] border border-[var(--border-color)] text-[var(--text-muted)] cursor-not-allowed\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.label')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={formData.label}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, label: e.target.value }))\r\n }\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n required\r\n />\r\n </div>\r\n <div className=\"md:col-span-2\">\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.description')}\r\n </label>\r\n <textarea\r\n value={formData.description}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, description: e.target.value }))\r\n }\r\n rows={3}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.icon')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={formData.icon}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, icon: e.target.value }))\r\n }\r\n placeholder={t('applicationDetail.fields.icon')}\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.route')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={formData.route}\r\n onChange={e =>\r\n setFormData(prev => ({ ...prev, route: e.target.value }))\r\n }\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.displayOrder')}\r\n </label>\r\n <input\r\n type=\"number\"\r\n value={formData.displayOrder}\r\n onChange={e =>\r\n setFormData(prev => ({\r\n ...prev,\r\n displayOrder: parseInt(e.target.value) || 0,\r\n }))\r\n }\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--color-accent-600)] focus:border-transparent\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.fields.zone', 'Zone')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={application.zone || ''}\r\n disabled\r\n className=\"w-full px-4 py-2 rounded-[var(--radius-input)] bg-[var(--bg-tertiary)] border border-[var(--border-color)] text-[var(--text-muted)] cursor-not-allowed\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex justify-end\">\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"flex items-center gap-2 px-6 py-2 rounded-[var(--radius-button)] font-medium bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50\"\r\n >\r\n {saving ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Save className=\"w-4 h-4\" />\r\n )}\r\n {t('applicationDetail.actions.save')}\r\n </button>\r\n </div>\r\n </form>\r\n );\r\n}\r\n","import { useState, type ReactNode } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport {\r\n DndContext,\r\n closestCenter,\r\n KeyboardSensor,\r\n PointerSensor,\r\n useSensor,\r\n useSensors,\r\n type DragEndEvent,\r\n} from '@dnd-kit/core';\r\nimport {\r\n arrayMove,\r\n SortableContext,\r\n sortableKeyboardCoordinates,\r\n useSortable,\r\n verticalListSortingStrategy,\r\n} from '@dnd-kit/sortable';\r\nimport { CSS } from '@dnd-kit/utilities';\r\nimport { GripVertical } from 'lucide-react';\r\n\r\nexport interface SortableItem {\r\n id: string;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface SortableListProps<T extends SortableItem> {\r\n readonly items: T[];\r\n readonly onReorder: (items: T[]) => void;\r\n readonly renderItem: (item: T, dragHandle: ReactNode) => ReactNode;\r\n readonly disabled?: boolean;\r\n}\r\n\r\ninterface SortableItemWrapperProps {\r\n readonly id: string;\r\n readonly disabled?: boolean;\r\n readonly children: (dragHandle: ReactNode) => ReactNode;\r\n}\r\n\r\nfunction SortableItemWrapper({ id, disabled, children }: SortableItemWrapperProps) {\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n } = useSortable({ id, disabled });\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.5 : 1,\r\n zIndex: isDragging ? 1 : 0,\r\n };\r\n\r\n const dragHandle = !disabled ? (\r\n <button\r\n type=\"button\"\r\n className=\"p-1.5 rounded hover:bg-[var(--bg-hover)] cursor-grab active:cursor-grabbing text-[var(--text-muted)] hover:text-[var(--text-secondary)] transition-colors\"\r\n {...attributes}\r\n {...listeners}\r\n >\r\n <GripVertical className=\"w-4 h-4\" />\r\n </button>\r\n ) : null;\r\n\r\n return (\r\n <div ref={setNodeRef} style={style}>\r\n {children(dragHandle)}\r\n </div>\r\n );\r\n}\r\n\r\nexport function SortableList<T extends SortableItem>({\r\n items,\r\n onReorder,\r\n renderItem,\r\n disabled = false,\r\n}: SortableListProps<T>): ReactElement {\r\n const [, setActiveId] = useState<string | null>(null);\r\n\r\n const sensors = useSensors(\r\n useSensor(PointerSensor, {\r\n activationConstraint: {\r\n distance: 8,\r\n },\r\n }),\r\n useSensor(KeyboardSensor, {\r\n coordinateGetter: sortableKeyboardCoordinates,\r\n })\r\n );\r\n\r\n const handleDragEnd = (event: DragEndEvent) => {\r\n const { active, over } = event;\r\n setActiveId(null);\r\n\r\n if (over && active.id !== over.id) {\r\n const oldIndex = items.findIndex((item) => item.id === active.id);\r\n const newIndex = items.findIndex((item) => item.id === over.id);\r\n const newItems = arrayMove(items, oldIndex, newIndex);\r\n onReorder(newItems);\r\n }\r\n };\r\n\r\n return (\r\n <DndContext\r\n sensors={sensors}\r\n collisionDetection={closestCenter}\r\n onDragStart={(event) => setActiveId(event.active.id as string)}\r\n onDragEnd={handleDragEnd}\r\n >\r\n <SortableContext\r\n items={items.map((item) => item.id)}\r\n strategy={verticalListSortingStrategy}\r\n disabled={disabled}\r\n >\r\n <div className=\"space-y-2\">\r\n {items.map((item) => (\r\n <SortableItemWrapper key={item.id} id={item.id} disabled={disabled}>\r\n {(dragHandle) => renderItem(item, dragHandle)}\r\n </SortableItemWrapper>\r\n ))}\r\n </div>\r\n </SortableContext>\r\n </DndContext>\r\n );\r\n}\r\n\r\nexport default SortableList;\r\n","import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { ChevronDown, ChevronRight, Edit, Layers, Loader2, Save } from 'lucide-react';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\nimport { SortableList } from '@/components/ui/SortableList';\r\nimport { renderLucideIcon } from '@/utils/renderLucideIcon';\r\nimport type {\r\n ApplicationDetailDto,\r\n ApplicationModuleDto,\r\n ModuleSectionDto,\r\n} from '@/services/api/adminApi';\r\n\r\ninterface ApplicationModulesTabProps {\r\n readonly application: ApplicationDetailDto;\r\n readonly expandedModules: Set<string>;\r\n readonly moduleSections: Map<string, ModuleSectionDto[]>;\r\n readonly loadingSections: Set<string>;\r\n readonly reordering: boolean;\r\n readonly editingModule: ApplicationModuleDto | null;\r\n readonly moduleFormData: {\r\n readonly code: string;\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n };\r\n readonly showModuleForm: boolean;\r\n readonly saving: boolean;\r\n readonly onToggleExpand: (moduleId: string) => void;\r\n readonly onStartEdit: (module: ApplicationModuleDto) => void;\r\n readonly onSaveModule: (e: React.FormEvent) => Promise<void>;\r\n readonly onCancelEdit: () => void;\r\n readonly onModulesReorder: (modules: (ApplicationModuleDto & { id: string })[]) => Promise<void>;\r\n readonly onSectionsReorder: (moduleId: string, sections: ModuleSectionDto[]) => Promise<void>;\r\n readonly setModuleFormData: React.Dispatch<\r\n React.SetStateAction<{\r\n readonly code: string;\r\n readonly label: string;\r\n readonly description: string;\r\n readonly icon: string;\r\n readonly route: string;\r\n readonly displayOrder: number;\r\n }>\r\n >;\r\n}\r\n\r\n\r\nconst renderModuleSections = (moduleId: string, loadingSections: Set<string>, moduleSections: Map<string, ModuleSectionDto[]>, onSectionsReorder: (moduleId: string, sections: ModuleSectionDto[]) => Promise<void>, reordering: boolean, t: TFunction) => {\r\n if (loadingSections.has(moduleId)) {\r\n return (\r\n <div className=\"flex items-center justify-center py-4\">\r\n <Loader2 className=\"w-5 h-5 animate-spin text-[var(--text-muted)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (moduleSections.get(moduleId)?.length === 0) {\r\n return (\r\n <p className=\"text-sm text-[var(--text-muted)] py-2\">\r\n {t('applicationDetail.modules.noSections', 'No sections')}\r\n </p>\r\n );\r\n }\r\n\r\n if (moduleSections.get(moduleId)) {\r\n return (\r\n <SortableList\r\n items={moduleSections.get(moduleId)!.map((s) => ({ ...s, id: s.id }))}\r\n onReorder={(sections) => onSectionsReorder(moduleId, sections)}\r\n disabled={reordering}\r\n renderItem={(section, sectionDragHandle) => (\r\n <div className=\"flex items-center gap-2 p-2 rounded bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n {sectionDragHandle}\r\n <div className=\"p-1 rounded bg-[var(--bg-tertiary)]\">\r\n {renderLucideIcon(section.icon, 'w-3 h-3') || (\r\n <Layers className=\"w-3 h-3 text-[var(--text-muted)]\" />\r\n )}\r\n </div>\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {section.label}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">{section.code}</p>\r\n </div>\r\n <span\r\n className={`px-2 py-0.5 text-xs rounded-full ${\r\n section.isActive\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n : 'bg-[var(--error-bg)] text-[var(--error-text)]'\r\n }`}\r\n >\r\n {section.isActive ? t('common:active') : t('common:inactive')}\r\n </span>\r\n </div>\r\n )}\r\n />\r\n );\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport function ApplicationModulesTab({\r\n application,\r\n expandedModules,\r\n moduleSections,\r\n loadingSections,\r\n reordering,\r\n editingModule,\r\n moduleFormData,\r\n showModuleForm,\r\n saving,\r\n onToggleExpand,\r\n onStartEdit,\r\n onSaveModule,\r\n onCancelEdit,\r\n onModulesReorder,\r\n onSectionsReorder,\r\n setModuleFormData,\r\n}: ApplicationModulesTabProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.modules.title')} ({application.modules.length})\r\n </h3>\r\n\r\n {showModuleForm && editingModule && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--border-color)]\">\r\n <h4 className=\"text-md font-semibold text-[var(--text-primary)] mb-4\">\r\n {t('applicationDetail.modules.edit')}\r\n </h4>\r\n <form onSubmit={onSaveModule} className=\"space-y-4\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.code')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.code}\r\n disabled\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-tertiary)] border border-[var(--border-color)] text-[var(--text-muted)] cursor-not-allowed\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.label')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.label}\r\n onChange={(e) => setModuleFormData((prev) => ({ ...prev, label: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n required\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.icon')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.icon}\r\n onChange={(e) => setModuleFormData((prev) => ({ ...prev, icon: e.target.value }))}\r\n placeholder=\"Users\"\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.route')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={moduleFormData.route}\r\n onChange={(e) => setModuleFormData((prev) => ({ ...prev, route: e.target.value }))}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n <div className=\"md:col-span-2\">\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('applicationDetail.fields.description')}\r\n </label>\r\n <textarea\r\n value={moduleFormData.description}\r\n onChange={(e) =>\r\n setModuleFormData((prev) => ({ ...prev, description: e.target.value }))\r\n }\r\n rows={2}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-primary)]\"\r\n />\r\n </div>\r\n </div>\r\n <div className=\"flex justify-end gap-2\">\r\n <button\r\n type=\"button\"\r\n onClick={onCancelEdit}\r\n className=\"px-4 py-2 rounded-[var(--radius-button)] font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]\"\r\n >\r\n {t('common:cancel')}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50\"\r\n >\r\n {saving ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Save className=\"w-4 h-4\" />}\r\n {t('common:save')}\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n )}\r\n\r\n {application.modules.length === 0 ? (\r\n <p className=\"text-center py-8 text-[var(--text-muted)]\">\r\n {t('applicationDetail.modules.empty')}\r\n </p>\r\n ) : (\r\n <SortableList\r\n items={application.modules.map((m) => ({ ...m, id: m.id }))}\r\n onReorder={onModulesReorder}\r\n disabled={reordering}\r\n renderItem={(module, dragHandle) => (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--item-color-border)] hover:border-[var(--color-accent-600)] transition-colors\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n {dragHandle}\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--bg-tertiary)]\">\r\n {renderLucideIcon(module.icon, 'w-4 h-4') || (\r\n <Layers className=\"w-4 h-4 text-[var(--text-muted)]\" />\r\n )}\r\n </div>\r\n <button\r\n onClick={() => onToggleExpand(module.id)}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)]\"\r\n aria-expanded={expandedModules.has(module.id)}\r\n aria-label={t('applicationDetail.modules.toggleExpand', 'Toggle sections')}\r\n >\r\n {expandedModules.has(module.id) ? (\r\n <ChevronDown className=\"w-4 h-4 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-4 h-4 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n <div>\r\n <p className=\"font-medium text-[var(--text-primary)]\">{module.label}</p>\r\n <p className=\"text-sm text-[var(--text-muted)]\">{module.code}</p>\r\n </div>\r\n <span\r\n className={`ml-2 px-2 py-0.5 text-xs font-medium rounded-full ${\r\n module.isActive\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n : 'bg-[var(--error-bg)] text-[var(--error-text)]'\r\n }`}\r\n >\r\n {module.isActive ? t('common:active') : t('common:inactive')}\r\n </span>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-muted)]\">\r\n {module.sectionsCount} {t('applicationDetail.modules.sections', 'sections')}\r\n </span>\r\n <button\r\n onClick={() => onStartEdit(module)}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)]\"\r\n aria-label={t('applicationDetail.modules.edit')}\r\n >\r\n <Edit className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n {expandedModules.has(module.id) && (\r\n <div className=\"mt-3 pl-10 pt-3 border-t border-[var(--border-color)]\">\r\n <div className=\"grid grid-cols-2 gap-4 text-sm mb-4\">\r\n <div>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {t('applicationDetail.fields.description')}:\r\n </span>\r\n <p className=\"text-[var(--text-primary)]\">{module.description || '-'}</p>\r\n </div>\r\n <div>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {t('applicationDetail.fields.route')}:\r\n </span>\r\n <p className=\"text-[var(--text-primary)] font-mono\">{module.route || '-'}</p>\r\n </div>\r\n </div>\r\n {/* Sections */}\r\n <div className=\"mt-4\">\r\n <h5 className=\"text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('applicationDetail.modules.sections', 'Sections')} ({module.sectionsCount})\r\n </h5>\r\n {renderModuleSections(module.id, loadingSections, moduleSections, onSectionsReorder, reordering, t)}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n","import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport type { ApplicationDetailDto, PermissionListDto, RoleListDto } from '@/services/api/adminApi';\r\n\r\nexport interface PermissionWithRoles {\r\n permission: PermissionListDto;\r\n roles: RoleListDto[];\r\n}\r\n\r\nexport interface ApplicationPermissionsTabProps {\r\n readonly application: ApplicationDetailDto;\r\n readonly permissions: PermissionListDto[];\r\n readonly permissionsWithRoles: PermissionWithRoles[];\r\n}\r\n\r\nexport function ApplicationPermissionsTab({\r\n application,\r\n permissions,\r\n permissionsWithRoles,\r\n}: ApplicationPermissionsTabProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.permissions.title')} ({permissions.length})\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {t('applicationDetail.permissions.description', {\r\n path: `${application.code}.*`,\r\n })}\r\n </p>\r\n\r\n {permissions.length === 0 ? (\r\n <p className=\"text-center py-8 text-[var(--text-muted)]\">\r\n {t('applicationDetail.permissions.empty')}\r\n </p>\r\n ) : (\r\n <div className=\"overflow-x-auto\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"border-b border-[var(--border-color)]\">\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.path')}\r\n </th>\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.action')}\r\n </th>\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.type')}\r\n </th>\r\n <th className=\"text-left py-3 px-4 text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('applicationDetail.permissions.roles')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {permissionsWithRoles.map(({ permission, roles: permRoles }) => (\r\n <tr\r\n key={permission.id}\r\n className=\"border-b border-[var(--border-color)] hover:bg-[var(--bg-hover)]\"\r\n >\r\n <td className=\"py-3 px-4 font-mono text-sm text-[var(--text-primary)]\">\r\n {permission.path}\r\n </td>\r\n <td className=\"py-3 px-4\">\r\n {permission.action ? (\r\n <span className=\"px-2 py-1 text-xs font-medium rounded-full bg-[var(--accent-bg)] text-[var(--accent-text)]\">\r\n {permission.action}\r\n </span>\r\n ) : (\r\n '-'\r\n )}\r\n </td>\r\n <td className=\"py-3 px-4\">\r\n {permission.isWildcard ? (\r\n <span className=\"px-2 py-1 text-xs font-medium rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)]\">\r\n {t('applicationDetail.permissions.wildcard', 'Wildcard')}\r\n </span>\r\n ) : (\r\n <span className=\"px-2 py-1 text-xs font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-muted)]\">\r\n {t('applicationDetail.permissions.specific', 'Specific')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"py-3 px-4\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {permRoles.length === 0 ? (\r\n <span className=\"text-[var(--text-muted)] text-sm\">-</span>\r\n ) : (\r\n permRoles.slice(0, 3).map(role => (\r\n <span\r\n key={role.id}\r\n className=\"px-2 py-0.5 text-xs font-medium rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)]\"\r\n >\r\n {role.name}\r\n </span>\r\n ))\r\n )}\r\n {permRoles.length > 3 && (\r\n <span className=\"px-2 py-0.5 text-xs font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-muted)]\">\r\n +{permRoles.length - 3}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import type { ReactElement } from 'react';\nimport { Shield, Eye } from 'lucide-react';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nexport interface RoleListDto {\r\n id: string;\r\n name: string;\r\n isSystem: boolean;\r\n usersCount: number;\r\n}\r\n\r\nexport interface PermissionListDto {\r\n id: string;\r\n path: string;\r\n isWildcard: boolean;\r\n}\r\n\r\nexport interface RoleWithPermissions {\r\n role: RoleListDto;\r\n permissions: PermissionListDto[];\r\n}\r\n\r\nexport interface ApplicationAccessTabProps {\r\n readonly rolesWithAppAccess: RoleWithPermissions[];\r\n readonly onNavigateToRole: (roleId: string) => void;\r\n}\r\n\r\nexport function ApplicationAccessTab({\r\n rolesWithAppAccess,\r\n onNavigateToRole,\r\n}: ApplicationAccessTabProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.roles.title')} ({rolesWithAppAccess.length})\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {t('applicationDetail.roles.description')}\r\n </p>\r\n\r\n {rolesWithAppAccess.length === 0 ? (\r\n <p className=\"text-center py-8 text-[var(--text-muted)]\">\r\n {t('applicationDetail.roles.empty')}\r\n </p>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n {rolesWithAppAccess.map(({ role, permissions: rolePermissions }) => (\r\n <div\r\n key={role.id}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--item-color-border)] hover:border-[var(--color-accent-600)] transition-colors\"\r\n >\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)]\">\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-600)]\" />\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.isSystem && (\r\n <span className=\"px-2 py-0.5 text-xs font-medium rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)]\">\r\n {t('applicationDetail.roles.system', 'System')}\r\n </span>\r\n )}\r\n </div>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {role.usersCount} {t('applicationDetail.roles.users')} • {rolePermissions.length}{' '}\r\n {t('applicationDetail.roles.permissions')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() => onNavigateToRole(role.id)}\r\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-[var(--radius-button)] text-sm font-medium text-[var(--color-accent-600)] hover:bg-[var(--color-accent-100)]\"\r\n >\r\n <Eye className=\"w-4 h-4\" />\r\n {t('applicationDetail.roles.viewRole')}\r\n </button>\r\n </div>\r\n </div>\r\n <div className=\"mt-3 flex flex-wrap gap-1\">\r\n {rolePermissions.slice(0, 5).map(perm => (\r\n <span\r\n key={perm.id}\r\n className=\"px-2 py-0.5 text-xs font-mono rounded bg-[var(--bg-tertiary)] text-[var(--text-muted)]\"\r\n >\r\n {perm.path.split('.').pop()}\r\n {perm.isWildcard && '.*'}\r\n </span>\r\n ))}\r\n {rolePermissions.length > 5 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded bg-[var(--bg-tertiary)] text-[var(--text-muted)]\">\r\n +{rolePermissions.length - 5} {t('applicationDetail.roles.more', 'more')}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","'use client';\r\n\r\nimport React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n Globe,\r\n} from 'lucide-react';\r\nimport type {\r\n ApplicationDetailDto,\r\n ApplicationTenantDto,\r\n ApplicationAccessLevel,\r\n AvailableTenantForAppDto,\r\n} from '@/services/api/adminApi';\r\nimport { useTenantTypeSettings } from '@/hooks/useTenantTypeSettings';\r\nimport { getLucideIcon, getColorClasses } from '@/utils/tenantIconMap';\r\n\r\nexport interface BulkModuleNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n sections: BulkSectionNode[];\r\n}\r\n\r\nexport interface BulkSectionNode {\r\n id: string;\r\n label: string;\r\n code: string;\r\n icon: string | null;\r\n isAssigned: boolean;\r\n}\r\n\r\nexport interface ApplicationPublicationTabProps {\r\n readonly application: ApplicationDetailDto;\r\n readonly assignedTenants: ApplicationTenantDto[];\r\n readonly availableTenants: AvailableTenantForAppDto[];\r\n readonly showAssignModal: boolean;\r\n readonly selectedTenantIds: string[];\r\n readonly selectedAccessLevel: ApplicationAccessLevel;\r\n readonly tenantSearch: string;\r\n readonly showCustomizeDrawer: boolean;\r\n readonly customizingTenant: ApplicationTenantDto | null;\r\n readonly bulkAccessMode: 'full' | 'custom';\r\n readonly bulkModules: BulkModuleNode[];\r\n readonly bulkExpandedModules: Set<string>;\r\n readonly loadingBulkModules: boolean;\r\n readonly isUpdateMode: boolean;\r\n readonly updateMergeMode: 'merge' | 'replace';\r\n readonly showConfirmRemovalDialog: boolean;\r\n readonly pendingRemovals: { modules: number; sections: number };\r\n readonly saving: boolean;\r\n readonly includePersonalTenants: boolean;\r\n readonly isInDefaultPersonalTemplate: boolean;\r\n readonly onAddTenant: () => void;\r\n readonly onRemoveTenant: (tenantId: string) => Promise<void>;\r\n readonly onUpdateAccessLevel: (tenantId: string, accessLevel: ApplicationAccessLevel) => Promise<void>;\r\n readonly onCustomizeTenant: (tenant: ApplicationTenantDto) => void;\r\n readonly onCloseCustomizeDrawer: () => void;\r\n readonly onAssignTenants: () => Promise<void>;\r\n readonly onUpdateTenants: () => Promise<void>;\r\n readonly onExecuteUpdateTenants: () => Promise<void>;\r\n readonly onCancelRemovalDialog: () => void;\r\n readonly setShowAssignModal: (show: boolean) => void;\r\n readonly setSelectedTenantIds: React.Dispatch<React.SetStateAction<string[]>>;\r\n readonly setSelectedAccessLevel: React.Dispatch<React.SetStateAction<ApplicationAccessLevel>>;\r\n readonly setTenantSearch: (search: string) => void;\r\n readonly setBulkAccessMode: React.Dispatch<React.SetStateAction<'full' | 'custom'>>;\r\n readonly setIsUpdateMode: (mode: boolean) => void;\r\n readonly setUpdateMergeMode: React.Dispatch<React.SetStateAction<'merge' | 'replace'>>;\r\n readonly onToggleTenantSelection: (tenantId: string) => void;\r\n readonly onSelectAllFilteredTenants: () => void;\r\n readonly onClearTenantSelection: () => void;\r\n readonly setIncludePersonalTenants: (value: boolean) => void;\r\n readonly onLoadBulkModules: () => Promise<void>;\r\n readonly onToggleBulkModuleExpand: (moduleId: string) => void;\r\n readonly onToggleBulkModule: (moduleId: string) => void;\r\n readonly onToggleBulkSection: (moduleId: string, sectionId: string) => void;\r\n readonly onGetBulkModuleCheckState: (module: BulkModuleNode) => 'checked' | 'unchecked' | 'indeterminate';\r\n readonly onGetBulkStats: () => { totalModules: number; assignedModules: number; totalSections: number; assignedSections: number };\r\n readonly onSelectAllBulkModules: () => void;\r\n readonly onClearBulkModules: () => void;\r\n readonly appId: string;\r\n}\r\n\r\n// Helper: Get CSS classes for access level indicator color\r\nconst getAccessLevelColorClass = (accessLevel: ApplicationAccessLevel): string => {\r\n switch (accessLevel) {\r\n case 'FullAccess':\r\n return 'bg-green-500';\r\n case 'RequestAccess':\r\n return 'bg-amber-500';\r\n case 'Disabled':\r\n return 'bg-gray-400';\r\n default:\r\n return 'bg-gray-400';\r\n }\r\n};\r\n\r\n// Helper: Get access level label key\r\nconst getLabelKey = (level: ApplicationAccessLevel): string => {\r\n switch (level) {\r\n case 'FullAccess':\r\n return 'fullAccess';\r\n case 'RequestAccess':\r\n return 'requestAccess';\r\n case 'Disabled':\r\n return 'disabled';\r\n default:\r\n return 'disabled';\r\n }\r\n};\r\n\r\n// Helper: Get tenant icon and color from settings\r\nconst useTenantIconForType = () => {\r\n const { getIconForType } = useTenantTypeSettings();\r\n return (tenantType: string) => {\r\n const typeInfo = getIconForType(tenantType);\r\n const Icon = getLucideIcon(typeInfo.icon);\r\n const colors = getColorClasses(typeInfo.color);\r\n return { Icon, bgClass: colors.bg, colorClass: colors.text };\r\n };\r\n};\r\n\r\nexport const ApplicationPublicationTab: React.FC<ApplicationPublicationTabProps> = ({\r\n assignedTenants,\r\n}) => {\r\n const { t } = useTranslation('admin');\r\n const getTenantIconInfo = useTenantIconForType();\r\n\r\n return (\r\n <div className=\"space-y-4\">\r\n {/* Header Section */}\r\n <div>\r\n <h3 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.title', 'Tenant Publication')} ({assignedTenants.length})\r\n </h3>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.description', 'Manage which tenants have access to this application')}\r\n </p>\r\n </div>\r\n\r\n {/* Access Levels Legend */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3 p-4 rounded-[var(--radius-card)] bg-[var(--bg-tertiary)] border border-[var(--border-color)]\">\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"w-3 h-3 mt-1 rounded-full bg-green-500 flex-shrink-0\" />\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.accessLevels.fullAccess', 'Full Access')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.accessLevels.fullAccessDesc', 'Users can use all features')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"w-3 h-3 mt-1 rounded-full bg-amber-500 flex-shrink-0\" />\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.accessLevels.requestAccess', 'Request Access')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.accessLevels.requestAccessDesc', 'Requires access request')}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"w-3 h-3 mt-1 rounded-full bg-gray-400 flex-shrink-0\" />\r\n <div>\r\n <p className=\"text-sm font-medium text-[var(--text-primary)]\">\r\n {t('applicationDetail.publication.accessLevels.disabled', 'Disabled')}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.accessLevels.disabledDesc', 'Not visible for tenant')}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Assigned Tenants List or Empty State */}\r\n {assignedTenants.length === 0 ? (\r\n <div className=\"text-center py-12\">\r\n <Globe className=\"w-12 h-12 mx-auto text-[var(--text-muted)] mb-4\" />\r\n <p className=\"text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.empty', 'No tenants have access to this application yet')}\r\n </p>\r\n </div>\r\n ) : (\r\n <div className=\"space-y-3\">\r\n {assignedTenants.map(tenant => {\r\n const { Icon, bgClass, colorClass } = getTenantIconInfo(tenant.tenantType);\r\n const statusBgClass = tenant.tenantStatus === 'Active'\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)]'\r\n : 'bg-[var(--warning-bg)] text-[var(--warning-text)]';\r\n\r\n return (\r\n <div\r\n key={tenant.tenantId}\r\n className=\"p-4 rounded-[var(--radius-card)] bg-[var(--bg-primary)] border border-[var(--item-color-border)] hover:border-[var(--color-accent-600)] transition-colors\"\r\n >\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)] ${bgClass}`}>\r\n <Icon className={`w-5 h-5 ${colorClass}`} />\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <p className=\"font-medium text-[var(--text-primary)]\">{tenant.tenantName}</p>\r\n <span className={`px-2 py-0.5 text-xs font-medium rounded-full ${statusBgClass}`}>\r\n {tenant.tenantStatus}\r\n </span>\r\n </div>\r\n <p className=\"text-sm text-[var(--text-muted)]\">\r\n {tenant.tenantSlug} • {tenant.tenantType}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <div className={`w-2.5 h-2.5 rounded-full ${getAccessLevelColorClass(tenant.accessLevel as ApplicationAccessLevel)}`} />\r\n <span className=\"px-3 py-1.5 rounded-[var(--radius-input)] bg-[var(--bg-secondary)] border border-[var(--border-color)] text-sm text-[var(--text-primary)]\">\r\n {t(`applicationDetail.publication.accessLevels.${getLabelKey(tenant.accessLevel as ApplicationAccessLevel)}`, tenant.accessLevel)}\r\n </span>\r\n </div>\r\n </div>\r\n <div className=\"mt-2 text-xs text-[var(--text-muted)]\">\r\n {t('applicationDetail.publication.assignedAt', 'Assigned')}: {new Date(tenant.assignedAt).toLocaleDateString()}\r\n {tenant.assignedBy && ` ${t('applicationDetail.publication.by', 'by')} ${tenant.assignedBy}`}\r\n </div>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import { useEffect, useMemo} from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useParams, useNavigate } from 'react-router-dom';\r\nimport { useTabNavigation } from '@/hooks/useTabNavigation';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport {\r\n ArrowLeft,\r\n Settings,\r\n Layers,\r\n Shield,\r\n Users,\r\n Loader2,\r\n AlertTriangle,\r\n CheckCircle,\r\n Power,\r\n PowerOff,\r\n Globe,\r\n AlertCircle,\r\n Inbox,\r\n} from 'lucide-react';\r\nimport { renderLucideIcon } from '@/utils/renderLucideIcon';\r\nimport { useApplicationDetail } from '@/hooks/useApplicationDetail';\r\nimport { useApplicationModules } from '@/hooks/useApplicationModules';\r\nimport { useApplicationPermissions } from '@/hooks/useApplicationPermissions';\r\nimport { useApplicationPublication } from '@/hooks/useApplicationPublication';\r\nimport {\r\n ApplicationInfoTab,\r\n ApplicationModulesTab,\r\n ApplicationPermissionsTab,\r\n ApplicationAccessTab,\r\n ApplicationPublicationTab,\r\n} from '@/components/platform/administration/applications';\r\nimport { AccessRequestsListTab } from '@/components/platform/administration/access-requests';\r\nimport { useAccessRequests } from '@/hooks/useAccessRequests';\r\n\r\nconst VALID_TABS = ['info', 'modules', 'permissions', 'roles', 'publication', 'requests'] as const;\r\ntype TabId = typeof VALID_TABS[number];\r\n\r\nexport default function ApplicationDetailPage(): ReactElement {\r\n const { id: appId } = useParams<{ id: string }>();\r\n const navigate = useNavigate();\r\n const { t } = useTranslation('admin');\r\n const { hasPermission } = useAuth();\r\n\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const canToggleStatus = hasPermission('administration.applications.execute');\r\n const { activeTab, setActiveTab } = useTabNavigation<TabId>('info', VALID_TABS);\r\n\r\n // Use all hooks\r\n const applicationDetail = useApplicationDetail();\r\n const applicationModules = useApplicationModules();\r\n const applicationPermissions = useApplicationPermissions();\r\n const applicationPublication = useApplicationPublication();\r\n const accessRequests = useAccessRequests('application', appId!);\r\n\r\n // Filter tenants based on current tenant context\r\n // When scoped to a specific tenant, only show that tenant in the publication modal\r\n const filteredAvailableTenants = useMemo(() => {\r\n if (isGlobalView || !currentTenant) return applicationPublication.availableTenants;\r\n return applicationPublication.availableTenants.filter(t => t.slug === currentTenant.slug);\r\n }, [applicationPublication.availableTenants, isGlobalView, currentTenant]);\r\n\r\n const filteredAssignedTenants = useMemo(() => {\r\n if (isGlobalView || !currentTenant) return applicationPublication.assignedTenants;\r\n return applicationPublication.assignedTenants.filter(t => t.tenantSlug === currentTenant.slug);\r\n }, [applicationPublication.assignedTenants, isGlobalView, currentTenant]);\r\n\r\n // Load data on mount\r\n useEffect(() => {\r\n if (appId) {\r\n applicationDetail.loadApplication(appId);\r\n }\r\n }, [appId]);\r\n\r\n // Load tab-specific data (lazy loading per tab)\r\n useEffect(() => {\r\n if (!applicationDetail.application) return;\r\n\r\n if (\r\n (activeTab === 'permissions' || activeTab === 'roles') &&\r\n applicationPermissions.permissions.length === 0\r\n ) {\r\n applicationPermissions.loadPermissionsData(applicationDetail.application);\r\n }\r\n if (\r\n activeTab === 'publication' &&\r\n applicationPublication.assignedTenants.length === 0\r\n ) {\r\n applicationPublication.loadPublicationData(appId!);\r\n }\r\n if (activeTab === 'requests') {\r\n accessRequests.loadRequests();\r\n }\r\n }, [\r\n activeTab,\r\n applicationDetail.application,\r\n applicationPublication.assignedTenants.length,\r\n ]);\r\n\r\n const tabs = [\r\n { id: 'info' as const, label: t('applicationDetail.tabs.info'), icon: Settings },\r\n { id: 'modules' as const, label: t('applicationDetail.tabs.modules'), icon: Layers },\r\n { id: 'permissions' as const, label: t('applicationDetail.tabs.permissions'), icon: Shield },\r\n { id: 'roles' as const, label: t('applicationDetail.tabs.roles'), icon: Users },\r\n { id: 'publication' as const, label: t('applicationDetail.tabs.publication'), icon: Globe },\r\n { id: 'requests' as const, label: t('applicationDetail.tabs.requests'), icon: Inbox },\r\n ];\r\n\r\n // Loading state\r\n if (applicationDetail.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 // Error or not found\r\n if (applicationDetail.error || !applicationDetail.application) {\r\n return (\r\n <div className=\"text-center py-12\">\r\n <AlertCircle className=\"w-12 h-12 text-[var(--error-text)] mx-auto mb-4\" />\r\n <p className=\"text-[var(--text-secondary)]\">\r\n {applicationDetail.error || t('applicationDetail.notFound')}\r\n </p>\r\n <button\r\n onClick={() => navigate('/administration/applications')}\r\n className=\"mt-4 px-4 py-2 rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)]\"\r\n >\r\n {t('applicationDetail.backToList')}\r\n </button>\r\n </div>\r\n );\r\n }\r\n\r\n const permissionsLoaded = applicationPermissions.permissions.length > 0 || activeTab === 'permissions' || activeTab === 'roles';\r\n const publicationLoaded = applicationPublication.assignedTenants.length > 0 || activeTab === 'publication';\r\n\r\n const statsCards = [\r\n {\r\n label: t('applicationDetail.stats.modules'),\r\n value: applicationDetail.application.modules?.length || 0,\r\n color: 'blue' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.permissions'),\r\n value: permissionsLoaded ? applicationPermissions.permissions.length : '—',\r\n color: 'green' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.rolesWithAccess'),\r\n value: permissionsLoaded ? applicationPermissions.rolesWithAppAccess.length : '—',\r\n color: 'purple' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.assignedTenants'),\r\n value: publicationLoaded ? filteredAssignedTenants.length : '—',\r\n color: 'yellow' as const,\r\n },\r\n {\r\n label: t('applicationDetail.stats.status'),\r\n value: applicationDetail.application.isActive ? t('common:active') : t('common:inactive'),\r\n color: applicationDetail.application.isActive ? 'green' : 'neutral',\r\n },\r\n ];\r\n\r\n const colorClasses: Record<string, string> = {\r\n blue: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n green: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n yellow: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n red: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\r\n purple: 'bg-[var(--accent-bg)] text-[var(--accent-text)] border-[var(--color-accent-300)]',\r\n neutral: 'bg-[var(--bg-secondary)] text-[var(--text-primary)] border-[var(--border-color)]',\r\n };\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('breadcrumb.admin', { ns: 'navigation' }), href: '/administration' },\r\n { label: t('applications.title'), href: '/administration/applications' },\r\n { label: applicationDetail.application.label },\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center gap-4\">\r\n <button\r\n onClick={() => navigate('/administration/applications')}\r\n className=\"p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n aria-label={t('common:back')}\r\n >\r\n <ArrowLeft className=\"w-5 h-5 text-[var(--text-secondary)]\" />\r\n </button>\r\n <div className=\"flex items-center gap-3\">\r\n {renderLucideIcon(applicationDetail.application.icon, 'w-5 h-5')}\r\n <div className=\"flex-1\">\r\n <h1 className=\"text-xl sm:text-2xl font-bold text-[var(--text-primary)]\">\r\n {applicationDetail.application.label}\r\n </h1>\r\n {applicationDetail.application.description && (\r\n <p className=\"text-sm sm:text-base text-[var(--text-secondary)]\">\r\n {applicationDetail.application.description}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 ml-auto\">\r\n <span\r\n className={`px-3 py-1 rounded-[var(--radius-badge)] text-sm font-medium ${\r\n applicationDetail.application.isActive\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)]'\r\n : 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)] border border-[var(--border-color)]'\r\n }`}\r\n >\r\n {applicationDetail.application.isActive ? t('common:active') : t('common:inactive')}\r\n </span>\r\n {canToggleStatus && (\r\n <button\r\n onClick={() => applicationDetail.handleToggleStatus(appId!)}\r\n disabled={applicationDetail.saving}\r\n className={`inline-flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-colors ${\r\n applicationDetail.application.isActive\r\n ? 'bg-[var(--error-bg)] text-[var(--error-text)] border border-[var(--error-border)] hover:bg-[var(--error-border)]'\r\n : 'bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)] hover:bg-[var(--success-border)]'\r\n } disabled:opacity-50`}\r\n >\r\n {applicationDetail.saving && (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n )}\r\n {!applicationDetail.saving && applicationDetail.application.isActive && (\r\n <PowerOff className=\"w-4 h-4\" />\r\n )}\r\n {!applicationDetail.saving && !applicationDetail.application.isActive && (\r\n <Power className=\"w-4 h-4\" />\r\n )}\r\n {applicationDetail.application.isActive\r\n ? t('applicationDetail.deactivate')\r\n : t('applicationDetail.activate')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Alerts */}\r\n {applicationDetail.error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] text-[var(--error-text)] flex items-center gap-2\">\r\n <AlertTriangle className=\"w-5 h-5 flex-shrink-0\" />\r\n {applicationDetail.error}\r\n </div>\r\n )}\r\n {applicationDetail.success && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--success-bg)] border border-[var(--success-border)] text-[var(--success-text)] flex items-center gap-2\">\r\n <CheckCircle className=\"w-5 h-5 flex-shrink-0\" />\r\n {applicationDetail.success}\r\n </div>\r\n )}\r\n\r\n {/* Stats cards */}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4\">\r\n {statsCards.map((stat) => (\r\n <div\r\n key={stat.label}\r\n className={`rounded-[var(--radius-card)] p-4 text-center border ${colorClasses[stat.color]}`}\r\n >\r\n <div className=\"text-2xl font-bold\">{stat.value}</div>\r\n <div className=\"text-sm opacity-80\">{stat.label}</div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {/* Tabs */}\r\n <div\r\n className=\"flex gap-1 p-1 overflow-x-auto bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)]\"\r\n role=\"tablist\"\r\n aria-label={t('applicationDetail.tabs.label', 'Application tabs')}\r\n >\r\n {tabs.map((tab) => {\r\n const Icon = tab.icon;\r\n const isActive = activeTab === tab.id;\r\n return (\r\n <button\r\n key={tab.id}\r\n role=\"tab\"\r\n aria-selected={isActive}\r\n aria-controls={`tabpanel-${tab.id}`}\r\n onClick={() => setActiveTab(tab.id)}\r\n className={`flex items-center gap-2 px-4 py-2 whitespace-nowrap rounded-[var(--radius-button)] font-medium transition-colors ${\r\n isActive\r\n ? 'bg-[var(--color-accent-600)] text-white'\r\n : 'text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <Icon className=\"w-4 h-4\" />\r\n {tab.label}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n\r\n {/* Tab content */}\r\n <div\r\n className=\"bg-[var(--bg-secondary)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4 sm:p-6\"\r\n role=\"tabpanel\"\r\n id={`tabpanel-${activeTab}`}\r\n aria-labelledby={activeTab}\r\n >\r\n {/* Info Tab */}\r\n {activeTab === 'info' && (\r\n <ApplicationInfoTab\r\n formData={applicationDetail.formData}\r\n setFormData={applicationDetail.setFormData}\r\n application={applicationDetail.application!}\r\n saving={applicationDetail.saving}\r\n onSubmit={() =>\r\n applicationDetail.handleSaveInfo(appId!, applicationDetail.formData)\r\n }\r\n />\r\n )}\r\n\r\n {/* Modules Tab */}\r\n {activeTab === 'modules' && (\r\n <ApplicationModulesTab\r\n application={applicationDetail.application!}\r\n expandedModules={applicationModules.expandedModules}\r\n moduleSections={applicationModules.moduleSections}\r\n loadingSections={applicationModules.loadingSections}\r\n reordering={applicationModules.reordering}\r\n editingModule={applicationModules.editingModule}\r\n moduleFormData={applicationModules.moduleFormData}\r\n showModuleForm={applicationModules.showModuleForm}\r\n saving={applicationDetail.saving}\r\n onToggleExpand={(moduleId) =>\r\n applicationModules.toggleModuleExpand(appId!, moduleId)\r\n }\r\n onStartEdit={applicationModules.startEditModule}\r\n onSaveModule={async () => {\r\n await applicationModules.handleSaveModule(\r\n appId!,\r\n applicationModules.editingModule!.id,\r\n applicationModules.moduleFormData\r\n );\r\n applicationDetail.setSuccess(t('applicationDetail.success.moduleUpdated'));\r\n await applicationDetail.loadApplication(appId!);\r\n }}\r\n onCancelEdit={() => {\r\n applicationModules.setShowModuleForm(false);\r\n applicationModules.setEditingModule(null);\r\n }}\r\n onModulesReorder={async (modules) => {\r\n await applicationModules.handleModulesReorder(appId!, modules);\r\n await applicationDetail.loadApplication(appId!);\r\n }}\r\n onSectionsReorder={(moduleId, sections) =>\r\n applicationModules.handleSectionsReorder(appId!, moduleId, sections)\r\n }\r\n setModuleFormData={(value) => applicationModules.setModuleFormData(typeof value === 'function' ? value(applicationModules.moduleFormData) : value)}\r\n />\r\n )}\r\n\r\n {/* Permissions Tab */}\r\n {activeTab === 'permissions' && (\r\n <ApplicationPermissionsTab\r\n application={applicationDetail.application!}\r\n permissions={applicationPermissions.permissions}\r\n permissionsWithRoles={applicationPermissions.permissionsWithRoles}\r\n />\r\n )}\r\n\r\n {/* Roles Tab */}\r\n {activeTab === 'roles' && (\r\n <ApplicationAccessTab\r\n rolesWithAppAccess={applicationPermissions.rolesWithAppAccess}\r\n onNavigateToRole={(roleId) =>\r\n navigate(`/administration/permissions/roles/${roleId}`)\r\n }\r\n />\r\n )}\r\n\r\n {/* Publication Tab */}\r\n {activeTab === 'publication' && (\r\n <ApplicationPublicationTab\r\n application={applicationDetail.application!}\r\n assignedTenants={filteredAssignedTenants}\r\n availableTenants={filteredAvailableTenants}\r\n showAssignModal={applicationPublication.showAssignModal}\r\n selectedTenantIds={applicationPublication.selectedTenantIds}\r\n selectedAccessLevel={applicationPublication.selectedAccessLevel}\r\n tenantSearch={applicationPublication.tenantSearch}\r\n showCustomizeDrawer={applicationPublication.showCustomizeDrawer}\r\n customizingTenant={applicationPublication.customizingTenant}\r\n bulkAccessMode={applicationPublication.bulkAccessMode}\r\n bulkModules={applicationPublication.bulkModules}\r\n bulkExpandedModules={applicationPublication.bulkExpandedModules}\r\n loadingBulkModules={applicationPublication.loadingBulkModules}\r\n isUpdateMode={applicationPublication.isUpdateMode}\r\n updateMergeMode={applicationPublication.updateMergeMode}\r\n showConfirmRemovalDialog={applicationPublication.showConfirmRemovalDialog}\r\n pendingRemovals={applicationPublication.pendingRemovals}\r\n saving={applicationDetail.saving}\r\n includePersonalTenants={applicationPublication.includePersonalTenants}\r\n isInDefaultPersonalTemplate={applicationPublication.isInDefaultPersonalTemplate}\r\n onAddTenant={() => {\r\n applicationPublication.loadPublicationData(appId!);\r\n applicationPublication.setShowAssignModal(true);\r\n }}\r\n onRemoveTenant={(tenantId) =>\r\n applicationPublication.handleRemoveTenant(appId!, tenantId, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.removed'));\r\n })\r\n }\r\n onUpdateAccessLevel={(tenantId, accessLevel) =>\r\n applicationPublication.handleUpdateAccessLevel(appId!, tenantId, accessLevel, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.updated'));\r\n })\r\n }\r\n onCustomizeTenant={(tenant) => {\r\n applicationPublication.setCustomizingTenant(tenant);\r\n applicationPublication.setShowCustomizeDrawer(true);\r\n }}\r\n onCloseCustomizeDrawer={() => {\r\n applicationPublication.setShowCustomizeDrawer(false);\r\n applicationPublication.setCustomizingTenant(null);\r\n applicationPublication.loadPublicationData(appId!);\r\n }}\r\n onAssignTenants={() =>\r\n applicationPublication.handleAssignTenants(appId!, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.assigned'));\r\n applicationPublication.loadPublicationData(appId!);\r\n })\r\n }\r\n onUpdateTenants={() =>\r\n applicationPublication.handleUpdateTenants(appId!, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.updated'));\r\n applicationPublication.loadPublicationData(appId!);\r\n })\r\n }\r\n onExecuteUpdateTenants={() =>\r\n applicationPublication.executeUpdateTenants(appId!, () => {\r\n applicationDetail.setSuccess(t('applicationDetail.publication.success.updated'));\r\n applicationPublication.loadPublicationData(appId!);\r\n })\r\n }\r\n onCancelRemovalDialog={() => {\r\n applicationPublication.setShowConfirmRemovalDialog(false);\r\n applicationPublication.setUpdateMergeMode('merge');\r\n }}\r\n setShowAssignModal={applicationPublication.setShowAssignModal}\r\n setSelectedTenantIds={applicationPublication.setSelectedTenantIds}\r\n setSelectedAccessLevel={applicationPublication.setSelectedAccessLevel}\r\n setTenantSearch={applicationPublication.setTenantSearch}\r\n setBulkAccessMode={applicationPublication.setBulkAccessMode}\r\n setIsUpdateMode={applicationPublication.setIsUpdateMode}\r\n setUpdateMergeMode={applicationPublication.setUpdateMergeMode}\r\n onToggleTenantSelection={applicationPublication.toggleTenantSelection}\r\n onSelectAllFilteredTenants={applicationPublication.selectAllFilteredTenants}\r\n onClearTenantSelection={applicationPublication.clearTenantSelection}\r\n setIncludePersonalTenants={applicationPublication.setIncludePersonalTenants}\r\n onLoadBulkModules={() => applicationPublication.loadBulkModules(appId!)}\r\n onToggleBulkModuleExpand={applicationPublication.toggleBulkModuleExpand}\r\n onToggleBulkModule={applicationPublication.toggleBulkModule}\r\n onToggleBulkSection={applicationPublication.toggleBulkSection}\r\n onGetBulkModuleCheckState={applicationPublication.getBulkModuleCheckState}\r\n onGetBulkStats={applicationPublication.getBulkStats}\r\n onSelectAllBulkModules={applicationPublication.selectAllBulkModules}\r\n onClearBulkModules={applicationPublication.clearBulkModules}\r\n appId={appId!}\r\n />\r\n )}\r\n\r\n {/* Access Requests Tab */}\r\n {activeTab === 'requests' && (\r\n <AccessRequestsListTab\r\n requests={accessRequests.requests}\r\n loading={accessRequests.loading}\r\n onReload={() => accessRequests.loadRequests()}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["renderLucideIcon","icon","className","IconComponent","LucideIcons","jsx","Icon","useApplicationDetail","useTranslation","application","setApplication","useState","loading","setLoading","saving","setSaving","error","setError","success","setSuccess","formData","setFormData","loadApplication","useCallback","appId","data","adminApi","err","handleSaveInfo","updateData","handleToggleStatus","useApplicationModules","expandedModules","setExpandedModules","moduleSections","setModuleSections","loadingSections","setLoadingSections","reordering","setReordering","editingModule","setEditingModule","moduleFormData","setModuleFormData","showModuleForm","setShowModuleForm","toggleModuleExpand","moduleId","isExpanding","prev","newSet","sections","handleSaveModule","resetModuleForm","handleModulesReorder","reorderedModules","newModules","m","index","handleSectionsReorder","reorderedSections","newSections","s","reloadErr","startEditModule","module","moduleCount","getPermissionWithRoles","perm","matrixRoles","allRoles","rolesWithPerm","mr","r","useApplicationPermissions","roles","setRoles","permissions","setPermissions","permissionsWithRoles","setPermissionsWithRoles","loadPermissionsData","matrix","appPermissionPrefix","appPermissions","p","permWithRoles","loadRolesData","rolesWithAppAccess","useMemo","roleAccessMap","permission","permRoles","role","a","b","updateModuleAssignment","newIsAssigned","updateSectionAssignment","sectionId","allSectionsAssigned","assignAllSections","clearAllSections","useApplicationPublication","assignedTenants","setAssignedTenants","availableTenants","setAvailableTenants","showAssignModal","setShowAssignModal","selectedTenantIds","setSelectedTenantIds","selectedAccessLevel","setSelectedAccessLevel","tenantSearch","setTenantSearch","showCustomizeDrawer","setShowCustomizeDrawer","customizingTenant","setCustomizingTenant","bulkAccessMode","setBulkAccessMode","bulkModules","setBulkModules","bulkExpandedModules","setBulkExpandedModules","loadingBulkModules","setLoadingBulkModules","isUpdateMode","setIsUpdateMode","updateMergeMode","setUpdateMergeMode","showConfirmRemovalDialog","setShowConfirmRemovalDialog","pendingRemovals","setPendingRemovals","includePersonalTenants","setIncludePersonalTenants","isInDefaultPersonalTemplate","setIsInDefaultPersonalTemplate","loadPublicationData","assigned","availableResponse","loadBulkModules","appModules","moduleNodes","appModule","sectionNodes","section","toggleBulkModuleExpand","toggleBulkModule","toggleBulkSection","getBulkModuleCheckState","assignedCount","getBulkStats","totalModules","assignedModules","totalSections","sum","assignedSections","selectAllBulkModules","clearBulkModules","toggleTenantSelection","tenantId","id","selectAllFilteredTenants","filteredIds","t","matchesSearch","matchesType","clearTenantSelection","executeUpdateTenants","onSuccess","request","handleAssignTenants","handleUpdateTenants","removedModulesCount","removedSectionsCount","currentModules","currentSections","targetModuleIds","targetSectionIds","handleRemoveTenant","handleUpdateAccessLevel","accessLevel","ApplicationInfoTab","onSubmit","jsxs","e","Loader2","Save","SortableItemWrapper","disabled","children","attributes","listeners","setNodeRef","transform","transition","isDragging","useSortable","style","CSS","dragHandle","GripVertical","SortableList","items","onReorder","renderItem","setActiveId","sensors","useSensors","useSensor","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","handleDragEnd","event","active","over","oldIndex","item","newIndex","newItems","arrayMove","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","renderModuleSections","onSectionsReorder","sectionDragHandle","Layers","ApplicationModulesTab","onToggleExpand","onStartEdit","onSaveModule","onCancelEdit","onModulesReorder","ChevronDown","ChevronRight","Edit","ApplicationPermissionsTab","ApplicationAccessTab","onNavigateToRole","rolePermissions","Shield","Eye","getAccessLevelColorClass","getLabelKey","level","useTenantIconForType","getIconForType","useTenantTypeSettings","tenantType","typeInfo","getLucideIcon","colors","getColorClasses","ApplicationPublicationTab","getTenantIconInfo","Globe","tenant","bgClass","colorClass","statusBgClass","VALID_TABS","ApplicationDetailPage","useParams","navigate","useNavigate","hasPermission","useAuth","currentTenant","isGlobalView","useTenant","canToggleStatus","activeTab","setActiveTab","useTabNavigation","applicationDetail","applicationModules","applicationPermissions","applicationPublication","accessRequests","useAccessRequests","filteredAvailableTenants","filteredAssignedTenants","useEffect","tabs","Settings","Users","Inbox","AlertCircle","permissionsLoaded","publicationLoaded","statsCards","colorClasses","Breadcrumb","ArrowLeft","PowerOff","Power","AlertTriangle","CheckCircle","stat","tab","isActive","modules","value","roleId","AccessRequestsListTab"],"mappings":"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"}