@atlashub/smartstack 3.29.0 → 3.31.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 (322) hide show
  1. package/dist/chunks/{AgentSkillsPage-ChykpPZx.js → AgentSkillsPage-CDMhqrhE.js} +2 -2
  2. package/dist/chunks/{AgentSkillsPage-ChykpPZx.js.map → AgentSkillsPage-CDMhqrhE.js.map} +1 -1
  3. package/dist/chunks/{AgentSkillsPage-ABpqnnyK.js → AgentSkillsPage-DcvOMm5k.js} +2 -2
  4. package/dist/chunks/{AgentSkillsPage-ABpqnnyK.js.map → AgentSkillsPage-DcvOMm5k.js.map} +1 -1
  5. package/dist/chunks/{AgentWorkloadPage-BltzNlXI.js → AgentWorkloadPage-DYBPNzjQ.js} +2 -2
  6. package/dist/chunks/{AgentWorkloadPage-BltzNlXI.js.map → AgentWorkloadPage-DYBPNzjQ.js.map} +1 -1
  7. package/dist/chunks/{AgentWorkloadPage-BI5QWJyQ.js → AgentWorkloadPage-YpJSDaWc.js} +2 -2
  8. package/dist/chunks/{AgentWorkloadPage-BI5QWJyQ.js.map → AgentWorkloadPage-YpJSDaWc.js.map} +1 -1
  9. package/dist/chunks/{ApiCatalogDetailPage-BaheZKBq.js → ApiCatalogDetailPage-9r1axtCg.js} +3 -3
  10. package/dist/chunks/{ApiCatalogDetailPage-BaheZKBq.js.map → ApiCatalogDetailPage-9r1axtCg.js.map} +1 -1
  11. package/dist/chunks/{ApiCatalogDetailPage-CsRxlHwO.js → ApiCatalogDetailPage-TjCQ8_A8.js} +2 -2
  12. package/dist/chunks/{ApiCatalogDetailPage-CsRxlHwO.js.map → ApiCatalogDetailPage-TjCQ8_A8.js.map} +1 -1
  13. package/dist/chunks/{ApiCatalogPage-B0yIz8-U.js → ApiCatalogPage-COxazTnz.js} +2 -2
  14. package/dist/chunks/{ApiCatalogPage-B0yIz8-U.js.map → ApiCatalogPage-COxazTnz.js.map} +1 -1
  15. package/dist/chunks/{ApiCatalogPage-CqmmHpQ4.js → ApiCatalogPage-QRysH0pT.js} +2 -2
  16. package/dist/chunks/{ApiCatalogPage-CqmmHpQ4.js.map → ApiCatalogPage-QRysH0pT.js.map} +1 -1
  17. package/dist/chunks/{ApplicationDetailPage-CdT6KNd7.js → ApplicationDetailPage-Dbx01Ikm.js} +4 -4
  18. package/dist/chunks/{ApplicationDetailPage-CdT6KNd7.js.map → ApplicationDetailPage-Dbx01Ikm.js.map} +1 -1
  19. package/dist/chunks/{ApplicationDetailPage-CngD5JSN.js → ApplicationDetailPage-jSHy3MPz.js} +2 -2
  20. package/dist/chunks/{ApplicationDetailPage-CngD5JSN.js.map → ApplicationDetailPage-jSHy3MPz.js.map} +1 -1
  21. package/dist/chunks/{ApplicationsDashboardPage-1V4iQ6eY.js → ApplicationsDashboardPage-CclKc0wI.js} +3 -3
  22. package/dist/chunks/{ApplicationsDashboardPage-1V4iQ6eY.js.map → ApplicationsDashboardPage-CclKc0wI.js.map} +1 -1
  23. package/dist/chunks/{ApplicationsDashboardPage-DHmnjk2O.js → ApplicationsDashboardPage-CxWmOc1x.js} +2 -2
  24. package/dist/chunks/{ApplicationsDashboardPage-DHmnjk2O.js.map → ApplicationsDashboardPage-CxWmOc1x.js.map} +1 -1
  25. package/dist/chunks/{ApplicationsGridPage-CiMJFlB_.js → ApplicationsGridPage-BJXWXwyI.js} +2 -2
  26. package/dist/chunks/{ApplicationsGridPage-CiMJFlB_.js.map → ApplicationsGridPage-BJXWXwyI.js.map} +1 -1
  27. package/dist/chunks/{ApplicationsGridPage-Bo3NDnBF.js → ApplicationsGridPage-D2l8cM3o.js} +2 -2
  28. package/dist/chunks/{ApplicationsGridPage-Bo3NDnBF.js.map → ApplicationsGridPage-D2l8cM3o.js.map} +1 -1
  29. package/dist/chunks/{ApplicationsListPage-L2_S23aN.js → ApplicationsListPage-CMosl3my.js} +2 -2
  30. package/dist/chunks/{ApplicationsListPage-L2_S23aN.js.map → ApplicationsListPage-CMosl3my.js.map} +1 -1
  31. package/dist/chunks/{ApplicationsListPage-De8jQ1Cm.js → ApplicationsListPage-Dc6NGQ61.js} +2 -2
  32. package/dist/chunks/{ApplicationsListPage-De8jQ1Cm.js.map → ApplicationsListPage-Dc6NGQ61.js.map} +1 -1
  33. package/dist/chunks/{ApplicationsPage-DBq7_Sm8.js → ApplicationsPage-DH7tpMlF.js} +2 -2
  34. package/dist/chunks/{ApplicationsPage-DBq7_Sm8.js.map → ApplicationsPage-DH7tpMlF.js.map} +1 -1
  35. package/dist/chunks/{ApplicationsPage-CiNI-b0R.js → ApplicationsPage-DI-iMqoJ.js} +4 -4
  36. package/dist/chunks/{ApplicationsPage-CiNI-b0R.js.map → ApplicationsPage-DI-iMqoJ.js.map} +1 -1
  37. package/dist/chunks/{AssignmentRulesPage-C8rfUsMB.js → AssignmentRulesPage-B5UbujbZ.js} +2 -2
  38. package/dist/chunks/{AssignmentRulesPage-C8rfUsMB.js.map → AssignmentRulesPage-B5UbujbZ.js.map} +1 -1
  39. package/dist/chunks/{AssignmentRulesPage-DFsO4ZES.js → AssignmentRulesPage-E79QBSLb.js} +2 -2
  40. package/dist/chunks/{AssignmentRulesPage-DFsO4ZES.js.map → AssignmentRulesPage-E79QBSLb.js.map} +1 -1
  41. package/dist/chunks/{AssignmentsPage-COCikISI.js → AssignmentsPage-CDFaL1gT.js} +2 -2
  42. package/dist/chunks/{AssignmentsPage-COCikISI.js.map → AssignmentsPage-CDFaL1gT.js.map} +1 -1
  43. package/dist/chunks/{AssignmentsPage-78C_EBsw.js → AssignmentsPage-CPeKJjyK.js} +2 -2
  44. package/dist/chunks/{AssignmentsPage-78C_EBsw.js.map → AssignmentsPage-CPeKJjyK.js.map} +1 -1
  45. package/dist/chunks/{AuthCallbackPage-DqT6ueVi.js → AuthCallbackPage-BZ3Ocos5.js} +2 -2
  46. package/dist/chunks/{AuthCallbackPage-DqT6ueVi.js.map → AuthCallbackPage-BZ3Ocos5.js.map} +1 -1
  47. package/dist/chunks/{AuthCallbackPage-BF4bkTnR.js → AuthCallbackPage-Bml48QpH.js} +2 -2
  48. package/dist/chunks/{AuthCallbackPage-BF4bkTnR.js.map → AuthCallbackPage-Bml48QpH.js.map} +1 -1
  49. package/dist/chunks/{ConfirmEmailPage-DJy4idrf.js → ConfirmEmailPage-DP1XPaKK.js} +2 -2
  50. package/dist/chunks/{ConfirmEmailPage-DJy4idrf.js.map → ConfirmEmailPage-DP1XPaKK.js.map} +1 -1
  51. package/dist/chunks/{ConfirmEmailPage-Bh_K5qJn.js → ConfirmEmailPage-DyzslZ06.js} +2 -2
  52. package/dist/chunks/{ConfirmEmailPage-Bh_K5qJn.js.map → ConfirmEmailPage-DyzslZ06.js.map} +1 -1
  53. package/dist/chunks/{CreateSupportTicketPage-pL7jbG9o.js → CreateSupportTicketPage-Bz2KrMik.js} +2 -2
  54. package/dist/chunks/{CreateSupportTicketPage-pL7jbG9o.js.map → CreateSupportTicketPage-Bz2KrMik.js.map} +1 -1
  55. package/dist/chunks/{CreateSupportTicketPage-AVTwXbJd.js → CreateSupportTicketPage-hKjKM0Bh.js} +2 -2
  56. package/dist/chunks/{CreateSupportTicketPage-AVTwXbJd.js.map → CreateSupportTicketPage-hKjKM0Bh.js.map} +1 -1
  57. package/dist/chunks/{DashboardPage-DdQlTLw0.js → DashboardPage-B4nAd8Tj.js} +2 -2
  58. package/dist/chunks/{DashboardPage-DdQlTLw0.js.map → DashboardPage-B4nAd8Tj.js.map} +1 -1
  59. package/dist/chunks/{DashboardPage-DOitDfGV.js → DashboardPage-C9qgPBS-.js} +3 -3
  60. package/dist/chunks/{DashboardPage-DOitDfGV.js.map → DashboardPage-C9qgPBS-.js.map} +1 -1
  61. package/dist/chunks/{DashboardPage-C55mIiB6.js → DashboardPage-CjbNGMo1.js} +3 -3
  62. package/dist/chunks/{DashboardPage-C55mIiB6.js.map → DashboardPage-CjbNGMo1.js.map} +1 -1
  63. package/dist/chunks/{DashboardPage-CcCnUl7s.js → DashboardPage-rN7IFlTR.js} +2 -2
  64. package/dist/chunks/{DashboardPage-CcCnUl7s.js.map → DashboardPage-rN7IFlTR.js.map} +1 -1
  65. package/dist/chunks/{EscalationConfigPage-DRr55328.js → EscalationConfigPage-CGv2L62M.js} +2 -2
  66. package/dist/chunks/{EscalationConfigPage-DRr55328.js.map → EscalationConfigPage-CGv2L62M.js.map} +1 -1
  67. package/dist/chunks/{EscalationConfigPage-DNnZftCH.js → EscalationConfigPage-DpYDmsgw.js} +2 -2
  68. package/dist/chunks/{EscalationConfigPage-DNnZftCH.js.map → EscalationConfigPage-DpYDmsgw.js.map} +1 -1
  69. package/dist/chunks/{ForceChangePasswordPage-1SCOPIqK.js → ForceChangePasswordPage-CLI_fpF4.js} +2 -2
  70. package/dist/chunks/{ForceChangePasswordPage-1SCOPIqK.js.map → ForceChangePasswordPage-CLI_fpF4.js.map} +1 -1
  71. package/dist/chunks/{ForceChangePasswordPage-DBeG_HRO.js → ForceChangePasswordPage-Db6sOrZN.js} +2 -2
  72. package/dist/chunks/{ForceChangePasswordPage-DBeG_HRO.js.map → ForceChangePasswordPage-Db6sOrZN.js.map} +1 -1
  73. package/dist/chunks/{ForgotPasswordPage-Dlb6wKfC.js → ForgotPasswordPage-BhMz2B6A.js} +2 -2
  74. package/dist/chunks/{ForgotPasswordPage-Dlb6wKfC.js.map → ForgotPasswordPage-BhMz2B6A.js.map} +1 -1
  75. package/dist/chunks/{ForgotPasswordPage-DffYfXva.js → ForgotPasswordPage-D06arMXO.js} +2 -2
  76. package/dist/chunks/{ForgotPasswordPage-DffYfXva.js.map → ForgotPasswordPage-D06arMXO.js.map} +1 -1
  77. package/dist/chunks/{GroupDetailPage-C9nRbeHI.js → GroupDetailPage-BCM8KBCd.js} +5 -5
  78. package/dist/chunks/{GroupDetailPage-C9nRbeHI.js.map → GroupDetailPage-BCM8KBCd.js.map} +1 -1
  79. package/dist/chunks/{GroupDetailPage-CPPUWzXf.js → GroupDetailPage-CGMV3bWt.js} +2 -2
  80. package/dist/chunks/{GroupDetailPage-CPPUWzXf.js.map → GroupDetailPage-CGMV3bWt.js.map} +1 -1
  81. package/dist/chunks/{MyAccessRequestsPage-BAX0xwJX.js → MyAccessRequestsPage-BBrwEomx.js} +2 -2
  82. package/dist/chunks/{MyAccessRequestsPage-BAX0xwJX.js.map → MyAccessRequestsPage-BBrwEomx.js.map} +1 -1
  83. package/dist/chunks/{MyAccessRequestsPage-BMY1V631.js → MyAccessRequestsPage-CrlWe3gd.js} +2 -2
  84. package/dist/chunks/{MyAccessRequestsPage-BMY1V631.js.map → MyAccessRequestsPage-CrlWe3gd.js.map} +1 -1
  85. package/dist/chunks/{MyTenantsPage-BHtp67SD.js → MyTenantsPage-BOV34_rJ.js} +3 -3
  86. package/dist/chunks/{MyTenantsPage-BHtp67SD.js.map → MyTenantsPage-BOV34_rJ.js.map} +1 -1
  87. package/dist/chunks/{MyTenantsPage-Bbn4HxN2.js → MyTenantsPage-CK4-klmd.js} +2 -2
  88. package/dist/chunks/{MyTenantsPage-Bbn4HxN2.js.map → MyTenantsPage-CK4-klmd.js.map} +1 -1
  89. package/dist/chunks/{MyTicketsPage-D9IGVofj.js → MyTicketsPage-CFZ1G4dG.js} +2 -2
  90. package/dist/chunks/{MyTicketsPage-D9IGVofj.js.map → MyTicketsPage-CFZ1G4dG.js.map} +1 -1
  91. package/dist/chunks/{MyTicketsPage-BvZeiTXu.js → MyTicketsPage-DuhpwhZx.js} +2 -2
  92. package/dist/chunks/{MyTicketsPage-BvZeiTXu.js.map → MyTicketsPage-DuhpwhZx.js.map} +1 -1
  93. package/dist/chunks/{NavigationAppsPage-ChtMK1yt.js → NavigationAppsPage-BnNQRfBP.js} +2 -2
  94. package/dist/chunks/{NavigationAppsPage-ChtMK1yt.js.map → NavigationAppsPage-BnNQRfBP.js.map} +1 -1
  95. package/dist/chunks/{NavigationAppsPage-DiPBCsAF.js → NavigationAppsPage-DdJxEoTZ.js} +2 -2
  96. package/dist/chunks/{NavigationAppsPage-DiPBCsAF.js.map → NavigationAppsPage-DdJxEoTZ.js.map} +1 -1
  97. package/dist/chunks/{NotificationsPage-BCnL9oPb.js → NotificationsPage-BllOlagk.js} +2 -2
  98. package/dist/chunks/{NotificationsPage-BCnL9oPb.js.map → NotificationsPage-BllOlagk.js.map} +1 -1
  99. package/dist/chunks/{NotificationsPage-BxCiGzHk.js → NotificationsPage-D1T_ozHl.js} +2 -2
  100. package/dist/chunks/{NotificationsPage-BxCiGzHk.js.map → NotificationsPage-D1T_ozHl.js.map} +1 -1
  101. package/dist/chunks/{OnboardingWizardPage-CV_cxq7k.js → OnboardingWizardPage-CioLaCYz.js} +2 -2
  102. package/dist/chunks/{OnboardingWizardPage-CV_cxq7k.js.map → OnboardingWizardPage-CioLaCYz.js.map} +1 -1
  103. package/dist/chunks/{OnboardingWizardPage-Du-tQ2ag.js → OnboardingWizardPage-CrAQt7qL.js} +2 -2
  104. package/dist/chunks/{OnboardingWizardPage-Du-tQ2ag.js.map → OnboardingWizardPage-CrAQt7qL.js.map} +1 -1
  105. package/dist/chunks/{PermissionDetailPage-C1iuWv0G.js → PermissionDetailPage-BIG78-1-.js} +2 -2
  106. package/dist/chunks/{PermissionDetailPage-C1iuWv0G.js.map → PermissionDetailPage-BIG78-1-.js.map} +1 -1
  107. package/dist/chunks/{PermissionDetailPage-Ds4Jt1os.js → PermissionDetailPage-CvPqugYu.js} +2 -2
  108. package/dist/chunks/{PermissionDetailPage-Ds4Jt1os.js.map → PermissionDetailPage-CvPqugYu.js.map} +1 -1
  109. package/dist/chunks/{PermissionsPage-BGI2nxCn.js → PermissionsPage-CDSuc8vw.js} +2 -2
  110. package/dist/chunks/{PermissionsPage-BGI2nxCn.js.map → PermissionsPage-CDSuc8vw.js.map} +1 -1
  111. package/dist/chunks/{PermissionsPage-sauv7ct1.js → PermissionsPage-XaOrGrPZ.js} +2 -2
  112. package/dist/chunks/{PermissionsPage-sauv7ct1.js.map → PermissionsPage-XaOrGrPZ.js.map} +1 -1
  113. package/dist/chunks/{PortalDashboardPage-CQWEcghD.js → PortalDashboardPage-BsWVXkMe.js} +2 -2
  114. package/dist/chunks/{PortalDashboardPage-CQWEcghD.js.map → PortalDashboardPage-BsWVXkMe.js.map} +1 -1
  115. package/dist/chunks/{PortalDashboardPage-2kCbJw9w.js → PortalDashboardPage-oSD7oQhJ.js} +2 -2
  116. package/dist/chunks/{PortalDashboardPage-2kCbJw9w.js.map → PortalDashboardPage-oSD7oQhJ.js.map} +1 -1
  117. package/dist/chunks/{PreferencesPage-Bu4gaDRb.js → PreferencesPage-DD0_XWdT.js} +2 -2
  118. package/dist/chunks/{PreferencesPage-Bu4gaDRb.js.map → PreferencesPage-DD0_XWdT.js.map} +1 -1
  119. package/dist/chunks/{PreferencesPage-Dbg0bEYD.js → PreferencesPage-ca2BOdoH.js} +2 -2
  120. package/dist/chunks/{PreferencesPage-Dbg0bEYD.js.map → PreferencesPage-ca2BOdoH.js.map} +1 -1
  121. package/dist/chunks/{ProfilePage-DfiBhOUt.js → ProfilePage-Bex_JN5N.js} +2 -2
  122. package/dist/chunks/{ProfilePage-DfiBhOUt.js.map → ProfilePage-Bex_JN5N.js.map} +1 -1
  123. package/dist/chunks/{ProfilePage-C5QS7tsh.js → ProfilePage-C8tUIOnb.js} +2 -2
  124. package/dist/chunks/{ProfilePage-C5QS7tsh.js.map → ProfilePage-C8tUIOnb.js.map} +1 -1
  125. package/dist/chunks/{ReferencesManagementPage-C0RgHbJb.js → ReferencesManagementPage-B-FXS2ln.js} +2 -2
  126. package/dist/chunks/{ReferencesManagementPage-C0RgHbJb.js.map → ReferencesManagementPage-B-FXS2ln.js.map} +1 -1
  127. package/dist/chunks/{ReferencesManagementPage-Bs0mapj8.js → ReferencesManagementPage-C8KZprkI.js} +3 -3
  128. package/dist/chunks/{ReferencesManagementPage-Bs0mapj8.js.map → ReferencesManagementPage-C8KZprkI.js.map} +1 -1
  129. package/dist/chunks/{RegisterPage-DoeIiJt0.js → RegisterPage-BYt__zKJ.js} +2 -2
  130. package/dist/chunks/{RegisterPage-DoeIiJt0.js.map → RegisterPage-BYt__zKJ.js.map} +1 -1
  131. package/dist/chunks/{RegisterPage-DS1chV_A.js → RegisterPage-MWcVu-LY.js} +2 -2
  132. package/dist/chunks/{RegisterPage-DS1chV_A.js.map → RegisterPage-MWcVu-LY.js.map} +1 -1
  133. package/dist/chunks/{ResetPasswordPage-3KEk3zj5.js → ResetPasswordPage-DaJiMj5Z.js} +2 -2
  134. package/dist/chunks/{ResetPasswordPage-3KEk3zj5.js.map → ResetPasswordPage-DaJiMj5Z.js.map} +1 -1
  135. package/dist/chunks/{ResetPasswordPage-C_VQSFB5.js → ResetPasswordPage-rCLUIj_T.js} +2 -2
  136. package/dist/chunks/{ResetPasswordPage-C_VQSFB5.js.map → ResetPasswordPage-rCLUIj_T.js.map} +1 -1
  137. package/dist/chunks/{ResolutionModal-S6URD--N.js → ResolutionModal-DeuPnLWg.js} +2 -2
  138. package/dist/chunks/{ResolutionModal-S6URD--N.js.map → ResolutionModal-DeuPnLWg.js.map} +1 -1
  139. package/dist/chunks/{ResolutionModal-BzI1x79r.js → ResolutionModal-j7Rp6apG.js} +2 -2
  140. package/dist/chunks/{ResolutionModal-BzI1x79r.js.map → ResolutionModal-j7Rp6apG.js.map} +1 -1
  141. package/dist/chunks/{RoleDetailPage-SXK9cq_3.js → RoleDetailPage-CLtZWX17.js} +3 -3
  142. package/dist/chunks/{RoleDetailPage-SXK9cq_3.js.map → RoleDetailPage-CLtZWX17.js.map} +1 -1
  143. package/dist/chunks/{RoleDetailPage-DvEEWPKr.js → RoleDetailPage-TGyGmLMM.js} +2 -2
  144. package/dist/chunks/{RoleDetailPage-DvEEWPKr.js.map → RoleDetailPage-TGyGmLMM.js.map} +1 -1
  145. package/dist/chunks/{RolesPage-C5gYJxAl.js → RolesPage-C0c5G9e7.js} +2 -2
  146. package/dist/chunks/{RolesPage-C5gYJxAl.js.map → RolesPage-C0c5G9e7.js.map} +1 -1
  147. package/dist/chunks/{RolesPage-B75lCugt.js → RolesPage-Dm03fBBf.js} +2 -2
  148. package/dist/chunks/{RolesPage-B75lCugt.js.map → RolesPage-Dm03fBBf.js.map} +1 -1
  149. package/dist/chunks/{SlaConfigPage-BqXHATb6.js → SlaConfigPage-B4WDzEKi.js} +2 -2
  150. package/dist/chunks/{SlaConfigPage-BqXHATb6.js.map → SlaConfigPage-B4WDzEKi.js.map} +1 -1
  151. package/dist/chunks/{SlaConfigPage-DZ4P1FFW.js → SlaConfigPage-Cwo9NwxH.js} +2 -2
  152. package/dist/chunks/{SlaConfigPage-DZ4P1FFW.js.map → SlaConfigPage-Cwo9NwxH.js.map} +1 -1
  153. package/dist/chunks/{SupportPermissionsPage-DW7KJjYK.js → SupportPermissionsPage-CL12dFy-.js} +2 -2
  154. package/dist/chunks/{SupportPermissionsPage-DW7KJjYK.js.map → SupportPermissionsPage-CL12dFy-.js.map} +1 -1
  155. package/dist/chunks/{SupportPermissionsPage-B4xy_pCQ.js → SupportPermissionsPage-CneIhl30.js} +2 -2
  156. package/dist/chunks/{SupportPermissionsPage-B4xy_pCQ.js.map → SupportPermissionsPage-CneIhl30.js.map} +1 -1
  157. package/dist/chunks/{TemplatesPage-m5-sLJ7F.js → TemplatesPage-DStKmwHT.js} +2 -2
  158. package/dist/chunks/{TemplatesPage-m5-sLJ7F.js.map → TemplatesPage-DStKmwHT.js.map} +1 -1
  159. package/dist/chunks/{TemplatesPage-DZa0PQTE.js → TemplatesPage-X4Rrhs9p.js} +2 -2
  160. package/dist/chunks/{TemplatesPage-DZa0PQTE.js.map → TemplatesPage-X4Rrhs9p.js.map} +1 -1
  161. package/dist/chunks/{TenantCard-CqfifMrM.js → TenantCard-BUBYWtvR.js} +2 -2
  162. package/dist/chunks/{TenantCard-CqfifMrM.js.map → TenantCard-BUBYWtvR.js.map} +1 -1
  163. package/dist/chunks/{TenantCard-BJQi7Oew.js → TenantCard-CAgiB-NG.js} +2 -2
  164. package/dist/chunks/{TenantCard-BJQi7Oew.js.map → TenantCard-CAgiB-NG.js.map} +1 -1
  165. package/dist/chunks/{TenantScopeSelector-CdiYJvuH.js → TenantScopeSelector-B9vtpIZx.js} +2 -2
  166. package/dist/chunks/{TenantScopeSelector-CdiYJvuH.js.map → TenantScopeSelector-B9vtpIZx.js.map} +1 -1
  167. package/dist/chunks/{TenantScopeSelector-Cl5DD318.js → TenantScopeSelector-BAoah-mL.js} +2 -2
  168. package/dist/chunks/{TenantScopeSelector-Cl5DD318.js.map → TenantScopeSelector-BAoah-mL.js.map} +1 -1
  169. package/dist/chunks/{TicketDetailPage-C1UuMxD8.js → TicketDetailPage-BFcP4X8s.js} +2 -2
  170. package/dist/chunks/{TicketDetailPage-C1UuMxD8.js.map → TicketDetailPage-BFcP4X8s.js.map} +1 -1
  171. package/dist/chunks/{TicketDetailPage-BOC9rHu3.js → TicketDetailPage-D_Npnt4A.js} +2 -2
  172. package/dist/chunks/{TicketDetailPage-BOC9rHu3.js.map → TicketDetailPage-D_Npnt4A.js.map} +1 -1
  173. package/dist/chunks/{TicketsPage-BjaN4Baq.js → TicketsPage-DBP9kalU.js} +2 -2
  174. package/dist/chunks/{TicketsPage-BjaN4Baq.js.map → TicketsPage-DBP9kalU.js.map} +1 -1
  175. package/dist/chunks/{TicketsPage-BCgHZA-m.js → TicketsPage-p21DLhUb.js} +2 -2
  176. package/dist/chunks/{TicketsPage-BCgHZA-m.js.map → TicketsPage-p21DLhUb.js.map} +1 -1
  177. package/dist/chunks/{UserCreateTicketPage-ChQL1mVY.js → UserCreateTicketPage-DOwShnG8.js} +3 -3
  178. package/dist/chunks/UserCreateTicketPage-DOwShnG8.js.map +1 -0
  179. package/dist/chunks/{UserCreateTicketPage-DkjsHeV7.js → UserCreateTicketPage-lvlvp2u6.js} +48 -48
  180. package/dist/chunks/UserCreateTicketPage-lvlvp2u6.js.map +1 -0
  181. package/dist/chunks/{UserDashboardPage-81-3GJAQ.js → UserDashboardPage-C_tm7Pld.js} +2 -2
  182. package/dist/chunks/{UserDashboardPage-81-3GJAQ.js.map → UserDashboardPage-C_tm7Pld.js.map} +1 -1
  183. package/dist/chunks/{UserDashboardPage-BMYrtF3o.js → UserDashboardPage-Dp6q6FEW.js} +2 -2
  184. package/dist/chunks/{UserDashboardPage-BMYrtF3o.js.map → UserDashboardPage-Dp6q6FEW.js.map} +1 -1
  185. package/dist/chunks/{UserDetailPage-D6oCH2eS.js → UserDetailPage-6grZ6gmV.js} +5 -5
  186. package/dist/chunks/{UserDetailPage-D6oCH2eS.js.map → UserDetailPage-6grZ6gmV.js.map} +1 -1
  187. package/dist/chunks/{UserDetailPage-BMW8jAWG.js → UserDetailPage-DXLxO7LF.js} +2 -2
  188. package/dist/chunks/{UserDetailPage-BMW8jAWG.js.map → UserDetailPage-DXLxO7LF.js.map} +1 -1
  189. package/dist/chunks/{UserTicketDetailPage-ZH2BDWBt.js → UserTicketDetailPage-Ch9IfCPo.js} +2 -2
  190. package/dist/chunks/{UserTicketDetailPage-ZH2BDWBt.js.map → UserTicketDetailPage-Ch9IfCPo.js.map} +1 -1
  191. package/dist/chunks/{UserTicketDetailPage-Z_myXXJ0.js → UserTicketDetailPage-a4II5VEE.js} +2 -2
  192. package/dist/chunks/{UserTicketDetailPage-Z_myXXJ0.js.map → UserTicketDetailPage-a4II5VEE.js.map} +1 -1
  193. package/dist/chunks/{UsersGroupsPage-B8Ka6uRa.js → UsersGroupsPage-B7Er0V4l.js} +3 -3
  194. package/dist/chunks/{UsersGroupsPage-B8Ka6uRa.js.map → UsersGroupsPage-B7Er0V4l.js.map} +1 -1
  195. package/dist/chunks/{UsersGroupsPage-xJmGib8b.js → UsersGroupsPage-BeAv4QfV.js} +2 -2
  196. package/dist/chunks/{UsersGroupsPage-xJmGib8b.js.map → UsersGroupsPage-BeAv4QfV.js.map} +1 -1
  197. package/dist/chunks/{UsersPage-CQ38akZ_.js → UsersPage-0M1FLqOe.js} +2 -2
  198. package/dist/chunks/{UsersPage-CQ38akZ_.js.map → UsersPage-0M1FLqOe.js.map} +1 -1
  199. package/dist/chunks/{UsersPage-Bd2-vl39.js → UsersPage-ZR9r9vvf.js} +2 -2
  200. package/dist/chunks/{UsersPage-Bd2-vl39.js.map → UsersPage-ZR9r9vvf.js.map} +1 -1
  201. package/dist/chunks/{accessRequestsApi-DguOx0q0.js → accessRequestsApi-BJH8EE1K.js} +2 -2
  202. package/dist/chunks/{accessRequestsApi-DguOx0q0.js.map → accessRequestsApi-BJH8EE1K.js.map} +1 -1
  203. package/dist/chunks/{accessRequestsApi-COtWo9kC.js → accessRequestsApi-CBpF5d54.js} +2 -2
  204. package/dist/chunks/{accessRequestsApi-COtWo9kC.js.map → accessRequestsApi-CBpF5d54.js.map} +1 -1
  205. package/dist/chunks/{aiApi-CITiWGYX.js → aiApi-CkkWAvNB.js} +2 -2
  206. package/dist/chunks/{aiApi-CITiWGYX.js.map → aiApi-CkkWAvNB.js.map} +1 -1
  207. package/dist/chunks/{aiApi-BmZsud6O.js → aiApi-Dl7a2lWz.js} +2 -2
  208. package/dist/chunks/{aiApi-BmZsud6O.js.map → aiApi-Dl7a2lWz.js.map} +1 -1
  209. package/dist/chunks/{applicationAnalyticsApi-D62lc6z4.js → applicationAnalyticsApi-BwcSE_H1.js} +2 -2
  210. package/dist/chunks/{applicationAnalyticsApi-D62lc6z4.js.map → applicationAnalyticsApi-BwcSE_H1.js.map} +1 -1
  211. package/dist/chunks/{applicationAnalyticsApi-BYoEJzSN.js → applicationAnalyticsApi-DKMmDvWk.js} +2 -2
  212. package/dist/chunks/{applicationAnalyticsApi-BYoEJzSN.js.map → applicationAnalyticsApi-DKMmDvWk.js.map} +1 -1
  213. package/dist/chunks/auth-Ca2Rn6on.js +2 -0
  214. package/dist/chunks/auth-Ca2Rn6on.js.map +1 -0
  215. package/dist/chunks/auth-ClNTDOqm.js +18 -0
  216. package/dist/chunks/auth-ClNTDOqm.js.map +1 -0
  217. package/dist/chunks/auth-DECnMZjF.js +18 -0
  218. package/dist/chunks/auth-DECnMZjF.js.map +1 -0
  219. package/dist/chunks/auth-DPvxdqy4.js +18 -0
  220. package/dist/chunks/auth-DPvxdqy4.js.map +1 -0
  221. package/dist/chunks/auth-HzvnTaOm.js +2 -0
  222. package/dist/chunks/auth-HzvnTaOm.js.map +1 -0
  223. package/dist/chunks/auth-M6aNTKCH.js +2 -0
  224. package/dist/chunks/auth-M6aNTKCH.js.map +1 -0
  225. package/dist/chunks/auth-UHnAu6_e.js +2 -0
  226. package/dist/chunks/auth-UHnAu6_e.js.map +1 -0
  227. package/dist/chunks/auth-YrujJY7m.js +18 -0
  228. package/dist/chunks/auth-YrujJY7m.js.map +1 -0
  229. package/dist/chunks/{groupsApi-3CR-_g5b.js → groupsApi-BzDV3_Jc.js} +2 -2
  230. package/dist/chunks/{groupsApi-3CR-_g5b.js.map → groupsApi-BzDV3_Jc.js.map} +1 -1
  231. package/dist/chunks/{groupsApi-BUyBgf_N.js → groupsApi-CQ4vFMdP.js} +2 -2
  232. package/dist/chunks/{groupsApi-BUyBgf_N.js.map → groupsApi-CQ4vFMdP.js.map} +1 -1
  233. package/dist/chunks/{index-BIqcvvbh.js → index-BBmMbSZV.js} +9 -8
  234. package/dist/chunks/index-BBmMbSZV.js.map +1 -0
  235. package/dist/chunks/{index-_g82N2nb.js → index-BLlESTfA.js} +2 -2
  236. package/dist/chunks/{index-_g82N2nb.js.map → index-BLlESTfA.js.map} +1 -1
  237. package/dist/chunks/{index-DEOBhXS_.js → index-BPMjxWVx.js} +2 -2
  238. package/dist/chunks/{index-DEOBhXS_.js.map → index-BPMjxWVx.js.map} +1 -1
  239. package/dist/chunks/{index-Czk12A3G.js → index-CEbwdURd.js} +2 -2
  240. package/dist/chunks/{index-Czk12A3G.js.map → index-CEbwdURd.js.map} +1 -1
  241. package/dist/chunks/{index-BOKR3bw6.js → index-CUZygY5Q.js} +2 -2
  242. package/dist/chunks/{index-BOKR3bw6.js.map → index-CUZygY5Q.js.map} +1 -1
  243. package/dist/chunks/{index-IJR_91Yt.js → index-Ci1SqFiY.js} +2 -2
  244. package/dist/chunks/{index-IJR_91Yt.js.map → index-Ci1SqFiY.js.map} +1 -1
  245. package/dist/chunks/{index-Br2wsGE8.js → index-Cib93xtp.js} +2 -2
  246. package/dist/chunks/{index-Br2wsGE8.js.map → index-Cib93xtp.js.map} +1 -1
  247. package/dist/chunks/{index-BxHVPJ-j.js → index-CoHIgn5H.js} +2 -2
  248. package/dist/chunks/{index-BxHVPJ-j.js.map → index-CoHIgn5H.js.map} +1 -1
  249. package/dist/chunks/{index-DA5VyW0k.js → index-CpY95_ro.js} +2296 -2309
  250. package/dist/chunks/index-CpY95_ro.js.map +1 -0
  251. package/dist/chunks/{index-BMsjMCv9.js → index-D-2xSu5W.js} +3 -3
  252. package/dist/chunks/{index-BMsjMCv9.js.map → index-D-2xSu5W.js.map} +1 -1
  253. package/dist/chunks/{index-DIQ6Jmmq.js → index-D18t9DhC.js} +4 -4
  254. package/dist/chunks/{index-DIQ6Jmmq.js.map → index-D18t9DhC.js.map} +1 -1
  255. package/dist/chunks/index-DK5czlkn.js +48 -0
  256. package/dist/chunks/index-DK5czlkn.js.map +1 -0
  257. package/dist/chunks/{index-CxgEV-rT.js → index-DQd324n7.js} +2 -2
  258. package/dist/chunks/{index-CxgEV-rT.js.map → index-DQd324n7.js.map} +1 -1
  259. package/dist/chunks/{index-S-X8qFYW.js → index-Dbq-x5H9.js} +2 -2
  260. package/dist/chunks/{index-S-X8qFYW.js.map → index-Dbq-x5H9.js.map} +1 -1
  261. package/dist/chunks/{index-CNxx56kE.js → index-Det9dEaQ.js} +2 -2
  262. package/dist/chunks/{index-CNxx56kE.js.map → index-Det9dEaQ.js.map} +1 -1
  263. package/dist/chunks/{index-C1w97Ejz.js → index-bgT9XOKZ.js} +2 -2
  264. package/dist/chunks/{index-C1w97Ejz.js.map → index-bgT9XOKZ.js.map} +1 -1
  265. package/dist/chunks/index-h7ZrwrQg.js +2 -0
  266. package/dist/chunks/index-h7ZrwrQg.js.map +1 -0
  267. package/dist/chunks/{index-Djy4eIbB.js → index-k4USDz2P.js} +2 -2
  268. package/dist/chunks/{index-Djy4eIbB.js.map → index-k4USDz2P.js.map} +1 -1
  269. package/dist/chunks/{tenantIconMap-COKA97Ug.js → tenantIconMap-7ihIWxAh.js} +2 -2
  270. package/dist/chunks/{tenantIconMap-COKA97Ug.js.map → tenantIconMap-7ihIWxAh.js.map} +1 -1
  271. package/dist/chunks/{tenantIconMap-BuSQUUyZ.js → tenantIconMap-Dk6K-UTE.js} +2 -2
  272. package/dist/chunks/{tenantIconMap-BuSQUUyZ.js.map → tenantIconMap-Dk6K-UTE.js.map} +1 -1
  273. package/dist/chunks/{ticketingApi-C6EbupqP.js → ticketingApi-BCMKkzlv.js} +2 -2
  274. package/dist/chunks/{ticketingApi-C6EbupqP.js.map → ticketingApi-BCMKkzlv.js.map} +1 -1
  275. package/dist/chunks/{ticketingApi-DbREwHez.js → ticketingApi-Dwn7pl5z.js} +2 -2
  276. package/dist/chunks/{ticketingApi-DbREwHez.js.map → ticketingApi-Dwn7pl5z.js.map} +1 -1
  277. package/dist/chunks/{useAccessRequests-vucIb3_w.js → useAccessRequests-Du7CvowE.js} +3 -3
  278. package/dist/chunks/{useAccessRequests-vucIb3_w.js.map → useAccessRequests-Du7CvowE.js.map} +1 -1
  279. package/dist/chunks/{useAccessRequests-C0dY6y-4.js → useAccessRequests-gJ7yhWyi.js} +2 -2
  280. package/dist/chunks/{useAccessRequests-C0dY6y-4.js.map → useAccessRequests-gJ7yhWyi.js.map} +1 -1
  281. package/dist/chunks/{useUserAccessRequests-Cj0nkesW.js → useUserAccessRequests-5wWea2Jg.js} +2 -2
  282. package/dist/chunks/{useUserAccessRequests-Cj0nkesW.js.map → useUserAccessRequests-5wWea2Jg.js.map} +1 -1
  283. package/dist/chunks/{useUserAccessRequests-BBcw1Rk9.js → useUserAccessRequests-Bk_v8egy.js} +2 -2
  284. package/dist/chunks/{useUserAccessRequests-BBcw1Rk9.js.map → useUserAccessRequests-Bk_v8egy.js.map} +1 -1
  285. package/dist/components/routing/ProtectedRoute.d.ts.map +1 -1
  286. package/dist/contexts/AuthContext.d.ts.map +1 -1
  287. package/dist/pages/LoginPage.d.ts.map +1 -1
  288. package/dist/pages/platform/administration/tenants/TenantDetailPage.d.ts.map +1 -1
  289. package/dist/pages/platform/support/UserCreateTicketPage.d.ts.map +1 -1
  290. package/dist/services/api/apiClient.d.ts.map +1 -1
  291. package/dist/services/support/ticketDraftService.d.ts.map +1 -1
  292. package/dist/smartstack.cjs +1 -1
  293. package/dist/smartstack.js +6 -6
  294. package/dist/utils/permissions.generated.d.ts +288 -0
  295. package/dist/utils/permissions.generated.d.ts.map +1 -0
  296. package/dist/utils/uuid.d.ts +6 -0
  297. package/dist/utils/uuid.d.ts.map +1 -0
  298. package/package.json +1 -1
  299. package/dist/chunks/UserCreateTicketPage-ChQL1mVY.js.map +0 -1
  300. package/dist/chunks/UserCreateTicketPage-DkjsHeV7.js.map +0 -1
  301. package/dist/chunks/auth-B-hELPDB.js +0 -2
  302. package/dist/chunks/auth-B-hELPDB.js.map +0 -1
  303. package/dist/chunks/auth-BYaMuq7D.js +0 -16
  304. package/dist/chunks/auth-BYaMuq7D.js.map +0 -1
  305. package/dist/chunks/auth-C5zpZ9k7.js +0 -2
  306. package/dist/chunks/auth-C5zpZ9k7.js.map +0 -1
  307. package/dist/chunks/auth-CDpRMVv1.js +0 -16
  308. package/dist/chunks/auth-CDpRMVv1.js.map +0 -1
  309. package/dist/chunks/auth-CyPkCta2.js +0 -2
  310. package/dist/chunks/auth-CyPkCta2.js.map +0 -1
  311. package/dist/chunks/auth-DL47kvnl.js +0 -2
  312. package/dist/chunks/auth-DL47kvnl.js.map +0 -1
  313. package/dist/chunks/auth-Diiv90i1.js +0 -16
  314. package/dist/chunks/auth-Diiv90i1.js.map +0 -1
  315. package/dist/chunks/auth-rog9MvUr.js +0 -16
  316. package/dist/chunks/auth-rog9MvUr.js.map +0 -1
  317. package/dist/chunks/index-BIqcvvbh.js.map +0 -1
  318. package/dist/chunks/index-DA5VyW0k.js.map +0 -1
  319. package/dist/chunks/index-Dht6EQW1.js +0 -2
  320. package/dist/chunks/index-Dht6EQW1.js.map +0 -1
  321. package/dist/chunks/index-vXiLh35n.js +0 -48
  322. package/dist/chunks/index-vXiLh35n.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionsPage-BGI2nxCn.js","sources":["../../src/pages/platform/administration/permissions/PermissionsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Search,\r\n Loader2,\r\n ChevronRight,\r\n ChevronDown,\r\n Shield,\r\n FolderTree,\r\n List,\r\n LayoutGrid,\r\n Layers,\r\n FileCode,\r\n Sparkles,\r\n ExternalLink\r\n} from 'lucide-react';\r\nimport { adminApi, type PermissionListDto, type PermissionTreeDto } from '@/services/api/adminApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\ninterface ApplicationTreeNodeProps {\r\n readonly app: PermissionTreeDto['applications'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ApplicationTreeNode({ app, expandedNodes, toggleNode, t }: Readonly<ApplicationTreeNodeProps>) {\r\n return (\r\n <div key={app.id}>\r\n <button\r\n onClick={() => toggleNode(app.id)}\r\n className=\"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n <div className=\"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors\">\r\n {expandedNodes.has(app.id) ? (\r\n <ChevronDown className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n )}\r\n </div>\r\n <div className=\"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-3.5 h-3.5 text-[var(--info-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] text-sm\">{app.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium\">\r\n {t('permissions.levels.application')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{app.permissionPath}</code>\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {app.modules.length} {t('permissions.stats.modules').toLowerCase()}\r\n </div>\r\n </button>\r\n\r\n {expandedNodes.has(app.id) && (\r\n <div className=\"bg-[var(--bg-tertiary)]/50\">\r\n {app.modules.map(module => (\r\n <ModuleTreeNode\r\n key={module.id}\r\n module={module}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface ModuleTreeNodeProps {\r\n readonly module: PermissionTreeDto['applications'][0]['modules'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ModuleTreeNode({ module, expandedNodes, toggleNode, t }: Readonly<ModuleTreeNodeProps>) {\r\n return (\r\n <div key={module.id}>\r\n <button\r\n onClick={() => toggleNode(module.id)}\r\n className=\"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n {module.sections.length > 0 ? (\r\n <div className=\"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors\">\r\n {expandedNodes.has(module.id) ? (\r\n <ChevronDown className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"w-4 h-4\" />\r\n )}\r\n <div className=\"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-3 h-3 text-[var(--success-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-primary)]\">{module.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium\">\r\n {t('permissions.levels.module')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{module.permissionPath}</code>\r\n </div>\r\n {module.sections.length > 0 && (\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {module.sections.length} {t('permissions.stats.sections').toLowerCase()}\r\n </div>\r\n )}\r\n </button>\r\n\r\n {expandedNodes.has(module.id) && module.sections.length > 0 && (\r\n <div className=\"bg-[var(--bg-primary)]\">\r\n {module.sections.map(section => (\r\n <div\r\n key={section.id}\r\n className=\"flex items-center gap-3 py-2 px-4 pl-36 text-sm\"\r\n >\r\n <div className=\"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-3 h-3 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-[var(--text-primary)]\">{section.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n {t('permissions.levels.section')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{section.permissionPath}</code>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface PermissionListRowProps {\r\n readonly permission: PermissionListDto;\r\n readonly navigate: (path: string) => void;\r\n}\r\n\r\nfunction PermissionListRow({ permission, navigate }: Readonly<PermissionListRowProps>) {\r\n return (\r\n <tr\r\n key={permission.id}\r\n onClick={() => navigate(`/administration/permissions/permissions/${permission.id}`)}\r\n className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <code className=\"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors\">{permission.path}</code>\r\n {permission.isWildcard && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n <Sparkles className=\"w-3 h-3\" />\r\n wildcard\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <span className=\"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium\">\r\n {permission.level}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell\">{permission.description || '-'}</td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]\">\r\n {permission.rolesCount}\r\n </span>\r\n <ExternalLink className=\"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity\" />\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n}\r\n\r\nexport function PermissionsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [tree, setTree] = useState<PermissionTreeDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState('');\r\n const [viewMode, setViewMode] = useState<'list' | 'tree'>('list');\r\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());\r\n\r\n const loadPermissions = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.permissions.getAll({ search: search || undefined });\r\n setPermissions(result);\r\n } catch (err) {\r\n console.error('Failed to load permissions:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [search]);\r\n\r\n const collectAllNodeIds = (tree: PermissionTreeDto): Set<string> => {\r\n const allIds = new Set<string>();\r\n (tree.applications ?? []).forEach(app => {\r\n allIds.add(app.id);\r\n (app.modules ?? []).forEach(mod => {\r\n allIds.add(mod.id);\r\n });\r\n });\r\n return allIds;\r\n };\r\n\r\n const loadTree = async () => {\r\n try {\r\n const result = await adminApi.permissions.getTree();\r\n setTree(result);\r\n const allIds = collectAllNodeIds(result);\r\n setExpandedNodes(allIds);\r\n } catch (err) {\r\n console.error('Failed to load permission tree:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadPermissions();\r\n loadTree();\r\n }, [loadPermissions]);\r\n\r\n const handleSearch = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n loadPermissions();\r\n };\r\n\r\n const toggleNode = (id: string) => {\r\n setExpandedNodes(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const countTreeStats = (tree: PermissionTreeDto) => {\r\n const apps = tree.applications ?? [];\r\n let modules = 0;\r\n let sections = 0;\r\n apps.forEach(app => {\r\n const mods = app.modules ?? [];\r\n modules += mods.length;\r\n mods.forEach(mod => {\r\n sections += (mod.sections ?? []).length;\r\n });\r\n });\r\n return { applications: apps.length, modules, sections };\r\n };\r\n\r\n const getStats = () => {\r\n if (!tree) return { applications: 0, modules: 0, sections: 0 };\r\n return countTreeStats(tree);\r\n };\r\n\r\n const stats = getStats();\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('permissions.title') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center\">\r\n <Shield className=\"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('permissions.title')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-0.5\">{t('permissions.subtitle')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]\">\r\n <button\r\n onClick={() => setViewMode('tree')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'tree'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <FolderTree className=\"w-4 h-4\" />\r\n {t('permissions.treeView')}\r\n </button>\r\n <button\r\n onClick={() => setViewMode('list')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'list'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n {t('permissions.listView')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Cards */}\r\n <div className=\"grid grid-cols-3 gap-4\">\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.applications}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.applications')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.modules}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.modules')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.sections}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.sections')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Search Bar (List View) */}\r\n {viewMode === 'list' && (\r\n <form onSubmit={handleSearch} className=\"flex gap-2\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]\" />\r\n <input\r\n type=\"text\"\r\n value={search}\r\n onChange={e => setSearch(e.target.value)}\r\n placeholder={t('common.search')}\r\n className=\"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all\"\r\n />\r\n </div>\r\n <button\r\n type=\"submit\"\r\n className=\"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors\"\r\n >\r\n {t('common.search')}\r\n </button>\r\n </form>\r\n )}\r\n\r\n {/* Tree View */}\r\n {viewMode === 'tree' ? (\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n {loading && (\r\n <div className=\"flex justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loading && tree?.applications?.length ? (\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {tree.applications.map(app => (\r\n <ApplicationTreeNode\r\n key={app.id}\r\n app={app}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n ) : !loading && (\r\n <div className=\"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noData')}</p>\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n /* List View */\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.path')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('permissions.columns.level')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('permissions.columns.description')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.roles')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <Loader2 className=\"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]\" />\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length === 0 && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noPermissions')}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length > 0 && (\r\n permissions.map(permission => (\r\n <PermissionListRow\r\n key={permission.id}\r\n permission={permission}\r\n navigate={navigate}\r\n />\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ApplicationTreeNode","app","expandedNodes","toggleNode","t","jsxs","jsx","ChevronDown","ChevronRight","LayoutGrid","module","ModuleTreeNode","Layers","section","FileCode","PermissionListRow","permission","navigate","Sparkles","ExternalLink","PermissionsPage","useTranslation","useNavigate","permissions","setPermissions","useState","tree","setTree","loading","setLoading","search","setSearch","viewMode","setViewMode","setExpandedNodes","loadPermissions","useCallback","result","adminApi","err","collectAllNodeIds","allIds","mod","loadTree","useEffect","handleSearch","e","id","prev","next","stats","apps","modules","sections","mods","Breadcrumb","Shield","FolderTree","List","Search","Loader2"],"mappings":"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"}
1
+ {"version":3,"file":"PermissionsPage-CDSuc8vw.js","sources":["../../src/pages/platform/administration/permissions/PermissionsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Search,\r\n Loader2,\r\n ChevronRight,\r\n ChevronDown,\r\n Shield,\r\n FolderTree,\r\n List,\r\n LayoutGrid,\r\n Layers,\r\n FileCode,\r\n Sparkles,\r\n ExternalLink\r\n} from 'lucide-react';\r\nimport { adminApi, type PermissionListDto, type PermissionTreeDto } from '@/services/api/adminApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\ninterface ApplicationTreeNodeProps {\r\n readonly app: PermissionTreeDto['applications'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ApplicationTreeNode({ app, expandedNodes, toggleNode, t }: Readonly<ApplicationTreeNodeProps>) {\r\n return (\r\n <div key={app.id}>\r\n <button\r\n onClick={() => toggleNode(app.id)}\r\n className=\"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n <div className=\"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors\">\r\n {expandedNodes.has(app.id) ? (\r\n <ChevronDown className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n )}\r\n </div>\r\n <div className=\"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-3.5 h-3.5 text-[var(--info-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] text-sm\">{app.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium\">\r\n {t('permissions.levels.application')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{app.permissionPath}</code>\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {app.modules.length} {t('permissions.stats.modules').toLowerCase()}\r\n </div>\r\n </button>\r\n\r\n {expandedNodes.has(app.id) && (\r\n <div className=\"bg-[var(--bg-tertiary)]/50\">\r\n {app.modules.map(module => (\r\n <ModuleTreeNode\r\n key={module.id}\r\n module={module}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface ModuleTreeNodeProps {\r\n readonly module: PermissionTreeDto['applications'][0]['modules'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ModuleTreeNode({ module, expandedNodes, toggleNode, t }: Readonly<ModuleTreeNodeProps>) {\r\n return (\r\n <div key={module.id}>\r\n <button\r\n onClick={() => toggleNode(module.id)}\r\n className=\"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n {module.sections.length > 0 ? (\r\n <div className=\"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors\">\r\n {expandedNodes.has(module.id) ? (\r\n <ChevronDown className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"w-4 h-4\" />\r\n )}\r\n <div className=\"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-3 h-3 text-[var(--success-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-primary)]\">{module.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium\">\r\n {t('permissions.levels.module')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{module.permissionPath}</code>\r\n </div>\r\n {module.sections.length > 0 && (\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {module.sections.length} {t('permissions.stats.sections').toLowerCase()}\r\n </div>\r\n )}\r\n </button>\r\n\r\n {expandedNodes.has(module.id) && module.sections.length > 0 && (\r\n <div className=\"bg-[var(--bg-primary)]\">\r\n {module.sections.map(section => (\r\n <div\r\n key={section.id}\r\n className=\"flex items-center gap-3 py-2 px-4 pl-36 text-sm\"\r\n >\r\n <div className=\"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-3 h-3 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-[var(--text-primary)]\">{section.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n {t('permissions.levels.section')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{section.permissionPath}</code>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface PermissionListRowProps {\r\n readonly permission: PermissionListDto;\r\n readonly navigate: (path: string) => void;\r\n}\r\n\r\nfunction PermissionListRow({ permission, navigate }: Readonly<PermissionListRowProps>) {\r\n return (\r\n <tr\r\n key={permission.id}\r\n onClick={() => navigate(`/administration/permissions/permissions/${permission.id}`)}\r\n className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <code className=\"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors\">{permission.path}</code>\r\n {permission.isWildcard && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n <Sparkles className=\"w-3 h-3\" />\r\n wildcard\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <span className=\"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium\">\r\n {permission.level}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell\">{permission.description || '-'}</td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]\">\r\n {permission.rolesCount}\r\n </span>\r\n <ExternalLink className=\"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity\" />\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n}\r\n\r\nexport function PermissionsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [tree, setTree] = useState<PermissionTreeDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState('');\r\n const [viewMode, setViewMode] = useState<'list' | 'tree'>('list');\r\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());\r\n\r\n const loadPermissions = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.permissions.getAll({ search: search || undefined });\r\n setPermissions(result);\r\n } catch (err) {\r\n console.error('Failed to load permissions:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [search]);\r\n\r\n const collectAllNodeIds = (tree: PermissionTreeDto): Set<string> => {\r\n const allIds = new Set<string>();\r\n (tree.applications ?? []).forEach(app => {\r\n allIds.add(app.id);\r\n (app.modules ?? []).forEach(mod => {\r\n allIds.add(mod.id);\r\n });\r\n });\r\n return allIds;\r\n };\r\n\r\n const loadTree = async () => {\r\n try {\r\n const result = await adminApi.permissions.getTree();\r\n setTree(result);\r\n const allIds = collectAllNodeIds(result);\r\n setExpandedNodes(allIds);\r\n } catch (err) {\r\n console.error('Failed to load permission tree:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadPermissions();\r\n loadTree();\r\n }, [loadPermissions]);\r\n\r\n const handleSearch = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n loadPermissions();\r\n };\r\n\r\n const toggleNode = (id: string) => {\r\n setExpandedNodes(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const countTreeStats = (tree: PermissionTreeDto) => {\r\n const apps = tree.applications ?? [];\r\n let modules = 0;\r\n let sections = 0;\r\n apps.forEach(app => {\r\n const mods = app.modules ?? [];\r\n modules += mods.length;\r\n mods.forEach(mod => {\r\n sections += (mod.sections ?? []).length;\r\n });\r\n });\r\n return { applications: apps.length, modules, sections };\r\n };\r\n\r\n const getStats = () => {\r\n if (!tree) return { applications: 0, modules: 0, sections: 0 };\r\n return countTreeStats(tree);\r\n };\r\n\r\n const stats = getStats();\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('permissions.title') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center\">\r\n <Shield className=\"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('permissions.title')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-0.5\">{t('permissions.subtitle')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]\">\r\n <button\r\n onClick={() => setViewMode('tree')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'tree'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <FolderTree className=\"w-4 h-4\" />\r\n {t('permissions.treeView')}\r\n </button>\r\n <button\r\n onClick={() => setViewMode('list')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'list'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n {t('permissions.listView')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Cards */}\r\n <div className=\"grid grid-cols-3 gap-4\">\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.applications}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.applications')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.modules}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.modules')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.sections}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.sections')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Search Bar (List View) */}\r\n {viewMode === 'list' && (\r\n <form onSubmit={handleSearch} className=\"flex gap-2\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]\" />\r\n <input\r\n type=\"text\"\r\n value={search}\r\n onChange={e => setSearch(e.target.value)}\r\n placeholder={t('common.search')}\r\n className=\"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all\"\r\n />\r\n </div>\r\n <button\r\n type=\"submit\"\r\n className=\"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors\"\r\n >\r\n {t('common.search')}\r\n </button>\r\n </form>\r\n )}\r\n\r\n {/* Tree View */}\r\n {viewMode === 'tree' ? (\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n {loading && (\r\n <div className=\"flex justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loading && tree?.applications?.length ? (\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {tree.applications.map(app => (\r\n <ApplicationTreeNode\r\n key={app.id}\r\n app={app}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n ) : !loading && (\r\n <div className=\"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noData')}</p>\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n /* List View */\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.path')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('permissions.columns.level')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('permissions.columns.description')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.roles')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <Loader2 className=\"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]\" />\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length === 0 && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noPermissions')}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length > 0 && (\r\n permissions.map(permission => (\r\n <PermissionListRow\r\n key={permission.id}\r\n permission={permission}\r\n navigate={navigate}\r\n />\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ApplicationTreeNode","app","expandedNodes","toggleNode","t","jsxs","jsx","ChevronDown","ChevronRight","LayoutGrid","module","ModuleTreeNode","Layers","section","FileCode","PermissionListRow","permission","navigate","Sparkles","ExternalLink","PermissionsPage","useTranslation","useNavigate","permissions","setPermissions","useState","tree","setTree","loading","setLoading","search","setSearch","viewMode","setViewMode","setExpandedNodes","loadPermissions","useCallback","result","adminApi","err","collectAllNodeIds","allIds","mod","loadTree","useEffect","handleSearch","e","id","prev","next","stats","apps","modules","sections","mods","Breadcrumb","Shield","FolderTree","List","Search","Loader2"],"mappings":";;;;;;AA8BA,SAASA,EAAoB,EAAE,KAAAC,GAAK,eAAAC,GAAe,YAAAC,GAAY,GAAAC,KAAyC;AACtG,2BACG,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS,MAAMF,EAAWF,EAAI,EAAE;AAAA,QAChC,WAAU;AAAA,QAEV,UAAA;AAAA,UAAA,gBAAAK,EAAC,SAAI,WAAU,8HACZ,UAAAJ,EAAc,IAAID,EAAI,EAAE,IACvB,gBAAAK,EAACC,GAAA,EAAY,WAAU,+EAAA,CAA+E,sBAErGC,GAAA,EAAa,WAAU,gFAA+E,GAE3G;AAAA,UACA,gBAAAF,EAAC,SAAI,WAAU,+FACb,4BAACG,GAAA,EAAW,WAAU,uCAAsC,EAAA,CAC9D;AAAA,UACA,gBAAAJ,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,kDAAkD,UAAAL,EAAI,OAAM;AAAA,gCAC3E,QAAA,EAAK,WAAU,6FACb,UAAAG,EAAE,gCAAgC,EAAA,CACrC;AAAA,YAAA,GACF;AAAA,YACA,gBAAAE,EAAC,QAAA,EAAK,WAAU,iDAAiD,YAAI,eAAA,CAAe;AAAA,UAAA,GACtF;AAAA,UACA,gBAAAD,EAAC,OAAA,EAAI,WAAU,wCACZ,UAAA;AAAA,YAAAJ,EAAI,QAAQ;AAAA,YAAO;AAAA,YAAEG,EAAE,2BAA2B,EAAE,YAAA;AAAA,UAAY,EAAA,CACnE;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGDF,EAAc,IAAID,EAAI,EAAE,KACvB,gBAAAK,EAAC,OAAA,EAAI,WAAU,8BACZ,UAAAL,EAAI,QAAQ,IAAI,CAAAS,MACf,gBAAAJ;AAAA,MAACK;AAAA,MAAA;AAAA,QAEC,QAAAD;AAAA,QACA,eAAAR;AAAA,QACA,YAAAC;AAAA,QACA,GAAAC;AAAA,MAAA;AAAA,MAJKM,EAAO;AAAA,IAAA,CAMf,EAAA,CACH;AAAA,EAAA,EAAA,GAxCMT,EAAI,EA0Cd;AAEJ;AASA,SAASU,EAAe,EAAE,QAAAD,GAAQ,eAAAR,GAAe,YAAAC,GAAY,GAAAC,KAAoC;AAC/F,2BACG,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS,MAAMF,EAAWO,EAAO,EAAE;AAAA,QACnC,WAAU;AAAA,QAET,UAAA;AAAA,UAAAA,EAAO,SAAS,SAAS,IACxB,gBAAAJ,EAAC,OAAA,EAAI,WAAU,iIACZ,UAAAJ,EAAc,IAAIQ,EAAO,EAAE,IAC1B,gBAAAJ,EAACC,KAAY,WAAU,8EAAA,CAA8E,IAErG,gBAAAD,EAACE,GAAA,EAAa,WAAU,8EAAA,CAA8E,EAAA,CAE1G,IAEA,gBAAAF,EAAC,OAAA,EAAI,WAAU,WAAU;AAAA,UAE3B,gBAAAA,EAAC,SAAI,WAAU,kGACb,4BAACM,GAAA,EAAO,WAAU,sCAAqC,EAAA,CACzD;AAAA,UACA,gBAAAP,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,sCAAsC,UAAAI,EAAO,OAAM;AAAA,gCAClE,QAAA,EAAK,WAAU,mGACb,UAAAN,EAAE,2BAA2B,EAAA,CAChC;AAAA,YAAA,GACF;AAAA,YACA,gBAAAE,EAAC,QAAA,EAAK,WAAU,iDAAiD,YAAO,eAAA,CAAe;AAAA,UAAA,GACzF;AAAA,UACCI,EAAO,SAAS,SAAS,KACxB,gBAAAL,EAAC,OAAA,EAAI,WAAU,wCACZ,UAAA;AAAA,YAAAK,EAAO,SAAS;AAAA,YAAO;AAAA,YAAEN,EAAE,4BAA4B,EAAE,YAAA;AAAA,UAAY,EAAA,CACxE;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAIHF,EAAc,IAAIQ,EAAO,EAAE,KAAKA,EAAO,SAAS,SAAS,KACxD,gBAAAJ,EAAC,SAAI,WAAU,0BACZ,UAAAI,EAAO,SAAS,IAAI,CAAAG,MACnB,gBAAAR;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAU;AAAA,QAEV,UAAA;AAAA,UAAA,gBAAAC,EAAC,SAAI,WAAU,2EACb,4BAACQ,GAAA,EAAS,WAAU,sCAAqC,EAAA,CAC3D;AAAA,UACA,gBAAAT,EAAC,OAAA,EAAI,WAAU,UACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,8BAA8B,UAAAO,EAAQ,OAAM;AAAA,gCAC3D,QAAA,EAAK,WAAU,mGACb,UAAAT,EAAE,4BAA4B,EAAA,CACjC;AAAA,YAAA,GACF;AAAA,YACA,gBAAAE,EAAC,QAAA,EAAK,WAAU,iDAAiD,YAAQ,eAAA,CAAe;AAAA,UAAA,EAAA,CAC1F;AAAA,QAAA;AAAA,MAAA;AAAA,MAdKO,EAAQ;AAAA,IAAA,CAgBhB,EAAA,CACH;AAAA,EAAA,EAAA,GAxDMH,EAAO,EA0DjB;AAEJ;AAOA,SAASK,EAAkB,EAAE,YAAAC,GAAY,UAAAC,KAA8C;AACrF,SACE,gBAAAZ;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,SAAS,MAAMY,EAAS,2CAA2CD,EAAW,EAAE,EAAE;AAAA,MAClF,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAV,EAAC,QAAG,WAAU,aACZ,UAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,sMAAsM,UAAAU,EAAW,MAAK;AAAA,UACrOA,EAAW,cACV,gBAAAX,EAAC,QAAA,EAAK,WAAU,iIACd,UAAA;AAAA,YAAA,gBAAAC,EAACY,GAAA,EAAS,WAAU,UAAA,CAAU;AAAA,YAAE;AAAA,UAAA,EAAA,CAElC;AAAA,QAAA,EAAA,CAEJ,EAAA,CACF;AAAA,QACA,gBAAAZ,EAAC,MAAA,EAAG,WAAU,kCACZ,UAAA,gBAAAA,EAAC,UAAK,WAAU,qLACb,UAAAU,EAAW,MAAA,CACd,EAAA,CACF;AAAA,0BACC,MAAA,EAAG,WAAU,+DAA+D,UAAAA,EAAW,eAAe,KAAI;AAAA,0BAC1G,MAAA,EAAG,WAAU,aACZ,UAAA,gBAAAX,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,sJACb,UAAAU,EAAW,YACd;AAAA,UACA,gBAAAV,EAACa,GAAA,EAAa,WAAU,2FAAA,CAA2F;AAAA,QAAA,EAAA,CACrH,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,IA5BKH,EAAW;AAAA,EAAA;AA+BtB;AAEO,SAASI,KAAgC;AAC9C,QAAM,EAAE,EAAA,IAAMC,EAAe,OAAO,GAC9BJ,IAAWK,EAAA,GACX,CAACC,GAAaC,CAAc,IAAIC,EAA8B,CAAA,CAAE,GAChE,CAACC,GAAMC,CAAO,IAAIF,EAAmC,IAAI,GACzD,CAACG,GAASC,CAAU,IAAIJ,EAAS,EAAI,GACrC,CAACK,GAAQC,CAAS,IAAIN,EAAS,EAAE,GACjC,CAACO,GAAUC,CAAW,IAAIR,EAA0B,MAAM,GAC1D,CAACvB,GAAegC,CAAgB,IAAIT,EAAsB,oBAAI,KAAK,GAEnEU,IAAkBC,EAAY,YAAY;AAC9C,QAAI;AACF,MAAAP,EAAW,EAAI;AACf,YAAMQ,IAAS,MAAMC,EAAS,YAAY,OAAO,EAAE,QAAQR,KAAU,QAAW;AAChF,MAAAN,EAAea,CAAM;AAAA,IACvB,SAASE,GAAK;AACZ,cAAQ,MAAM,+BAA+BA,CAAG;AAAA,IAClD,UAAA;AACE,MAAAV,EAAW,EAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAACC,CAAM,CAAC,GAELU,IAAoB,CAACd,MAAyC;AAClE,UAAMe,wBAAa,IAAA;AACnB,YAACf,EAAK,gBAAgB,CAAA,GAAI,QAAQ,CAAAzB,MAAO;AACvC,MAAAwC,EAAO,IAAIxC,EAAI,EAAE,IAChBA,EAAI,WAAW,CAAA,GAAI,QAAQ,CAAAyC,MAAO;AACjC,QAAAD,EAAO,IAAIC,EAAI,EAAE;AAAA,MACnB,CAAC;AAAA,IACH,CAAC,GACMD;AAAA,EACT,GAEME,IAAW,YAAY;AAC3B,QAAI;AACF,YAAMN,IAAS,MAAMC,EAAS,YAAY,QAAA;AAC1C,MAAAX,EAAQU,CAAM;AACd,YAAMI,IAASD,EAAkBH,CAAM;AACvC,MAAAH,EAAiBO,CAAM;AAAA,IACzB,SAASF,GAAK;AACZ,cAAQ,MAAM,mCAAmCA,CAAG;AAAA,IACtD;AAAA,EACF;AAEA,EAAAK,EAAU,MAAM;AACd,IAAAT,EAAA,GACAQ,EAAA;AAAA,EACF,GAAG,CAACR,CAAe,CAAC;AAEpB,QAAMU,IAAe,CAACC,MAAuB;AAC3C,IAAAA,EAAE,eAAA,GACFX,EAAA;AAAA,EACF,GAEMhC,IAAa,CAAC4C,MAAe;AACjC,IAAAb,EAAiB,CAAAc,MAAQ;AACvB,YAAMC,IAAO,IAAI,IAAID,CAAI;AACzB,aAAIC,EAAK,IAAIF,CAAE,IACbE,EAAK,OAAOF,CAAE,IAEdE,EAAK,IAAIF,CAAE,GAENE;AAAA,IACT,CAAC;AAAA,EACH,GAqBMC,IAJCxB,KAfgB,CAACA,MAA4B;AAClD,UAAMyB,IAAOzB,EAAK,gBAAgB,CAAA;AAClC,QAAI0B,IAAU,GACVC,IAAW;AACf,WAAAF,EAAK,QAAQ,CAAAlD,MAAO;AAClB,YAAMqD,IAAOrD,EAAI,WAAW,CAAA;AAC5B,MAAAmD,KAAWE,EAAK,QAChBA,EAAK,QAAQ,CAAAZ,MAAO;AAClB,QAAAW,MAAaX,EAAI,YAAY,CAAA,GAAI;AAAA,MACnC,CAAC;AAAA,IACH,CAAC,GACM,EAAE,cAAcS,EAAK,QAAQ,SAAAC,GAAS,UAAAC,EAAA;AAAA,EAC/C,GAIwB3B,CAAI,IADR,EAAE,cAAc,GAAG,SAAS,GAAG,UAAU,EAAA;AAM7D,SACE,gBAAArB,EAAC,OAAA,EAAI,WAAU,aAEb,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAACiD;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,kBAAA;AAAA,UAClC,EAAE,OAAO,EAAE,mBAAmB,EAAA;AAAA,QAAE;AAAA,MAClC;AAAA,IAAA;AAAA,IAIF,gBAAAlD,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,SAAI,WAAU,+IACb,4BAACkD,GAAA,EAAO,WAAU,8EAA6E,EAAA,CACjG;AAAA,0BACC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAlD,EAAC,MAAA,EAAG,WAAU,iDAAiD,UAAA,EAAE,mBAAmB,GAAE;AAAA,4BACrF,KAAA,EAAE,WAAU,uCAAuC,UAAA,EAAE,sBAAsB,EAAA,CAAE;AAAA,QAAA,EAAA,CAChF;AAAA,MAAA,GACF;AAAA,MAGA,gBAAAD,EAAC,OAAA,EAAI,WAAU,sFACb,UAAA;AAAA,QAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM4B,EAAY,MAAM;AAAA,YACjC,WAAW,+FACTD,MAAa,SACT,sDACA,0FACN;AAAA,YAEA,UAAA;AAAA,cAAA,gBAAA1B,EAACmD,GAAA,EAAW,WAAU,UAAA,CAAU;AAAA,cAC/B,EAAE,sBAAsB;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAE3B,gBAAApD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM4B,EAAY,MAAM;AAAA,YACjC,WAAW,+FACTD,MAAa,SACT,sDACA,0FACN;AAAA,YAEA,UAAA;AAAA,cAAA,gBAAA1B,EAACoD,GAAA,EAAK,WAAU,UAAA,CAAU;AAAA,cACzB,EAAE,sBAAsB;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAC3B,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGA,gBAAArD,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,MAAA,gBAAAC,EAAC,SAAI,WAAU,4FACb,UAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,SAAI,WAAU,iGACb,4BAACG,GAAA,EAAW,WAAU,mCAAkC,EAAA,CAC1D;AAAA,0BACC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAH,EAAC,OAAA,EAAI,WAAU,iDAAiD,UAAA4C,EAAM,cAAa;AAAA,4BAClF,OAAA,EAAI,WAAU,wCAAwC,UAAA,EAAE,gCAAgC,EAAA,CAAE;AAAA,QAAA,EAAA,CAC7F;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA,wBACC,OAAA,EAAI,WAAU,4FACb,UAAA,gBAAA7C,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,SAAI,WAAU,oGACb,4BAACM,GAAA,EAAO,WAAU,sCAAqC,EAAA,CACzD;AAAA,0BACC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAN,EAAC,OAAA,EAAI,WAAU,iDAAiD,UAAA4C,EAAM,SAAQ;AAAA,4BAC7E,OAAA,EAAI,WAAU,wCAAwC,UAAA,EAAE,2BAA2B,EAAA,CAAE;AAAA,QAAA,EAAA,CACxF;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA,wBACC,OAAA,EAAI,WAAU,4FACb,UAAA,gBAAA7C,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,SAAI,WAAU,oGACb,4BAACQ,GAAA,EAAS,WAAU,sCAAqC,EAAA,CAC3D;AAAA,0BACC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,iDAAiD,UAAA4C,EAAM,UAAS;AAAA,4BAC9E,OAAA,EAAI,WAAU,wCAAwC,UAAA,EAAE,4BAA4B,EAAA,CAAE;AAAA,QAAA,EAAA,CACzF;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGClB,MAAa,UACZ,gBAAA3B,EAAC,UAAK,UAAUwC,GAAc,WAAU,cACtC,UAAA;AAAA,MAAA,gBAAAxC,EAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,QAAA,gBAAAC,EAACqD,GAAA,EAAO,WAAU,gFAAA,CAAgF;AAAA,QAClG,gBAAArD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,OAAOwB;AAAA,YACP,UAAU,CAAAgB,MAAKf,EAAUe,EAAE,OAAO,KAAK;AAAA,YACvC,aAAa,EAAE,eAAe;AAAA,YAC9B,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ,GACF;AAAA,MACA,gBAAAxC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UAET,YAAE,eAAe;AAAA,QAAA;AAAA,MAAA;AAAA,IACpB,GACF;AAAA,IAID0B,MAAa,SACZ,gBAAA3B,EAAC,OAAA,EAAI,WAAU,wGACZ,UAAA;AAAA,MAAAuB,KACC,gBAAAtB,EAAC,SAAI,WAAU,6BACb,4BAACsD,GAAA,EAAQ,WAAU,uDAAsD,EAAA,CAC3E;AAAA,MAED,CAAChC,KAAWF,GAAM,cAAc,SAC/B,gBAAApB,EAAC,OAAA,EAAI,WAAU,yCACZ,UAAAoB,EAAK,aAAa,IAAI,CAAAzB,MACrB,gBAAAK;AAAA,QAACN;AAAA,QAAA;AAAA,UAEC,KAAAC;AAAA,UACA,eAAAC;AAAA,UACA,YAAAC;AAAA,UACA;AAAA,QAAA;AAAA,QAJKF,EAAI;AAAA,MAAA,CAMZ,GACH,IACE,CAAC2B,KACH,gBAAAvB,EAAC,OAAA,EAAI,WAAU,gFACb,UAAA;AAAA,QAAA,gBAAAC,EAACkD,GAAA,EAAO,WAAU,6CAAA,CAA6C;AAAA,QAC/D,gBAAAlD,EAAC,KAAA,EAAG,UAAA,EAAE,oBAAoB,EAAA,CAAE;AAAA,MAAA,EAAA,CAC9B;AAAA,IAAA,GAEJ;AAAA;AAAA,wBAGC,OAAA,EAAI,WAAU,wBACb,UAAA,gBAAAD,EAAC,SAAA,EAAM,WAAU,UACf,UAAA;AAAA,QAAA,gBAAAC,EAAC,SAAA,EACC,UAAA,gBAAAD,EAAC,MAAA,EAAG,WAAU,4BACZ,UAAA;AAAA,UAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,kGAAkG,UAAA,EAAE,0BAA0B,GAAE;AAAA,4BAC7I,MAAA,EAAG,WAAU,uHAAuH,UAAA,EAAE,2BAA2B,GAAE;AAAA,4BACnK,MAAA,EAAG,WAAU,uHAAuH,UAAA,EAAE,iCAAiC,GAAE;AAAA,4BACzK,MAAA,EAAG,WAAU,kGAAkG,UAAA,EAAE,2BAA2B,EAAA,CAAE;AAAA,QAAA,EAAA,CACjJ,EAAA,CACF;AAAA,QACA,gBAAAD,EAAC,SAAA,EAAM,WAAU,yCACd,UAAA;AAAA,UAAAuB,KACC,gBAAAtB,EAAC,MAAA,EACC,UAAA,gBAAAA,EAAC,MAAA,EAAG,SAAS,GAAG,WAAU,0BACxB,UAAA,gBAAAA,EAACsD,GAAA,EAAQ,WAAU,8DAAA,CAA8D,GACnF,GACF;AAAA,UAED,CAAChC,KAAWL,EAAY,WAAW,uBACjC,MAAA,EACC,UAAA,gBAAAjB,EAAC,MAAA,EAAG,SAAS,GAAG,WAAU,0BACxB,UAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,2DACb,UAAA;AAAA,YAAA,gBAAAC,EAACkD,GAAA,EAAO,WAAU,6CAAA,CAA6C;AAAA,YAC/D,gBAAAlD,EAAC,KAAA,EAAG,UAAA,EAAE,2BAA2B,EAAA,CAAE;AAAA,UAAA,EAAA,CACrC,GACF,GACF;AAAA,UAED,CAACsB,KAAWL,EAAY,SAAS,KAChCA,EAAY,IAAI,CAAAP,MACd,gBAAAV;AAAA,YAACS;AAAA,YAAA;AAAA,cAEC,YAAAC;AAAA,cACA,UAAAC;AAAA,YAAA;AAAA,YAFKD,EAAW;AAAA,UAAA,CAInB;AAAA,QAAA,EAAA,CAEL;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA;AAAA,EAAA,GAEJ;AAEJ;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),d=require("react"),q=require("react-i18next"),R=require("react-router-dom"),r=require("lucide-react"),g=require("./index-vXiLh35n.js");function A({app:s,expandedNodes:i,toggleNode:o,t:l}){return e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>o(s.id),className:"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group",children:[e.jsx("div",{className:"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors",children:i.has(s.id)?e.jsx(r.ChevronDown,{className:"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]"}):e.jsx(r.ChevronRight,{className:"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]"})}),e.jsx("div",{className:"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center",children:e.jsx(r.LayoutGrid,{className:"w-3.5 h-3.5 text-[var(--info-text)]"})}),e.jsxs("div",{className:"flex-1 text-left",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-[var(--text-primary)] text-sm",children:s.label}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium",children:l("permissions.levels.application")})]}),e.jsx("code",{className:"text-xs text-[var(--text-tertiary)] font-mono",children:s.permissionPath})]}),e.jsxs("div",{className:"text-xs text-[var(--text-secondary)]",children:[s.modules.length," ",l("permissions.stats.modules").toLowerCase()]})]}),i.has(s.id)&&e.jsx("div",{className:"bg-[var(--bg-tertiary)]/50",children:s.modules.map(a=>e.jsx(D,{module:a,expandedNodes:i,toggleNode:o,t:l},a.id))})]},s.id)}function D({module:s,expandedNodes:i,toggleNode:o,t:l}){return e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>o(s.id),className:"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group",children:[s.sections.length>0?e.jsx("div",{className:"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors",children:i.has(s.id)?e.jsx(r.ChevronDown,{className:"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]"}):e.jsx(r.ChevronRight,{className:"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]"})}):e.jsx("div",{className:"w-4 h-4"}),e.jsx("div",{className:"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center",children:e.jsx(r.Layers,{className:"w-3 h-3 text-[var(--success-text)]"})}),e.jsxs("div",{className:"flex-1 text-left",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm text-[var(--text-primary)]",children:s.label}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium",children:l("permissions.levels.module")})]}),e.jsx("code",{className:"text-xs text-[var(--text-tertiary)] font-mono",children:s.permissionPath})]}),s.sections.length>0&&e.jsxs("div",{className:"text-xs text-[var(--text-secondary)]",children:[s.sections.length," ",l("permissions.stats.sections").toLowerCase()]})]}),i.has(s.id)&&s.sections.length>0&&e.jsx("div",{className:"bg-[var(--bg-primary)]",children:s.sections.map(a=>e.jsxs("div",{className:"flex items-center gap-3 py-2 px-4 pl-36 text-sm",children:[e.jsx("div",{className:"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center",children:e.jsx(r.FileCode,{className:"w-3 h-3 text-[var(--warning-text)]"})}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[var(--text-primary)]",children:a.label}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium",children:l("permissions.levels.section")})]}),e.jsx("code",{className:"text-xs text-[var(--text-tertiary)] font-mono",children:a.permissionPath})]})]},a.id))})]},s.id)}function F({permission:s,navigate:i}){return e.jsxs("tr",{onClick:()=>i(`/administration/permissions/permissions/${s.id}`),className:"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group",children:[e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors",children:s.path}),s.isWildcard&&e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium",children:[e.jsx(r.Sparkles,{className:"w-3 h-3"}),"wildcard"]})]})}),e.jsx("td",{className:"px-4 py-3 hidden md:table-cell",children:e.jsx("span",{className:"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium",children:s.level})}),e.jsx("td",{className:"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell",children:s.description||"-"}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]",children:s.rolesCount}),e.jsx(r.ExternalLink,{className:"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity"})]})})]},s.id)}function I(){const{t:s}=q.useTranslation("admin"),i=R.useNavigate(),[o,l]=d.useState([]),[a,N]=d.useState(null),[x,b]=d.useState(!0),[h,w]=d.useState(""),[m,j]=d.useState("list"),[S,f]=d.useState(new Set),p=d.useCallback(async()=>{try{b(!0);const t=await g.adminApi.permissions.getAll({search:h||void 0});l(t)}catch(t){console.error("Failed to load permissions:",t)}finally{b(!1)}},[h]),k=t=>{const n=new Set;return(t.applications??[]).forEach(c=>{n.add(c.id),(c.modules??[]).forEach(v=>{n.add(v.id)})}),n},C=async()=>{try{const t=await g.adminApi.permissions.getTree();N(t);const n=k(t);f(n)}catch(t){console.error("Failed to load permission tree:",t)}};d.useEffect(()=>{p(),C()},[p]);const L=t=>{t.preventDefault(),p()},P=t=>{f(n=>{const c=new Set(n);return c.has(t)?c.delete(t):c.add(t),c})},u=a?(t=>{const n=t.applications??[];let c=0,v=0;return n.forEach(T=>{const y=T.modules??[];c+=y.length,y.forEach(E=>{v+=(E.sections??[]).length})}),{applications:n.length,modules:c,sections:v}})(a):{applications:0,modules:0,sections:0};return e.jsxs("div",{className:"space-y-6",children:[e.jsx(g.Breadcrumb,{items:[{label:s("header.title"),href:"/administration"},{label:s("permissions.title")}]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center",children:e.jsx(r.Shield,{className:"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("permissions.title")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-0.5",children:s("permissions.subtitle")})]})]}),e.jsxs("div",{className:"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]",children:[e.jsxs("button",{onClick:()=>j("tree"),className:`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${m==="tree"?"bg-[var(--color-accent-500)] text-white shadow-sm":"text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,children:[e.jsx(r.FolderTree,{className:"w-4 h-4"}),s("permissions.treeView")]}),e.jsxs("button",{onClick:()=>j("list"),className:`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${m==="list"?"bg-[var(--color-accent-500)] text-white shadow-sm":"text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,children:[e.jsx(r.List,{className:"w-4 h-4"}),s("permissions.listView")]})]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-4",children:[e.jsx("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center",children:e.jsx(r.LayoutGrid,{className:"w-5 h-5 text-[var(--info-text)]"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[var(--text-primary)]",children:u.applications}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("permissions.stats.applications")})]})]})}),e.jsx("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center",children:e.jsx(r.Layers,{className:"w-5 h-5 text-[var(--success-text)]"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[var(--text-primary)]",children:u.modules}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("permissions.stats.modules")})]})]})}),e.jsx("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center",children:e.jsx(r.FileCode,{className:"w-5 h-5 text-[var(--warning-text)]"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[var(--text-primary)]",children:u.sections}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("permissions.stats.sections")})]})]})})]}),m==="list"&&e.jsxs("form",{onSubmit:L,className:"flex gap-2",children:[e.jsxs("div",{className:"relative flex-1 max-w-md",children:[e.jsx(r.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("input",{type:"text",value:h,onChange:t=>w(t.target.value),placeholder:s("common.search"),className:"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all"})]}),e.jsx("button",{type:"submit",className:"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors",children:s("common.search")})]}),m==="tree"?e.jsxs("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden",children:[x&&e.jsx("div",{className:"flex justify-center py-16",children:e.jsx(r.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-500)]"})}),!x&&a?.applications?.length?e.jsx("div",{className:"divide-y divide-[var(--border-color)]",children:a.applications.map(t=>e.jsx(A,{app:t,expandedNodes:S,toggleNode:P,t:s},t.id))}):!x&&e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]",children:[e.jsx(r.Shield,{className:"w-12 h-12 mb-4 text-[var(--text-tertiary)]"}),e.jsx("p",{children:s("permissions.noData")})]})]}):e.jsx("div",{className:"card overflow-hidden",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-[var(--bg-secondary)]",children:[e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:s("permissions.columns.path")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell",children:s("permissions.columns.level")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell",children:s("permissions.columns.description")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:s("permissions.columns.roles")})]})}),e.jsxs("tbody",{className:"divide-y divide-[var(--border-color)]",children:[x&&e.jsx("tr",{children:e.jsx("td",{colSpan:4,className:"px-6 py-16 text-center",children:e.jsx(r.Loader2,{className:"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]"})})}),!x&&o.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:4,className:"px-6 py-16 text-center",children:e.jsxs("div",{className:"flex flex-col items-center text-[var(--text-secondary)]",children:[e.jsx(r.Shield,{className:"w-12 h-12 mb-4 text-[var(--text-tertiary)]"}),e.jsx("p",{children:s("permissions.noPermissions")})]})})}),!x&&o.length>0&&o.map(t=>e.jsx(F,{permission:t,navigate:i},t.id))]})]})})]})}exports.PermissionsPage=I;
2
- //# sourceMappingURL=PermissionsPage-sauv7ct1.js.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),d=require("react"),q=require("react-i18next"),R=require("react-router-dom"),r=require("lucide-react"),g=require("./index-DK5czlkn.js");function A({app:s,expandedNodes:i,toggleNode:o,t:l}){return e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>o(s.id),className:"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group",children:[e.jsx("div",{className:"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors",children:i.has(s.id)?e.jsx(r.ChevronDown,{className:"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]"}):e.jsx(r.ChevronRight,{className:"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]"})}),e.jsx("div",{className:"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center",children:e.jsx(r.LayoutGrid,{className:"w-3.5 h-3.5 text-[var(--info-text)]"})}),e.jsxs("div",{className:"flex-1 text-left",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-[var(--text-primary)] text-sm",children:s.label}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium",children:l("permissions.levels.application")})]}),e.jsx("code",{className:"text-xs text-[var(--text-tertiary)] font-mono",children:s.permissionPath})]}),e.jsxs("div",{className:"text-xs text-[var(--text-secondary)]",children:[s.modules.length," ",l("permissions.stats.modules").toLowerCase()]})]}),i.has(s.id)&&e.jsx("div",{className:"bg-[var(--bg-tertiary)]/50",children:s.modules.map(a=>e.jsx(D,{module:a,expandedNodes:i,toggleNode:o,t:l},a.id))})]},s.id)}function D({module:s,expandedNodes:i,toggleNode:o,t:l}){return e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>o(s.id),className:"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group",children:[s.sections.length>0?e.jsx("div",{className:"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors",children:i.has(s.id)?e.jsx(r.ChevronDown,{className:"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]"}):e.jsx(r.ChevronRight,{className:"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]"})}):e.jsx("div",{className:"w-4 h-4"}),e.jsx("div",{className:"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center",children:e.jsx(r.Layers,{className:"w-3 h-3 text-[var(--success-text)]"})}),e.jsxs("div",{className:"flex-1 text-left",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm text-[var(--text-primary)]",children:s.label}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium",children:l("permissions.levels.module")})]}),e.jsx("code",{className:"text-xs text-[var(--text-tertiary)] font-mono",children:s.permissionPath})]}),s.sections.length>0&&e.jsxs("div",{className:"text-xs text-[var(--text-secondary)]",children:[s.sections.length," ",l("permissions.stats.sections").toLowerCase()]})]}),i.has(s.id)&&s.sections.length>0&&e.jsx("div",{className:"bg-[var(--bg-primary)]",children:s.sections.map(a=>e.jsxs("div",{className:"flex items-center gap-3 py-2 px-4 pl-36 text-sm",children:[e.jsx("div",{className:"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center",children:e.jsx(r.FileCode,{className:"w-3 h-3 text-[var(--warning-text)]"})}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[var(--text-primary)]",children:a.label}),e.jsx("span",{className:"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium",children:l("permissions.levels.section")})]}),e.jsx("code",{className:"text-xs text-[var(--text-tertiary)] font-mono",children:a.permissionPath})]})]},a.id))})]},s.id)}function F({permission:s,navigate:i}){return e.jsxs("tr",{onClick:()=>i(`/administration/permissions/permissions/${s.id}`),className:"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group",children:[e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors",children:s.path}),s.isWildcard&&e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium",children:[e.jsx(r.Sparkles,{className:"w-3 h-3"}),"wildcard"]})]})}),e.jsx("td",{className:"px-4 py-3 hidden md:table-cell",children:e.jsx("span",{className:"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium",children:s.level})}),e.jsx("td",{className:"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell",children:s.description||"-"}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]",children:s.rolesCount}),e.jsx(r.ExternalLink,{className:"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity"})]})})]},s.id)}function I(){const{t:s}=q.useTranslation("admin"),i=R.useNavigate(),[o,l]=d.useState([]),[a,N]=d.useState(null),[x,b]=d.useState(!0),[h,w]=d.useState(""),[m,j]=d.useState("list"),[S,f]=d.useState(new Set),p=d.useCallback(async()=>{try{b(!0);const t=await g.adminApi.permissions.getAll({search:h||void 0});l(t)}catch(t){console.error("Failed to load permissions:",t)}finally{b(!1)}},[h]),k=t=>{const n=new Set;return(t.applications??[]).forEach(c=>{n.add(c.id),(c.modules??[]).forEach(v=>{n.add(v.id)})}),n},C=async()=>{try{const t=await g.adminApi.permissions.getTree();N(t);const n=k(t);f(n)}catch(t){console.error("Failed to load permission tree:",t)}};d.useEffect(()=>{p(),C()},[p]);const L=t=>{t.preventDefault(),p()},P=t=>{f(n=>{const c=new Set(n);return c.has(t)?c.delete(t):c.add(t),c})},u=a?(t=>{const n=t.applications??[];let c=0,v=0;return n.forEach(T=>{const y=T.modules??[];c+=y.length,y.forEach(E=>{v+=(E.sections??[]).length})}),{applications:n.length,modules:c,sections:v}})(a):{applications:0,modules:0,sections:0};return e.jsxs("div",{className:"space-y-6",children:[e.jsx(g.Breadcrumb,{items:[{label:s("header.title"),href:"/administration"},{label:s("permissions.title")}]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center",children:e.jsx(r.Shield,{className:"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("permissions.title")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-0.5",children:s("permissions.subtitle")})]})]}),e.jsxs("div",{className:"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]",children:[e.jsxs("button",{onClick:()=>j("tree"),className:`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${m==="tree"?"bg-[var(--color-accent-500)] text-white shadow-sm":"text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,children:[e.jsx(r.FolderTree,{className:"w-4 h-4"}),s("permissions.treeView")]}),e.jsxs("button",{onClick:()=>j("list"),className:`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${m==="list"?"bg-[var(--color-accent-500)] text-white shadow-sm":"text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,children:[e.jsx(r.List,{className:"w-4 h-4"}),s("permissions.listView")]})]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-4",children:[e.jsx("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center",children:e.jsx(r.LayoutGrid,{className:"w-5 h-5 text-[var(--info-text)]"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[var(--text-primary)]",children:u.applications}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("permissions.stats.applications")})]})]})}),e.jsx("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center",children:e.jsx(r.Layers,{className:"w-5 h-5 text-[var(--success-text)]"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[var(--text-primary)]",children:u.modules}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("permissions.stats.modules")})]})]})}),e.jsx("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center",children:e.jsx(r.FileCode,{className:"w-5 h-5 text-[var(--warning-text)]"})}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[var(--text-primary)]",children:u.sections}),e.jsx("div",{className:"text-sm text-[var(--text-secondary)]",children:s("permissions.stats.sections")})]})]})})]}),m==="list"&&e.jsxs("form",{onSubmit:L,className:"flex gap-2",children:[e.jsxs("div",{className:"relative flex-1 max-w-md",children:[e.jsx(r.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("input",{type:"text",value:h,onChange:t=>w(t.target.value),placeholder:s("common.search"),className:"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all"})]}),e.jsx("button",{type:"submit",className:"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors",children:s("common.search")})]}),m==="tree"?e.jsxs("div",{className:"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden",children:[x&&e.jsx("div",{className:"flex justify-center py-16",children:e.jsx(r.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-500)]"})}),!x&&a?.applications?.length?e.jsx("div",{className:"divide-y divide-[var(--border-color)]",children:a.applications.map(t=>e.jsx(A,{app:t,expandedNodes:S,toggleNode:P,t:s},t.id))}):!x&&e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]",children:[e.jsx(r.Shield,{className:"w-12 h-12 mb-4 text-[var(--text-tertiary)]"}),e.jsx("p",{children:s("permissions.noData")})]})]}):e.jsx("div",{className:"card overflow-hidden",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"bg-[var(--bg-secondary)]",children:[e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:s("permissions.columns.path")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell",children:s("permissions.columns.level")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell",children:s("permissions.columns.description")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:s("permissions.columns.roles")})]})}),e.jsxs("tbody",{className:"divide-y divide-[var(--border-color)]",children:[x&&e.jsx("tr",{children:e.jsx("td",{colSpan:4,className:"px-6 py-16 text-center",children:e.jsx(r.Loader2,{className:"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]"})})}),!x&&o.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:4,className:"px-6 py-16 text-center",children:e.jsxs("div",{className:"flex flex-col items-center text-[var(--text-secondary)]",children:[e.jsx(r.Shield,{className:"w-12 h-12 mb-4 text-[var(--text-tertiary)]"}),e.jsx("p",{children:s("permissions.noPermissions")})]})})}),!x&&o.length>0&&o.map(t=>e.jsx(F,{permission:t,navigate:i},t.id))]})]})})]})}exports.PermissionsPage=I;
2
+ //# sourceMappingURL=PermissionsPage-XaOrGrPZ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionsPage-sauv7ct1.js","sources":["../../src/pages/platform/administration/permissions/PermissionsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Search,\r\n Loader2,\r\n ChevronRight,\r\n ChevronDown,\r\n Shield,\r\n FolderTree,\r\n List,\r\n LayoutGrid,\r\n Layers,\r\n FileCode,\r\n Sparkles,\r\n ExternalLink\r\n} from 'lucide-react';\r\nimport { adminApi, type PermissionListDto, type PermissionTreeDto } from '@/services/api/adminApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\ninterface ApplicationTreeNodeProps {\r\n readonly app: PermissionTreeDto['applications'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ApplicationTreeNode({ app, expandedNodes, toggleNode, t }: Readonly<ApplicationTreeNodeProps>) {\r\n return (\r\n <div key={app.id}>\r\n <button\r\n onClick={() => toggleNode(app.id)}\r\n className=\"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n <div className=\"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors\">\r\n {expandedNodes.has(app.id) ? (\r\n <ChevronDown className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n )}\r\n </div>\r\n <div className=\"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-3.5 h-3.5 text-[var(--info-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] text-sm\">{app.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium\">\r\n {t('permissions.levels.application')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{app.permissionPath}</code>\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {app.modules.length} {t('permissions.stats.modules').toLowerCase()}\r\n </div>\r\n </button>\r\n\r\n {expandedNodes.has(app.id) && (\r\n <div className=\"bg-[var(--bg-tertiary)]/50\">\r\n {app.modules.map(module => (\r\n <ModuleTreeNode\r\n key={module.id}\r\n module={module}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface ModuleTreeNodeProps {\r\n readonly module: PermissionTreeDto['applications'][0]['modules'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ModuleTreeNode({ module, expandedNodes, toggleNode, t }: Readonly<ModuleTreeNodeProps>) {\r\n return (\r\n <div key={module.id}>\r\n <button\r\n onClick={() => toggleNode(module.id)}\r\n className=\"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n {module.sections.length > 0 ? (\r\n <div className=\"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors\">\r\n {expandedNodes.has(module.id) ? (\r\n <ChevronDown className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"w-4 h-4\" />\r\n )}\r\n <div className=\"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-3 h-3 text-[var(--success-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-primary)]\">{module.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium\">\r\n {t('permissions.levels.module')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{module.permissionPath}</code>\r\n </div>\r\n {module.sections.length > 0 && (\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {module.sections.length} {t('permissions.stats.sections').toLowerCase()}\r\n </div>\r\n )}\r\n </button>\r\n\r\n {expandedNodes.has(module.id) && module.sections.length > 0 && (\r\n <div className=\"bg-[var(--bg-primary)]\">\r\n {module.sections.map(section => (\r\n <div\r\n key={section.id}\r\n className=\"flex items-center gap-3 py-2 px-4 pl-36 text-sm\"\r\n >\r\n <div className=\"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-3 h-3 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-[var(--text-primary)]\">{section.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n {t('permissions.levels.section')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{section.permissionPath}</code>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface PermissionListRowProps {\r\n readonly permission: PermissionListDto;\r\n readonly navigate: (path: string) => void;\r\n}\r\n\r\nfunction PermissionListRow({ permission, navigate }: Readonly<PermissionListRowProps>) {\r\n return (\r\n <tr\r\n key={permission.id}\r\n onClick={() => navigate(`/administration/permissions/permissions/${permission.id}`)}\r\n className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <code className=\"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors\">{permission.path}</code>\r\n {permission.isWildcard && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n <Sparkles className=\"w-3 h-3\" />\r\n wildcard\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <span className=\"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium\">\r\n {permission.level}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell\">{permission.description || '-'}</td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]\">\r\n {permission.rolesCount}\r\n </span>\r\n <ExternalLink className=\"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity\" />\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n}\r\n\r\nexport function PermissionsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [tree, setTree] = useState<PermissionTreeDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState('');\r\n const [viewMode, setViewMode] = useState<'list' | 'tree'>('list');\r\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());\r\n\r\n const loadPermissions = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.permissions.getAll({ search: search || undefined });\r\n setPermissions(result);\r\n } catch (err) {\r\n console.error('Failed to load permissions:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [search]);\r\n\r\n const collectAllNodeIds = (tree: PermissionTreeDto): Set<string> => {\r\n const allIds = new Set<string>();\r\n (tree.applications ?? []).forEach(app => {\r\n allIds.add(app.id);\r\n (app.modules ?? []).forEach(mod => {\r\n allIds.add(mod.id);\r\n });\r\n });\r\n return allIds;\r\n };\r\n\r\n const loadTree = async () => {\r\n try {\r\n const result = await adminApi.permissions.getTree();\r\n setTree(result);\r\n const allIds = collectAllNodeIds(result);\r\n setExpandedNodes(allIds);\r\n } catch (err) {\r\n console.error('Failed to load permission tree:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadPermissions();\r\n loadTree();\r\n }, [loadPermissions]);\r\n\r\n const handleSearch = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n loadPermissions();\r\n };\r\n\r\n const toggleNode = (id: string) => {\r\n setExpandedNodes(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const countTreeStats = (tree: PermissionTreeDto) => {\r\n const apps = tree.applications ?? [];\r\n let modules = 0;\r\n let sections = 0;\r\n apps.forEach(app => {\r\n const mods = app.modules ?? [];\r\n modules += mods.length;\r\n mods.forEach(mod => {\r\n sections += (mod.sections ?? []).length;\r\n });\r\n });\r\n return { applications: apps.length, modules, sections };\r\n };\r\n\r\n const getStats = () => {\r\n if (!tree) return { applications: 0, modules: 0, sections: 0 };\r\n return countTreeStats(tree);\r\n };\r\n\r\n const stats = getStats();\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('permissions.title') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center\">\r\n <Shield className=\"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('permissions.title')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-0.5\">{t('permissions.subtitle')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]\">\r\n <button\r\n onClick={() => setViewMode('tree')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'tree'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <FolderTree className=\"w-4 h-4\" />\r\n {t('permissions.treeView')}\r\n </button>\r\n <button\r\n onClick={() => setViewMode('list')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'list'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n {t('permissions.listView')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Cards */}\r\n <div className=\"grid grid-cols-3 gap-4\">\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.applications}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.applications')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.modules}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.modules')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.sections}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.sections')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Search Bar (List View) */}\r\n {viewMode === 'list' && (\r\n <form onSubmit={handleSearch} className=\"flex gap-2\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]\" />\r\n <input\r\n type=\"text\"\r\n value={search}\r\n onChange={e => setSearch(e.target.value)}\r\n placeholder={t('common.search')}\r\n className=\"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all\"\r\n />\r\n </div>\r\n <button\r\n type=\"submit\"\r\n className=\"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors\"\r\n >\r\n {t('common.search')}\r\n </button>\r\n </form>\r\n )}\r\n\r\n {/* Tree View */}\r\n {viewMode === 'tree' ? (\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n {loading && (\r\n <div className=\"flex justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loading && tree?.applications?.length ? (\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {tree.applications.map(app => (\r\n <ApplicationTreeNode\r\n key={app.id}\r\n app={app}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n ) : !loading && (\r\n <div className=\"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noData')}</p>\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n /* List View */\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.path')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('permissions.columns.level')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('permissions.columns.description')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.roles')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <Loader2 className=\"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]\" />\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length === 0 && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noPermissions')}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length > 0 && (\r\n permissions.map(permission => (\r\n <PermissionListRow\r\n key={permission.id}\r\n permission={permission}\r\n navigate={navigate}\r\n />\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ApplicationTreeNode","app","expandedNodes","toggleNode","t","jsxs","jsx","ChevronDown","ChevronRight","LayoutGrid","module","ModuleTreeNode","Layers","section","FileCode","PermissionListRow","permission","navigate","Sparkles","ExternalLink","PermissionsPage","useTranslation","useNavigate","permissions","setPermissions","useState","tree","setTree","loading","setLoading","search","setSearch","viewMode","setViewMode","setExpandedNodes","loadPermissions","useCallback","result","adminApi","err","collectAllNodeIds","allIds","mod","loadTree","useEffect","handleSearch","e","id","prev","next","stats","apps","modules","sections","mods","Breadcrumb","Shield","FolderTree","List","Search","Loader2"],"mappings":"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"}
1
+ {"version":3,"file":"PermissionsPage-XaOrGrPZ.js","sources":["../../src/pages/platform/administration/permissions/PermissionsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useNavigate } from 'react-router-dom';\r\nimport {\r\n Search,\r\n Loader2,\r\n ChevronRight,\r\n ChevronDown,\r\n Shield,\r\n FolderTree,\r\n List,\r\n LayoutGrid,\r\n Layers,\r\n FileCode,\r\n Sparkles,\r\n ExternalLink\r\n} from 'lucide-react';\r\nimport { adminApi, type PermissionListDto, type PermissionTreeDto } from '@/services/api/adminApi';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\n\r\ninterface ApplicationTreeNodeProps {\r\n readonly app: PermissionTreeDto['applications'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ApplicationTreeNode({ app, expandedNodes, toggleNode, t }: Readonly<ApplicationTreeNodeProps>) {\r\n return (\r\n <div key={app.id}>\r\n <button\r\n onClick={() => toggleNode(app.id)}\r\n className=\"w-full flex items-center gap-3 py-3 px-4 pl-14 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n <div className=\"flex items-center justify-center w-5 h-5 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--info-bg)] transition-colors\">\r\n {expandedNodes.has(app.id) ? (\r\n <ChevronDown className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3.5 h-3.5 text-[var(--text-secondary)] group-hover:text-[var(--info-text)]\" />\r\n )}\r\n </div>\r\n <div className=\"w-7 h-7 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-3.5 h-3.5 text-[var(--info-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] text-sm\">{app.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--info-bg)] text-[var(--info-text)] font-medium\">\r\n {t('permissions.levels.application')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{app.permissionPath}</code>\r\n </div>\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {app.modules.length} {t('permissions.stats.modules').toLowerCase()}\r\n </div>\r\n </button>\r\n\r\n {expandedNodes.has(app.id) && (\r\n <div className=\"bg-[var(--bg-tertiary)]/50\">\r\n {app.modules.map(module => (\r\n <ModuleTreeNode\r\n key={module.id}\r\n module={module}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface ModuleTreeNodeProps {\r\n readonly module: PermissionTreeDto['applications'][0]['modules'][0];\r\n readonly expandedNodes: Set<string>;\r\n readonly toggleNode: (id: string) => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction ModuleTreeNode({ module, expandedNodes, toggleNode, t }: Readonly<ModuleTreeNodeProps>) {\r\n return (\r\n <div key={module.id}>\r\n <button\r\n onClick={() => toggleNode(module.id)}\r\n className=\"w-full flex items-center gap-3 py-2.5 px-4 pl-24 hover:bg-[var(--bg-hover)] transition-colors group\"\r\n >\r\n {module.sections.length > 0 ? (\r\n <div className=\"flex items-center justify-center w-4 h-4 rounded bg-[var(--bg-tertiary)] group-hover:bg-[var(--success-bg)] transition-colors\">\r\n {expandedNodes.has(module.id) ? (\r\n <ChevronDown className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n ) : (\r\n <ChevronRight className=\"w-3 h-3 text-[var(--text-secondary)] group-hover:text-[var(--success-text)]\" />\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"w-4 h-4\" />\r\n )}\r\n <div className=\"w-6 h-6 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-3 h-3 text-[var(--success-text)]\" />\r\n </div>\r\n <div className=\"flex-1 text-left\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-[var(--text-primary)]\">{module.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--success-bg)] text-[var(--success-text)] font-medium\">\r\n {t('permissions.levels.module')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{module.permissionPath}</code>\r\n </div>\r\n {module.sections.length > 0 && (\r\n <div className=\"text-xs text-[var(--text-secondary)]\">\r\n {module.sections.length} {t('permissions.stats.sections').toLowerCase()}\r\n </div>\r\n )}\r\n </button>\r\n\r\n {expandedNodes.has(module.id) && module.sections.length > 0 && (\r\n <div className=\"bg-[var(--bg-primary)]\">\r\n {module.sections.map(section => (\r\n <div\r\n key={section.id}\r\n className=\"flex items-center gap-3 py-2 px-4 pl-36 text-sm\"\r\n >\r\n <div className=\"w-5 h-5 rounded bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-3 h-3 text-[var(--warning-text)]\" />\r\n </div>\r\n <div className=\"flex-1\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-[var(--text-primary)]\">{section.label}</span>\r\n <span className=\"px-1.5 py-0.5 text-[10px] rounded bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n {t('permissions.levels.section')}\r\n </span>\r\n </div>\r\n <code className=\"text-xs text-[var(--text-tertiary)] font-mono\">{section.permissionPath}</code>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\ninterface PermissionListRowProps {\r\n readonly permission: PermissionListDto;\r\n readonly navigate: (path: string) => void;\r\n}\r\n\r\nfunction PermissionListRow({ permission, navigate }: Readonly<PermissionListRowProps>) {\r\n return (\r\n <tr\r\n key={permission.id}\r\n onClick={() => navigate(`/administration/permissions/permissions/${permission.id}`)}\r\n className=\"hover:bg-[var(--bg-hover)] transition-colors cursor-pointer group\"\r\n >\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <code className=\"font-mono text-sm text-[var(--text-primary)] bg-[var(--bg-tertiary)] px-2 py-1 rounded group-hover:bg-[var(--color-accent-100)] dark:group-hover:bg-[var(--color-accent-900)]/30 transition-colors\">{permission.path}</code>\r\n {permission.isWildcard && (\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-[var(--warning-bg)] text-[var(--warning-text)] font-medium\">\r\n <Sparkles className=\"w-3 h-3\" />\r\n wildcard\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <span className=\"px-2.5 py-1 text-xs rounded-full bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 text-[var(--color-accent-700)] dark:text-[var(--color-accent-300)] font-medium\">\r\n {permission.level}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3 text-[var(--text-secondary)] hidden lg:table-cell\">{permission.description || '-'}</td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <span className=\"inline-flex items-center justify-center min-w-[2rem] px-2 py-1 text-sm font-medium rounded-full bg-[var(--bg-tertiary)] text-[var(--text-primary)]\">\r\n {permission.rolesCount}\r\n </span>\r\n <ExternalLink className=\"w-4 h-4 text-[var(--text-tertiary)] opacity-0 group-hover:opacity-100 transition-opacity\" />\r\n </div>\r\n </td>\r\n </tr>\r\n );\r\n}\r\n\r\nexport function PermissionsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [permissions, setPermissions] = useState<PermissionListDto[]>([]);\r\n const [tree, setTree] = useState<PermissionTreeDto | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState('');\r\n const [viewMode, setViewMode] = useState<'list' | 'tree'>('list');\r\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());\r\n\r\n const loadPermissions = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.permissions.getAll({ search: search || undefined });\r\n setPermissions(result);\r\n } catch (err) {\r\n console.error('Failed to load permissions:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [search]);\r\n\r\n const collectAllNodeIds = (tree: PermissionTreeDto): Set<string> => {\r\n const allIds = new Set<string>();\r\n (tree.applications ?? []).forEach(app => {\r\n allIds.add(app.id);\r\n (app.modules ?? []).forEach(mod => {\r\n allIds.add(mod.id);\r\n });\r\n });\r\n return allIds;\r\n };\r\n\r\n const loadTree = async () => {\r\n try {\r\n const result = await adminApi.permissions.getTree();\r\n setTree(result);\r\n const allIds = collectAllNodeIds(result);\r\n setExpandedNodes(allIds);\r\n } catch (err) {\r\n console.error('Failed to load permission tree:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadPermissions();\r\n loadTree();\r\n }, [loadPermissions]);\r\n\r\n const handleSearch = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n loadPermissions();\r\n };\r\n\r\n const toggleNode = (id: string) => {\r\n setExpandedNodes(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n const countTreeStats = (tree: PermissionTreeDto) => {\r\n const apps = tree.applications ?? [];\r\n let modules = 0;\r\n let sections = 0;\r\n apps.forEach(app => {\r\n const mods = app.modules ?? [];\r\n modules += mods.length;\r\n mods.forEach(mod => {\r\n sections += (mod.sections ?? []).length;\r\n });\r\n });\r\n return { applications: apps.length, modules, sections };\r\n };\r\n\r\n const getStats = () => {\r\n if (!tree) return { applications: 0, modules: 0, sections: 0 };\r\n return countTreeStats(tree);\r\n };\r\n\r\n const stats = getStats();\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('permissions.title') }\r\n ]}\r\n />\r\n\r\n {/* Page Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"w-12 h-12 rounded-[var(--radius-button)] bg-[var(--color-accent-100)] dark:bg-[var(--color-accent-900)]/30 flex items-center justify-center\">\r\n <Shield className=\"w-6 h-6 text-[var(--color-accent-600)] dark:text-[var(--color-accent-400)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('permissions.title')}</h1>\r\n <p className=\"text-[var(--text-secondary)] mt-0.5\">{t('permissions.subtitle')}</p>\r\n </div>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 bg-[var(--bg-tertiary)] rounded-[var(--radius-button)]\">\r\n <button\r\n onClick={() => setViewMode('tree')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'tree'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <FolderTree className=\"w-4 h-4\" />\r\n {t('permissions.treeView')}\r\n </button>\r\n <button\r\n onClick={() => setViewMode('list')}\r\n className={`flex items-center gap-2 px-4 py-2 rounded-[var(--radius-button)] font-medium transition-all ${\r\n viewMode === 'list'\r\n ? 'bg-[var(--color-accent-500)] text-white shadow-sm'\r\n : 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]'\r\n }`}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n {t('permissions.listView')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Stats Cards */}\r\n <div className=\"grid grid-cols-3 gap-4\">\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--info-bg)] flex items-center justify-center\">\r\n <LayoutGrid className=\"w-5 h-5 text-[var(--info-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.applications}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.applications')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--success-bg)] flex items-center justify-center\">\r\n <Layers className=\"w-5 h-5 text-[var(--success-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.modules}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.modules')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] p-4\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-10 h-10 rounded-[var(--radius-button)] bg-[var(--warning-bg)] flex items-center justify-center\">\r\n <FileCode className=\"w-5 h-5 text-[var(--warning-text)]\" />\r\n </div>\r\n <div>\r\n <div className=\"text-2xl font-bold text-[var(--text-primary)]\">{stats.sections}</div>\r\n <div className=\"text-sm text-[var(--text-secondary)]\">{t('permissions.stats.sections')}</div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Search Bar (List View) */}\r\n {viewMode === 'list' && (\r\n <form onSubmit={handleSearch} className=\"flex gap-2\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-secondary)]\" />\r\n <input\r\n type=\"text\"\r\n value={search}\r\n onChange={e => setSearch(e.target.value)}\r\n placeholder={t('common.search')}\r\n className=\"w-full pl-10 pr-4 py-2.5 rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-transparent transition-all\"\r\n />\r\n </div>\r\n <button\r\n type=\"submit\"\r\n className=\"px-4 py-2.5 rounded-[var(--radius-button)] bg-[var(--color-accent-500)] hover:bg-[var(--color-accent-600)] text-white font-medium transition-colors\"\r\n >\r\n {t('common.search')}\r\n </button>\r\n </form>\r\n )}\r\n\r\n {/* Tree View */}\r\n {viewMode === 'tree' ? (\r\n <div className=\"bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n {loading && (\r\n <div className=\"flex justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n )}\r\n {!loading && tree?.applications?.length ? (\r\n <div className=\"divide-y divide-[var(--border-color)]\">\r\n {tree.applications.map(app => (\r\n <ApplicationTreeNode\r\n key={app.id}\r\n app={app}\r\n expandedNodes={expandedNodes}\r\n toggleNode={toggleNode}\r\n t={t}\r\n />\r\n ))}\r\n </div>\r\n ) : !loading && (\r\n <div className=\"flex flex-col items-center justify-center py-16 text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noData')}</p>\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n /* List View */\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.path')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('permissions.columns.level')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('permissions.columns.description')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('permissions.columns.roles')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <Loader2 className=\"w-8 h-8 animate-spin mx-auto text-[var(--color-accent-500)]\" />\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length === 0 && (\r\n <tr>\r\n <td colSpan={4} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center text-[var(--text-secondary)]\">\r\n <Shield className=\"w-12 h-12 mb-4 text-[var(--text-tertiary)]\" />\r\n <p>{t('permissions.noPermissions')}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && permissions.length > 0 && (\r\n permissions.map(permission => (\r\n <PermissionListRow\r\n key={permission.id}\r\n permission={permission}\r\n navigate={navigate}\r\n />\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["ApplicationTreeNode","app","expandedNodes","toggleNode","t","jsxs","jsx","ChevronDown","ChevronRight","LayoutGrid","module","ModuleTreeNode","Layers","section","FileCode","PermissionListRow","permission","navigate","Sparkles","ExternalLink","PermissionsPage","useTranslation","useNavigate","permissions","setPermissions","useState","tree","setTree","loading","setLoading","search","setSearch","viewMode","setViewMode","setExpandedNodes","loadPermissions","useCallback","result","adminApi","err","collectAllNodeIds","allIds","mod","loadTree","useEffect","handleSearch","e","id","prev","next","stats","apps","modules","sections","mods","Breadcrumb","Shield","FolderTree","List","Search","Loader2"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),r=require("react-i18next"),a=require("./index-vXiLh35n.js");function o(){const{t:e}=r.useTranslation("navigation");return t.jsx(a.UnderDevelopment,{title:e("portal.title","Client Portal"),description:e("portal.description","View aggregated data from all your linked business workspaces.")})}exports.PortalDashboardPage=o;
2
- //# sourceMappingURL=PortalDashboardPage-CQWEcghD.js.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),r=require("react-i18next"),a=require("./index-DK5czlkn.js");function o(){const{t:e}=r.useTranslation("navigation");return t.jsx(a.UnderDevelopment,{title:e("portal.title","Client Portal"),description:e("portal.description","View aggregated data from all your linked business workspaces.")})}exports.PortalDashboardPage=o;
2
+ //# sourceMappingURL=PortalDashboardPage-BsWVXkMe.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PortalDashboardPage-CQWEcghD.js","sources":["../../src/pages/personal/myspace/PortalDashboardPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { UnderDevelopment } from '@/components/ui/UnderDevelopment';\r\n\r\nexport function PortalDashboardPage(): ReactElement {\r\n const { t } = useTranslation('navigation');\r\n\r\n return (\r\n <UnderDevelopment\r\n title={t('portal.title', 'Client Portal')}\r\n description={t('portal.description', 'View aggregated data from all your linked business workspaces.')}\r\n />\r\n );\r\n}\r\n"],"names":["PortalDashboardPage","t","useTranslation","jsx","UnderDevelopment"],"mappings":"iLAIO,SAASA,GAAoC,CAClD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAAA,eAAe,YAAY,EAEzC,OACEC,EAAAA,IAACC,EAAAA,iBAAA,CACC,MAAOH,EAAE,eAAgB,eAAe,EACxC,YAAaA,EAAE,qBAAsB,gEAAgE,CAAA,CAAA,CAG3G"}
1
+ {"version":3,"file":"PortalDashboardPage-BsWVXkMe.js","sources":["../../src/pages/personal/myspace/PortalDashboardPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { UnderDevelopment } from '@/components/ui/UnderDevelopment';\r\n\r\nexport function PortalDashboardPage(): ReactElement {\r\n const { t } = useTranslation('navigation');\r\n\r\n return (\r\n <UnderDevelopment\r\n title={t('portal.title', 'Client Portal')}\r\n description={t('portal.description', 'View aggregated data from all your linked business workspaces.')}\r\n />\r\n );\r\n}\r\n"],"names":["PortalDashboardPage","t","useTranslation","jsx","UnderDevelopment"],"mappings":"iLAIO,SAASA,GAAoC,CAClD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAAA,eAAe,YAAY,EAEzC,OACEC,EAAAA,IAACC,EAAAA,iBAAA,CACC,MAAOH,EAAE,eAAgB,eAAe,EACxC,YAAaA,EAAE,qBAAsB,gEAAgE,CAAA,CAAA,CAG3G"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as o } from "react/jsx-runtime";
2
2
  import { useTranslation as r } from "react-i18next";
3
- import { F as e } from "./index-DA5VyW0k.js";
3
+ import { F as e } from "./index-CpY95_ro.js";
4
4
  function s() {
5
5
  const { t } = r("navigation");
6
6
  return /* @__PURE__ */ o(
@@ -14,4 +14,4 @@ function s() {
14
14
  export {
15
15
  s as PortalDashboardPage
16
16
  };
17
- //# sourceMappingURL=PortalDashboardPage-2kCbJw9w.js.map
17
+ //# sourceMappingURL=PortalDashboardPage-oSD7oQhJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PortalDashboardPage-2kCbJw9w.js","sources":["../../src/pages/personal/myspace/PortalDashboardPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { UnderDevelopment } from '@/components/ui/UnderDevelopment';\r\n\r\nexport function PortalDashboardPage(): ReactElement {\r\n const { t } = useTranslation('navigation');\r\n\r\n return (\r\n <UnderDevelopment\r\n title={t('portal.title', 'Client Portal')}\r\n description={t('portal.description', 'View aggregated data from all your linked business workspaces.')}\r\n />\r\n );\r\n}\r\n"],"names":["PortalDashboardPage","useTranslation","jsx","UnderDevelopment"],"mappings":";;;AAIO,SAASA,IAAoC;AAClD,QAAM,EAAE,EAAA,IAAMC,EAAe,YAAY;AAEzC,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAO,EAAE,gBAAgB,eAAe;AAAA,MACxC,aAAa,EAAE,sBAAsB,gEAAgE;AAAA,IAAA;AAAA,EAAA;AAG3G;"}
1
+ {"version":3,"file":"PortalDashboardPage-oSD7oQhJ.js","sources":["../../src/pages/personal/myspace/PortalDashboardPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { UnderDevelopment } from '@/components/ui/UnderDevelopment';\r\n\r\nexport function PortalDashboardPage(): ReactElement {\r\n const { t } = useTranslation('navigation');\r\n\r\n return (\r\n <UnderDevelopment\r\n title={t('portal.title', 'Client Portal')}\r\n description={t('portal.description', 'View aggregated data from all your linked business workspaces.')}\r\n />\r\n );\r\n}\r\n"],"names":["PortalDashboardPage","useTranslation","jsx","UnderDevelopment"],"mappings":";;;AAIO,SAASA,IAAoC;AAClD,QAAM,EAAE,EAAA,IAAMC,EAAe,YAAY;AAEzC,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAO,EAAE,gBAAgB,eAAe;AAAA,MACxC,aAAa,EAAE,sBAAsB,gEAAgE;AAAA,IAAA;AAAA,EAAA;AAG3G;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),c=require("react"),oe=require("react-router-dom"),le=require("./useTabNavigation-BVtbCTd5.js"),de=require("react-i18next"),n=require("lucide-react"),u=require("./index-vXiLh35n.js");function ue(s){const l=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const x in s)if(x!=="default"){const o=Object.getOwnPropertyDescriptor(s,x);Object.defineProperty(l,x,o.get?o:{enumerable:!0,get:()=>s[x]})}}return l.default=s,Object.freeze(l)}const xe=ue(n),me=["appearance","language","notifications","favorites"];function S({name:s,className:l}){const o=xe[s];return o?e.jsx(o,{className:l}):e.jsx(n.Star,{className:l})}function ve(s,l){return s?"bg-[var(--accent-bg)] border-2 border-[var(--color-accent-500)]":l?"opacity-50 cursor-not-allowed bg-[var(--bg-tertiary)] border border-[var(--border-color)]":"bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)]"}function fe(){const{t:s,i18n:l}=de.useTranslation(["navigation","common"]),x=oe.useNavigate(),{activeTab:o,setActiveTab:$}=le.useTabNavigation("appearance",me),{loadFromServer:z,isSyncing:G,selectedThemeTenant:B}=u.useTheme(),{currentTenant:k,isLoading:C}=u.useTenant(),{menu:_}=u.useNavigation(),{favorites:f,toggleFavorite:R,isFavorite:U,canAddMore:V,maxFavorites:W,reorderFavorites:X,loading:T}=u.useFavorites(),[H,j]=c.useState(!1),[d,J]=c.useState(""),[L,D]=c.useState(null),[K,y]=c.useState(null),v=c.useRef(null),[h,F]=c.useState(!0),[p,P]=c.useState(!0),[Q,Y]=c.useState(!1),[A,E]=c.useState(!1),[Z,N]=c.useState(!1),b=c.useRef(null),w=c.useRef(!0);c.useEffect(()=>{!C&&k&&I()},[C,k]);const I=async()=>{try{const t=await u.userApi.preferences.get();F(t.emailNotifications),P(t.pushNotifications),w.current=!1}catch{w.current=!1}},M=c.useCallback(async()=>{E(!0),N(!1);try{await u.userApi.preferences.updateNotifications({emailNotifications:h,pushNotifications:p}),N(!0),setTimeout(()=>N(!1),2e3)}catch{console.error("[PreferencesPage] Failed to save notifications")}finally{E(!1)}},[h,p]);c.useEffect(()=>{if(!w.current)return b.current&&clearTimeout(b.current),b.current=setTimeout(()=>{M()},1e3),()=>{b.current&&clearTimeout(b.current)}},[h,p,M]);const ee=async()=>{const t=B===null?"global":"tenant";j(!1);try{await z(t),await I(),j(!0),setTimeout(()=>j(!1),3e3)}catch(r){console.error("[PreferencesPage] Sync failed:",r)}},te=[{id:"appearance",label:"Apparence",icon:n.Palette,description:"Personnaliser le thème et les couleurs"},{id:"language",label:"Langue",icon:n.Globe,description:"Changer la langue de l'interface"},{id:"notifications",label:"Notifications",icon:n.Bell,description:"Gérer les notifications"},{id:"favorites",label:s("common:favorites.quickAccess"),icon:n.Star,description:"Gérer vos modules favoris"}],g=[];_?.applications.forEach(t=>{(t.modules?.length??0)>0&&g.push({app:t,modules:t.modules})});const re=(t,r)=>{const a={id:t.id,code:t.code,label:t.label,icon:t.icon||"Star",route:`/${r.code}/${t.code}`,applicationCode:r.code,applicationLabel:r.label};R(a)},ae=t=>{t.route&&x(t.route)},se=(t,r)=>{D(r),v.current=t.currentTarget,t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",r.toString()),setTimeout(()=>{v.current&&(v.current.style.opacity="0.4")},0)},O=()=>{v.current&&(v.current.style.opacity="1"),D(null),y(null),v.current=null},ce=(t,r)=>{t.preventDefault(),t.dataTransfer.dropEffect="move",r!==L&&y(r)},ne=()=>{y(null)},ie=(t,r)=>{t.preventDefault();const a=L;if(a===null||a===r)return;const i=[...f],[m]=i.splice(a,1);i.splice(r,0,m),X(i),O()};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("navigation:sidebar.preferences")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:"Personnalisez votre expérience SmartStack"})]}),e.jsx("div",{className:"border-b border-[var(--item-color-border)]",children:e.jsx("nav",{className:"flex gap-1","aria-label":"Tabs",children:te.map(t=>{const r=t.icon;return e.jsxs("button",{onClick:()=>$(t.id),className:`flex items-center gap-2 px-4 py-3 text-sm font-medium transition-all border-b-2 ${o===t.id?"border-[var(--color-accent-500)] text-[var(--color-accent-600)] bg-[var(--accent-bg)]":"border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,style:{borderRadius:"var(--radius-button) var(--radius-button) 0 0"},children:[e.jsx(r,{className:"w-5 h-5"}),e.jsx("span",{children:t.label})]},t.id)})})}),e.jsxs("div",{className:"bg-[var(--bg-card)] border border-[var(--item-color-border)] p-6",style:{borderRadius:"var(--radius-card)"},children:[o==="appearance"&&e.jsx("div",{className:"space-y-4",children:e.jsx(u.ThemeCustomizer,{onSync:ee,isSyncing:G,syncSuccess:H})}),o==="language"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Langue"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Sélectionnez la langue de l'interface"})]}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:l.language?.startsWith("fr")?"Français":"English"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Langue actuelle de l'interface"})]}),e.jsx(u.LanguageSwitcher,{})]})})]}),o==="notifications"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Notifications"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Gérez vos préférences de notifications"})]}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-[var(--text-muted)]",children:[A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Loader2,{className:"w-3 h-3 animate-spin"}),e.jsx("span",{children:"Sauvegarde..."})]}),Z&&!A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Check,{className:"w-3 h-3 text-green-500"}),e.jsx("span",{className:"text-green-600",children:"Sauvegardé"})]})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Notifications par email"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Recevoir des notifications par email"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:h,onChange:t=>F(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Alertes de sécurité"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Être notifié des événements de sécurité"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:p,onChange:t=>P(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Mises à jour produit"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Nouvelles fonctionnalités et améliorations"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:Q,onChange:t=>Y(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})})]})]}),o==="favorites"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:s("common:favorites.quickAccess")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:s("common:favorites.selectModules",{count:f.length,max:W})})]}),T&&e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx(n.Loader2,{className:"w-6 h-6 animate-spin text-[var(--color-accent-500)]"}),e.jsx("span",{className:"ml-2 text-[var(--text-secondary)]",children:"Chargement des favoris..."})]}),!T&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Vos favoris actuels"}),f.length>1&&e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"Glissez pour réorganiser"})]}),f.length===0?e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:"Aucun favori sélectionné"}):e.jsx("div",{className:"flex flex-col gap-2",children:f.map((t,r)=>e.jsxs("div",{draggable:!0,onDragStart:a=>se(a,r),onDragEnd:O,onDragOver:a=>ce(a,r),onDragLeave:ne,onDrop:a=>ie(a,r),className:`flex items-center gap-2 px-3 py-2 bg-[var(--accent-bg)] border text-[var(--color-accent-500)] cursor-grab active:cursor-grabbing transition-all ${K===r?"border-[var(--color-accent-500)] border-2 scale-[1.02]":"border-[var(--color-accent-500)]/50"}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx(n.GripVertical,{className:"w-4 h-4 text-[var(--color-accent-400)] flex-shrink-0"}),e.jsx("span",{className:"text-xs text-[var(--color-accent-500)] font-mono w-4",children:r+1}),e.jsxs("button",{onClick:()=>ae(t),className:"flex items-center gap-2 hover:underline flex-1",children:[e.jsx(S,{name:t.icon,className:"w-4 h-4"}),e.jsx("span",{className:"text-sm font-medium",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",t.applicationLabel,")"]})]}),e.jsx("button",{onClick:()=>R(t),className:"p-1 hover:bg-[var(--bg-tertiary)] rounded flex-shrink-0",title:"Retirer des favoris",children:e.jsx(n.X,{className:"w-3.5 h-3.5"})})]},t.id))})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Modules disponibles"}),e.jsxs("div",{className:"relative",children:[e.jsx(n.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]"}),e.jsx("input",{type:"text",placeholder:"Rechercher un module...",value:d,onChange:t=>J(t.target.value),className:"pl-9 pr-3 py-2 w-64 bg-[var(--bg-primary)] border border-[var(--border-color)] text-sm focus:outline-none focus:border-[var(--color-accent-500)]",style:{borderRadius:"var(--radius-input)"}})]})]}),g.map(({app:t,modules:r})=>{const a=d?r.filter(i=>i.label.toLowerCase().includes(d.toLowerCase())||i.code.toLowerCase().includes(d.toLowerCase())||t.label.toLowerCase().includes(d.toLowerCase())):r;return a.length===0?null:e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(S,{name:t.icon||"Folder",className:"w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",a.length," module",a.length>1?"s":"",")"]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2",children:a.map(i=>{const m=U(i.id),q=!m&&!V;return e.jsxs("button",{onClick:()=>re(i,t),disabled:q,className:`flex items-center gap-3 p-3 transition-all ${ve(m,q)}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx("div",{className:`w-8 h-8 flex items-center justify-center ${m?"bg-[var(--color-accent-600)] text-white":"bg-[var(--bg-tertiary)] text-[var(--text-secondary)]"}`,style:{borderRadius:"var(--radius-button)"},children:e.jsx(S,{name:i.icon||"Star",className:"w-4 h-4"})}),e.jsx("span",{className:`text-sm ${m?"font-medium text-[var(--color-accent-500)]":"text-[var(--text-primary)]"}`,children:i.label}),m&&e.jsx(n.Check,{className:"w-4 h-4 text-[var(--color-accent-500)] ml-auto"})]},i.id)})})]},t.id)}),(g.length===0||d&&g.every(({modules:t})=>!t.some(r=>r.label.toLowerCase().includes(d.toLowerCase())||r.code.toLowerCase().includes(d.toLowerCase()))))&&e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:d?`Aucun module trouvé pour "${d}"`:s("common:favorites.noModules")})]})]})]})]})]})}exports.PreferencesPage=fe;
2
- //# sourceMappingURL=PreferencesPage-Bu4gaDRb.js.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),c=require("react"),oe=require("react-router-dom"),le=require("./useTabNavigation-BVtbCTd5.js"),de=require("react-i18next"),n=require("lucide-react"),u=require("./index-DK5czlkn.js");function ue(s){const l=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const x in s)if(x!=="default"){const o=Object.getOwnPropertyDescriptor(s,x);Object.defineProperty(l,x,o.get?o:{enumerable:!0,get:()=>s[x]})}}return l.default=s,Object.freeze(l)}const xe=ue(n),me=["appearance","language","notifications","favorites"];function S({name:s,className:l}){const o=xe[s];return o?e.jsx(o,{className:l}):e.jsx(n.Star,{className:l})}function ve(s,l){return s?"bg-[var(--accent-bg)] border-2 border-[var(--color-accent-500)]":l?"opacity-50 cursor-not-allowed bg-[var(--bg-tertiary)] border border-[var(--border-color)]":"bg-[var(--bg-primary)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)]"}function fe(){const{t:s,i18n:l}=de.useTranslation(["navigation","common"]),x=oe.useNavigate(),{activeTab:o,setActiveTab:$}=le.useTabNavigation("appearance",me),{loadFromServer:z,isSyncing:G,selectedThemeTenant:B}=u.useTheme(),{currentTenant:k,isLoading:C}=u.useTenant(),{menu:_}=u.useNavigation(),{favorites:f,toggleFavorite:R,isFavorite:U,canAddMore:V,maxFavorites:W,reorderFavorites:X,loading:T}=u.useFavorites(),[H,j]=c.useState(!1),[d,J]=c.useState(""),[L,D]=c.useState(null),[K,y]=c.useState(null),v=c.useRef(null),[h,F]=c.useState(!0),[p,P]=c.useState(!0),[Q,Y]=c.useState(!1),[A,E]=c.useState(!1),[Z,N]=c.useState(!1),b=c.useRef(null),w=c.useRef(!0);c.useEffect(()=>{!C&&k&&I()},[C,k]);const I=async()=>{try{const t=await u.userApi.preferences.get();F(t.emailNotifications),P(t.pushNotifications),w.current=!1}catch{w.current=!1}},M=c.useCallback(async()=>{E(!0),N(!1);try{await u.userApi.preferences.updateNotifications({emailNotifications:h,pushNotifications:p}),N(!0),setTimeout(()=>N(!1),2e3)}catch{console.error("[PreferencesPage] Failed to save notifications")}finally{E(!1)}},[h,p]);c.useEffect(()=>{if(!w.current)return b.current&&clearTimeout(b.current),b.current=setTimeout(()=>{M()},1e3),()=>{b.current&&clearTimeout(b.current)}},[h,p,M]);const ee=async()=>{const t=B===null?"global":"tenant";j(!1);try{await z(t),await I(),j(!0),setTimeout(()=>j(!1),3e3)}catch(r){console.error("[PreferencesPage] Sync failed:",r)}},te=[{id:"appearance",label:"Apparence",icon:n.Palette,description:"Personnaliser le thème et les couleurs"},{id:"language",label:"Langue",icon:n.Globe,description:"Changer la langue de l'interface"},{id:"notifications",label:"Notifications",icon:n.Bell,description:"Gérer les notifications"},{id:"favorites",label:s("common:favorites.quickAccess"),icon:n.Star,description:"Gérer vos modules favoris"}],g=[];_?.applications.forEach(t=>{(t.modules?.length??0)>0&&g.push({app:t,modules:t.modules})});const re=(t,r)=>{const a={id:t.id,code:t.code,label:t.label,icon:t.icon||"Star",route:`/${r.code}/${t.code}`,applicationCode:r.code,applicationLabel:r.label};R(a)},ae=t=>{t.route&&x(t.route)},se=(t,r)=>{D(r),v.current=t.currentTarget,t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",r.toString()),setTimeout(()=>{v.current&&(v.current.style.opacity="0.4")},0)},O=()=>{v.current&&(v.current.style.opacity="1"),D(null),y(null),v.current=null},ce=(t,r)=>{t.preventDefault(),t.dataTransfer.dropEffect="move",r!==L&&y(r)},ne=()=>{y(null)},ie=(t,r)=>{t.preventDefault();const a=L;if(a===null||a===r)return;const i=[...f],[m]=i.splice(a,1);i.splice(r,0,m),X(i),O()};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("navigation:sidebar.preferences")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:"Personnalisez votre expérience SmartStack"})]}),e.jsx("div",{className:"border-b border-[var(--item-color-border)]",children:e.jsx("nav",{className:"flex gap-1","aria-label":"Tabs",children:te.map(t=>{const r=t.icon;return e.jsxs("button",{onClick:()=>$(t.id),className:`flex items-center gap-2 px-4 py-3 text-sm font-medium transition-all border-b-2 ${o===t.id?"border-[var(--color-accent-500)] text-[var(--color-accent-600)] bg-[var(--accent-bg)]":"border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]"}`,style:{borderRadius:"var(--radius-button) var(--radius-button) 0 0"},children:[e.jsx(r,{className:"w-5 h-5"}),e.jsx("span",{children:t.label})]},t.id)})})}),e.jsxs("div",{className:"bg-[var(--bg-card)] border border-[var(--item-color-border)] p-6",style:{borderRadius:"var(--radius-card)"},children:[o==="appearance"&&e.jsx("div",{className:"space-y-4",children:e.jsx(u.ThemeCustomizer,{onSync:ee,isSyncing:G,syncSuccess:H})}),o==="language"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Langue"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Sélectionnez la langue de l'interface"})]}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:l.language?.startsWith("fr")?"Français":"English"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Langue actuelle de l'interface"})]}),e.jsx(u.LanguageSwitcher,{})]})})]}),o==="notifications"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:"Notifications"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Gérez vos préférences de notifications"})]}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-[var(--text-muted)]",children:[A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Loader2,{className:"w-3 h-3 animate-spin"}),e.jsx("span",{children:"Sauvegarde..."})]}),Z&&!A&&e.jsxs(e.Fragment,{children:[e.jsx(n.Check,{className:"w-3 h-3 text-green-500"}),e.jsx("span",{className:"text-green-600",children:"Sauvegardé"})]})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Notifications par email"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Recevoir des notifications par email"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:h,onChange:t=>F(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Alertes de sécurité"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Être notifié des événements de sécurité"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:p,onChange:t=>P(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})}),e.jsx("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Mises à jour produit"}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:"Nouvelles fonctionnalités et améliorations"})]}),e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"sr-only peer",checked:Q,onChange:t=>Y(t.target.checked)}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer peer-checked:bg-[var(--color-accent-500)] after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:h-5 after:w-5 after:transition-all peer-checked:after:translate-x-full",style:{borderRadius:"var(--radius-button)"},children:e.jsx("span",{className:"after:rounded-full"})})]})]})})]})]}),o==="favorites"&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:s("common:favorites.quickAccess")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:s("common:favorites.selectModules",{count:f.length,max:W})})]}),T&&e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx(n.Loader2,{className:"w-6 h-6 animate-spin text-[var(--color-accent-500)]"}),e.jsx("span",{className:"ml-2 text-[var(--text-secondary)]",children:"Chargement des favoris..."})]}),!T&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Vos favoris actuels"}),f.length>1&&e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"Glissez pour réorganiser"})]}),f.length===0?e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:"Aucun favori sélectionné"}):e.jsx("div",{className:"flex flex-col gap-2",children:f.map((t,r)=>e.jsxs("div",{draggable:!0,onDragStart:a=>se(a,r),onDragEnd:O,onDragOver:a=>ce(a,r),onDragLeave:ne,onDrop:a=>ie(a,r),className:`flex items-center gap-2 px-3 py-2 bg-[var(--accent-bg)] border text-[var(--color-accent-500)] cursor-grab active:cursor-grabbing transition-all ${K===r?"border-[var(--color-accent-500)] border-2 scale-[1.02]":"border-[var(--color-accent-500)]/50"}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx(n.GripVertical,{className:"w-4 h-4 text-[var(--color-accent-400)] flex-shrink-0"}),e.jsx("span",{className:"text-xs text-[var(--color-accent-500)] font-mono w-4",children:r+1}),e.jsxs("button",{onClick:()=>ae(t),className:"flex items-center gap-2 hover:underline flex-1",children:[e.jsx(S,{name:t.icon,className:"w-4 h-4"}),e.jsx("span",{className:"text-sm font-medium",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",t.applicationLabel,")"]})]}),e.jsx("button",{onClick:()=>R(t),className:"p-1 hover:bg-[var(--bg-tertiary)] rounded flex-shrink-0",title:"Retirer des favoris",children:e.jsx(n.X,{className:"w-3.5 h-3.5"})})]},t.id))})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)]",children:"Modules disponibles"}),e.jsxs("div",{className:"relative",children:[e.jsx(n.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)]"}),e.jsx("input",{type:"text",placeholder:"Rechercher un module...",value:d,onChange:t=>J(t.target.value),className:"pl-9 pr-3 py-2 w-64 bg-[var(--bg-primary)] border border-[var(--border-color)] text-sm focus:outline-none focus:border-[var(--color-accent-500)]",style:{borderRadius:"var(--radius-input)"}})]})]}),g.map(({app:t,modules:r})=>{const a=d?r.filter(i=>i.label.toLowerCase().includes(d.toLowerCase())||i.code.toLowerCase().includes(d.toLowerCase())||t.label.toLowerCase().includes(d.toLowerCase())):r;return a.length===0?null:e.jsxs("div",{className:"p-4 bg-[var(--bg-secondary)] border border-[var(--item-color-border)]",style:{borderRadius:"var(--radius-card)"},children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(S,{name:t.icon||"Folder",className:"w-4 h-4 text-[var(--text-secondary)]"}),e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t.label}),e.jsxs("span",{className:"text-xs text-[var(--text-muted)]",children:["(",a.length," module",a.length>1?"s":"",")"]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2",children:a.map(i=>{const m=U(i.id),q=!m&&!V;return e.jsxs("button",{onClick:()=>re(i,t),disabled:q,className:`flex items-center gap-3 p-3 transition-all ${ve(m,q)}`,style:{borderRadius:"var(--radius-button)"},children:[e.jsx("div",{className:`w-8 h-8 flex items-center justify-center ${m?"bg-[var(--color-accent-600)] text-white":"bg-[var(--bg-tertiary)] text-[var(--text-secondary)]"}`,style:{borderRadius:"var(--radius-button)"},children:e.jsx(S,{name:i.icon||"Star",className:"w-4 h-4"})}),e.jsx("span",{className:`text-sm ${m?"font-medium text-[var(--color-accent-500)]":"text-[var(--text-primary)]"}`,children:i.label}),m&&e.jsx(n.Check,{className:"w-4 h-4 text-[var(--color-accent-500)] ml-auto"})]},i.id)})})]},t.id)}),(g.length===0||d&&g.every(({modules:t})=>!t.some(r=>r.label.toLowerCase().includes(d.toLowerCase())||r.code.toLowerCase().includes(d.toLowerCase()))))&&e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:d?`Aucun module trouvé pour "${d}"`:s("common:favorites.noModules")})]})]})]})]})]})}exports.PreferencesPage=fe;
2
+ //# sourceMappingURL=PreferencesPage-DD0_XWdT.js.map