@atlashub/smartstack 3.39.0 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{AgentSkillsPage-DgqyaZwI.js → AgentSkillsPage-BS_W2KTh.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-DgqyaZwI.js.map → AgentSkillsPage-BS_W2KTh.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js → AgentSkillsPage-CmDFLnp7.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js.map → AgentSkillsPage-CmDFLnp7.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js → AgentWorkloadPage-C8IvYfhT.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js.map → AgentWorkloadPage-C8IvYfhT.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js → AgentWorkloadPage-JXsQbwuM.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js.map → AgentWorkloadPage-JXsQbwuM.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js → ApiCatalogDetailPage-CYOt34Vy.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js.map → ApiCatalogDetailPage-CYOt34Vy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js → ApiCatalogDetailPage-wFZDsTGy.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js.map → ApiCatalogDetailPage-wFZDsTGy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js → ApiCatalogPage-Bdm3HNGP.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js.map → ApiCatalogPage-Bdm3HNGP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js → ApiCatalogPage-m_TWQyGv.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js.map → ApiCatalogPage-m_TWQyGv.js.map} +1 -1
- package/dist/chunks/ApplicationDetailPage-C2BSpEoW.js +2 -0
- package/dist/chunks/{ApplicationDetailPage-CWdz0TS4.js.map → ApplicationDetailPage-C2BSpEoW.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js → ApplicationDetailPage-CcgDAP-J.js} +503 -501
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js.map → ApplicationDetailPage-CcgDAP-J.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js → ApplicationsDashboardPage-CDIjziL3.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js.map → ApplicationsDashboardPage-CDIjziL3.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js → ApplicationsDashboardPage-DslDyNzJ.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js.map → ApplicationsDashboardPage-DslDyNzJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js → ApplicationsGridPage-BCjsQGU0.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js.map → ApplicationsGridPage-BCjsQGU0.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js → ApplicationsGridPage-CIfKiCND.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js.map → ApplicationsGridPage-CIfKiCND.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js → ApplicationsListPage-CT75kNcH.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js.map → ApplicationsListPage-CT75kNcH.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js → ApplicationsListPage-D2B4PZ5n.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js.map → ApplicationsListPage-D2B4PZ5n.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js → ApplicationsPage-CaTBtduL.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js.map → ApplicationsPage-CaTBtduL.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js → ApplicationsPage-DW1LhL0U.js} +4 -4
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js.map → ApplicationsPage-DW1LhL0U.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js → AssignmentRulesPage-Bt9M0ki7.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js.map → AssignmentRulesPage-Bt9M0ki7.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js → AssignmentRulesPage-Y7xv60NY.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js.map → AssignmentRulesPage-Y7xv60NY.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js → AssignmentsPage-1eQGTjTi.js} +2 -2
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js.map → AssignmentsPage-1eQGTjTi.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js → AssignmentsPage-RURdPvfZ.js} +2 -2
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js.map → AssignmentsPage-RURdPvfZ.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js → AuthCallbackPage-8hF0jYlK.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js.map → AuthCallbackPage-8hF0jYlK.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js → AuthCallbackPage-DPL68Asu.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js.map → AuthCallbackPage-DPL68Asu.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js → ConfirmEmailPage-BKlpZkVk.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js.map → ConfirmEmailPage-BKlpZkVk.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js → ConfirmEmailPage-CawSZypI.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js.map → ConfirmEmailPage-CawSZypI.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js → CreateSupportTicketPage-AwbMbBIH.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js.map → CreateSupportTicketPage-AwbMbBIH.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js → CreateSupportTicketPage-Dg1YW1eA.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js.map → CreateSupportTicketPage-Dg1YW1eA.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js → DashboardPage-B4YxOF-9.js} +3 -3
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js.map → DashboardPage-B4YxOF-9.js.map} +1 -1
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js → DashboardPage-BZxjinar.js} +2 -2
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js.map → DashboardPage-BZxjinar.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BAqpoxCW.js → DashboardPage-Bo09y8r7.js} +3 -3
- package/dist/chunks/{DashboardPage-BAqpoxCW.js.map → DashboardPage-Bo09y8r7.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BT5kFaQA.js → DashboardPage-Cq5adDjP.js} +2 -2
- package/dist/chunks/{DashboardPage-BT5kFaQA.js.map → DashboardPage-Cq5adDjP.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js → EscalationConfigPage-C8Hv5naz.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js.map → EscalationConfigPage-C8Hv5naz.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js → EscalationConfigPage-DNAqMRxA.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js.map → EscalationConfigPage-DNAqMRxA.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js → ForceChangePasswordPage-BURE_vNg.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js.map → ForceChangePasswordPage-BURE_vNg.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js → ForceChangePasswordPage-C6jDZshk.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js.map → ForceChangePasswordPage-C6jDZshk.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js → ForgotPasswordPage-C5HLYbz4.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js.map → ForgotPasswordPage-C5HLYbz4.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js → ForgotPasswordPage-D3ZQBtjd.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js.map → ForgotPasswordPage-D3ZQBtjd.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js → GroupDetailPage-CTuzp9Vp.js} +5 -5
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js.map → GroupDetailPage-CTuzp9Vp.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js → GroupDetailPage-NJc2zCxC.js} +2 -2
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js.map → GroupDetailPage-NJc2zCxC.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js → MyAccessRequestsPage-Cvr29Pnq.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js.map → MyAccessRequestsPage-Cvr29Pnq.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js → MyAccessRequestsPage-t6I24rHN.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js.map → MyAccessRequestsPage-t6I24rHN.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js → MyTenantsPage-Dy2RZ_Ei.js} +2 -2
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js.map → MyTenantsPage-Dy2RZ_Ei.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js → MyTenantsPage-SvDCQ4Wt.js} +3 -3
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js.map → MyTenantsPage-SvDCQ4Wt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js → MyTicketsPage-C3lEBFD9.js} +2 -2
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js.map → MyTicketsPage-C3lEBFD9.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js → MyTicketsPage-DydDgFyz.js} +2 -2
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js.map → MyTicketsPage-DydDgFyz.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js → NavigationAppsPage-Dyv767w8.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js.map → NavigationAppsPage-Dyv767w8.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js → NavigationAppsPage-WqSspaVo.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js.map → NavigationAppsPage-WqSspaVo.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-_62-bmuk.js → NotificationsPage-Di4I95PM.js} +2 -2
- package/dist/chunks/{NotificationsPage-_62-bmuk.js.map → NotificationsPage-Di4I95PM.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js → NotificationsPage-elSovpBw.js} +2 -2
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js.map → NotificationsPage-elSovpBw.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js → OnboardingWizardPage-fdWdkwiT.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js.map → OnboardingWizardPage-fdWdkwiT.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js → OnboardingWizardPage-nPLe2buQ.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js.map → OnboardingWizardPage-nPLe2buQ.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js → PermissionDetailPage-B8C7tWFP.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js.map → PermissionDetailPage-B8C7tWFP.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js → PermissionDetailPage-IUgUaTkE.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js.map → PermissionDetailPage-IUgUaTkE.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js → PermissionsPage-CmX5sQf2.js} +2 -2
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js.map → PermissionsPage-CmX5sQf2.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js → PermissionsPage-Kg0rduOM.js} +2 -2
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js.map → PermissionsPage-Kg0rduOM.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js → PortalDashboardPage-CCAYuhtI.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js.map → PortalDashboardPage-CCAYuhtI.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js → PortalDashboardPage-Dme1XmzN.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js.map → PortalDashboardPage-Dme1XmzN.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js → PreferencesPage-Ct6xWAFp.js} +2 -2
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js.map → PreferencesPage-Ct6xWAFp.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js → PreferencesPage-Db2RjMpm.js} +2 -2
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js.map → PreferencesPage-Db2RjMpm.js.map} +1 -1
- package/dist/chunks/{ProfilePage-6Gf7igUI.js → ProfilePage-D6Xb1ALH.js} +2 -2
- package/dist/chunks/{ProfilePage-6Gf7igUI.js.map → ProfilePage-D6Xb1ALH.js.map} +1 -1
- package/dist/chunks/{ProfilePage-BzBWkztf.js → ProfilePage-DN2s-lfp.js} +2 -2
- package/dist/chunks/{ProfilePage-BzBWkztf.js.map → ProfilePage-DN2s-lfp.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js → ReferencesManagementPage-B5mcshG1.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js.map → ReferencesManagementPage-B5mcshG1.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js → ReferencesManagementPage-DB975ktX.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js.map → ReferencesManagementPage-DB975ktX.js.map} +1 -1
- package/dist/chunks/{RegisterPage-asdx33fV.js → RegisterPage-ZskZrLZH.js} +2 -2
- package/dist/chunks/{RegisterPage-asdx33fV.js.map → RegisterPage-ZskZrLZH.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CIPHRYkl.js → RegisterPage-b8yIPVgh.js} +2 -2
- package/dist/chunks/{RegisterPage-CIPHRYkl.js.map → RegisterPage-b8yIPVgh.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js → ResetPasswordPage-CeAvfsE-.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js.map → ResetPasswordPage-CeAvfsE-.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js → ResetPasswordPage-Dzp5dCp8.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js.map → ResetPasswordPage-Dzp5dCp8.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Cs6T441o.js → ResolutionModal-CRVN7gHv.js} +2 -2
- package/dist/chunks/{ResolutionModal-Cs6T441o.js.map → ResolutionModal-CRVN7gHv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js → ResolutionModal-DJOw1sLT.js} +2 -2
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js.map → ResolutionModal-DJOw1sLT.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js → RoleDetailPage-CLVoFVF8.js} +2 -2
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js.map → RoleDetailPage-CLVoFVF8.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js → RoleDetailPage-XGnPD_8C.js} +3 -3
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js.map → RoleDetailPage-XGnPD_8C.js.map} +1 -1
- package/dist/chunks/{RolesPage-BHEkMR2O.js → RolesPage-BnAMpR2b.js} +2 -2
- package/dist/chunks/{RolesPage-BHEkMR2O.js.map → RolesPage-BnAMpR2b.js.map} +1 -1
- package/dist/chunks/{RolesPage-D35jwDJU.js → RolesPage-Czj9LMkL.js} +2 -2
- package/dist/chunks/{RolesPage-D35jwDJU.js.map → RolesPage-Czj9LMkL.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-DtonDehw.js → SlaConfigPage-HM0MpIlg.js} +2 -2
- package/dist/chunks/{SlaConfigPage-DtonDehw.js.map → SlaConfigPage-HM0MpIlg.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js → SlaConfigPage-ZRyAs8aY.js} +2 -2
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js.map → SlaConfigPage-ZRyAs8aY.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js → SupportPermissionsPage-CxJuGgcQ.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js.map → SupportPermissionsPage-CxJuGgcQ.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js → SupportPermissionsPage-DNd323OK.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js.map → SupportPermissionsPage-DNd323OK.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js → TemplatesPage-CdwPLsHj.js} +2 -2
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js.map → TemplatesPage-CdwPLsHj.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DlY91VO_.js → TemplatesPage-Co3ygZvF.js} +2 -2
- package/dist/chunks/{TemplatesPage-DlY91VO_.js.map → TemplatesPage-Co3ygZvF.js.map} +1 -1
- package/dist/chunks/{TenantCard-BHLcv2gD.js → TenantCard-CmCfIK2F.js} +2 -2
- package/dist/chunks/{TenantCard-BHLcv2gD.js.map → TenantCard-CmCfIK2F.js.map} +1 -1
- package/dist/chunks/{TenantCard-DGCKVvKI.js → TenantCard-DI66acce.js} +2 -2
- package/dist/chunks/{TenantCard-DGCKVvKI.js.map → TenantCard-DI66acce.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js → TenantScopeSelector-5NOwmFX2.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js.map → TenantScopeSelector-5NOwmFX2.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js → TenantScopeSelector-CEFgxiWt.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js.map → TenantScopeSelector-CEFgxiWt.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js → TicketDetailPage-BhZ-mpv7.js} +2 -2
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js.map → TicketDetailPage-BhZ-mpv7.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js → TicketDetailPage-BxOiOG22.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js.map → TicketDetailPage-BxOiOG22.js.map} +1 -1
- package/dist/chunks/{TicketsPage-CufUJctx.js → TicketsPage-BiTvIcM8.js} +2 -2
- package/dist/chunks/{TicketsPage-CufUJctx.js.map → TicketsPage-BiTvIcM8.js.map} +1 -1
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js → TicketsPage-CSiinHME.js} +2 -2
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js.map → TicketsPage-CSiinHME.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js → UserCreateTicketPage-B3TW1oV7.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js.map → UserCreateTicketPage-B3TW1oV7.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js → UserCreateTicketPage-BszUd_WZ.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js.map → UserCreateTicketPage-BszUd_WZ.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js → UserDashboardPage-C6MvatAb.js} +2 -2
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js.map → UserDashboardPage-C6MvatAb.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js → UserDashboardPage-Dtt9VzG_.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js.map → UserDashboardPage-Dtt9VzG_.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-C97e-Dax.js → UserDetailPage-BEEV2vlJ.js} +5 -5
- package/dist/chunks/{UserDetailPage-C97e-Dax.js.map → UserDetailPage-BEEV2vlJ.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js → UserDetailPage-Dw5OHheZ.js} +2 -2
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js.map → UserDetailPage-Dw5OHheZ.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js → UserTicketDetailPage-B4YkzzbR.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js.map → UserTicketDetailPage-B4YkzzbR.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js → UserTicketDetailPage-DCFV-0ny.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js.map → UserTicketDetailPage-DCFV-0ny.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js → UsersGroupsPage-CY-l9fTp.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js.map → UsersGroupsPage-CY-l9fTp.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js → UsersGroupsPage-c28vYHN9.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js.map → UsersGroupsPage-c28vYHN9.js.map} +1 -1
- package/dist/chunks/{UsersPage-BIXWHFmG.js → UsersPage-1sLlq9QD.js} +2 -2
- package/dist/chunks/{UsersPage-BIXWHFmG.js.map → UsersPage-1sLlq9QD.js.map} +1 -1
- package/dist/chunks/{UsersPage-DS8aWUKj.js → UsersPage-Bm-uNxh0.js} +2 -2
- package/dist/chunks/{UsersPage-DS8aWUKj.js.map → UsersPage-Bm-uNxh0.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js → accessRequestsApi-CJPjyEkH.js} +2 -2
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js.map → accessRequestsApi-CJPjyEkH.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js → accessRequestsApi-D_pj1wl6.js} +2 -2
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js.map → accessRequestsApi-D_pj1wl6.js.map} +1 -1
- package/dist/chunks/{aiApi-B-H-76wM.js → aiApi-ByF-oo1J.js} +2 -2
- package/dist/chunks/{aiApi-B-H-76wM.js.map → aiApi-ByF-oo1J.js.map} +1 -1
- package/dist/chunks/{aiApi-CcdrBILv.js → aiApi-Dt3fj0dU.js} +2 -2
- package/dist/chunks/{aiApi-CcdrBILv.js.map → aiApi-Dt3fj0dU.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js → applicationAnalyticsApi-BgG3SGJm.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js.map → applicationAnalyticsApi-BgG3SGJm.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js → applicationAnalyticsApi-ktD65iLO.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js.map → applicationAnalyticsApi-ktD65iLO.js.map} +1 -1
- package/dist/chunks/{groupsApi-DExOJZPF.js → groupsApi-C-FLWPCO.js} +2 -2
- package/dist/chunks/{groupsApi-DExOJZPF.js.map → groupsApi-C-FLWPCO.js.map} +1 -1
- package/dist/chunks/{groupsApi-CyqyYsmi.js → groupsApi-CBI5vMLa.js} +2 -2
- package/dist/chunks/{groupsApi-CyqyYsmi.js.map → groupsApi-CBI5vMLa.js.map} +1 -1
- package/dist/chunks/{index-DtAReZI6.js → index-B727-QSU.js} +2 -2
- package/dist/chunks/{index-DtAReZI6.js.map → index-B727-QSU.js.map} +1 -1
- package/dist/chunks/{index-BlOgmQzc.js → index-B9q3vx13.js} +2 -2
- package/dist/chunks/{index-BlOgmQzc.js.map → index-B9q3vx13.js.map} +1 -1
- package/dist/chunks/{index-VSQ2prtJ.js → index-BD-REzV9.js} +2 -2
- package/dist/chunks/{index-VSQ2prtJ.js.map → index-BD-REzV9.js.map} +1 -1
- package/dist/chunks/{index-XOOiD_zY.js → index-BDRogQH_.js} +3 -3
- package/dist/chunks/{index-XOOiD_zY.js.map → index-BDRogQH_.js.map} +1 -1
- package/dist/chunks/{index-DOQyf5yZ.js → index-C-DYxdvd.js} +8 -8
- package/dist/chunks/{index-DOQyf5yZ.js.map → index-C-DYxdvd.js.map} +1 -1
- package/dist/chunks/{index-Cq80YBne.js → index-CBtjGPod.js} +105 -105
- package/dist/chunks/{index-Cq80YBne.js.map → index-CBtjGPod.js.map} +1 -1
- package/dist/chunks/{index-dlXYTPWH.js → index-CF1cvNUL.js} +4 -4
- package/dist/chunks/{index-dlXYTPWH.js.map → index-CF1cvNUL.js.map} +1 -1
- package/dist/chunks/{index-COA_xJVJ.js → index-CH0pTHy1.js} +2 -2
- package/dist/chunks/{index-COA_xJVJ.js.map → index-CH0pTHy1.js.map} +1 -1
- package/dist/chunks/{index-DjZQ6ZG_.js → index-Ca88RIuT.js} +2 -2
- package/dist/chunks/{index-DjZQ6ZG_.js.map → index-Ca88RIuT.js.map} +1 -1
- package/dist/chunks/{index-Cj-9tGpd.js → index-CkWvsvKW.js} +2 -2
- package/dist/chunks/{index-Cj-9tGpd.js.map → index-CkWvsvKW.js.map} +1 -1
- package/dist/chunks/{index-EL_ZNnMH.js → index-CzYKE5fL.js} +2 -2
- package/dist/chunks/{index-EL_ZNnMH.js.map → index-CzYKE5fL.js.map} +1 -1
- package/dist/chunks/{index-qXfYaEmV.js → index-D32ol7lq.js} +2 -2
- package/dist/chunks/{index-qXfYaEmV.js.map → index-D32ol7lq.js.map} +1 -1
- package/dist/chunks/{index-DMQQ0KyA.js → index-D7hmx9IX.js} +2 -2
- package/dist/chunks/{index-DMQQ0KyA.js.map → index-D7hmx9IX.js.map} +1 -1
- package/dist/chunks/{index-BetDcNZm.js → index-DThcQmwZ.js} +2 -2
- package/dist/chunks/{index-BetDcNZm.js.map → index-DThcQmwZ.js.map} +1 -1
- package/dist/chunks/{index-C7h5yvcP.js → index-D_3J6ziZ.js} +2 -2
- package/dist/chunks/{index-C7h5yvcP.js.map → index-D_3J6ziZ.js.map} +1 -1
- package/dist/chunks/{index-C_nDTEP5.js → index-JSjfMShT.js} +2 -2
- package/dist/chunks/{index-C_nDTEP5.js.map → index-JSjfMShT.js.map} +1 -1
- package/dist/chunks/{index-COXxU0FH.js → index-gzXJw_ow.js} +3 -3
- package/dist/chunks/{index-COXxU0FH.js.map → index-gzXJw_ow.js.map} +1 -1
- package/dist/chunks/{index-jJxtz2bs.js → index-rRAbl04H.js} +2 -2
- package/dist/chunks/{index-jJxtz2bs.js.map → index-rRAbl04H.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js → tenantIconMap-Cw-hQ9n4.js} +2 -2
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js.map → tenantIconMap-Cw-hQ9n4.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js → tenantIconMap-DinwojNW.js} +2 -2
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js.map → tenantIconMap-DinwojNW.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js → ticketingApi-CcWdebXv.js} +2 -2
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js.map → ticketingApi-CcWdebXv.js.map} +1 -1
- package/dist/chunks/{ticketingApi-D6s75rOB.js → ticketingApi-x0BwZ1NH.js} +2 -2
- package/dist/chunks/{ticketingApi-D6s75rOB.js.map → ticketingApi-x0BwZ1NH.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js → useAccessRequests-BBTIYht3.js} +2 -2
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js.map → useAccessRequests-BBTIYht3.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CanI2ypo.js → useAccessRequests-BBUj9XY9.js} +71 -71
- package/dist/chunks/{useAccessRequests-CanI2ypo.js.map → useAccessRequests-BBUj9XY9.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js → useUserAccessRequests-BKQxcOXH.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js.map → useUserAccessRequests-BKQxcOXH.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js → useUserAccessRequests-BPUPiP55.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js.map → useUserAccessRequests-BPUPiP55.js.map} +1 -1
- package/dist/pages/platform/administration/applications/ApplicationDetailPage.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/ApplicationDetailPage-CWdz0TS4.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersGroupsPage-DS2YiUE4.js","sources":["../../src/pages/platform/administration/users/UsersGroupsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link, useNavigate } from 'react-router-dom';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport {\r\n Building2,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n Search,\r\n Users,\r\n Shield,\r\n Plus,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n LayoutGrid,\r\n List,\r\n Filter,\r\n Cloud,\r\n CloudOff,\r\n Trash2,\r\n Check,\r\n GitBranch,\r\n CornerDownRight,\r\n} from 'lucide-react';\r\nimport {\r\n groupsApi,\r\n type GroupListDto,\r\n type GroupMemberDto,\r\n type GroupRoleDto,\r\n} from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\n\r\ntype ViewMode = 'cards' | 'table';\r\ntype GroupTypeFilter = 'all' | 'security' | 'distribution';\r\ntype SyncFilter = 'all' | 'local' | 'synced';\r\n\r\ninterface GroupWithDetails extends GroupListDto {\r\n membersLoaded?: GroupMemberDto[];\r\n rolesLoaded?: GroupRoleDto[];\r\n}\r\n\r\nconst getViewModeButtonClass = (isActive: boolean): string => {\r\n if (isActive) {\r\n return 'bg-[var(--color-accent-500)] text-white';\r\n }\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]';\r\n};\r\n\r\n/** Build a hierarchical list: root groups first, then their children indented, recursively */\r\nfunction buildHierarchicalList<T extends { id: string; parentGroupId: string | null }>(\r\n items: T[]\r\n): { item: T; depth: number }[] {\r\n const childrenMap = new Map<string | null, T[]>();\r\n for (const item of items) {\r\n const parentId = item.parentGroupId;\r\n if (!childrenMap.has(parentId)) childrenMap.set(parentId, []);\r\n childrenMap.get(parentId)!.push(item);\r\n }\r\n\r\n const result: { item: T; depth: number }[] = [];\r\n const addChildren = (parentId: string | null, depth: number) => {\r\n const children = childrenMap.get(parentId) || [];\r\n for (const child of children) {\r\n result.push({ item: child, depth });\r\n addChildren(child.id, depth + 1);\r\n }\r\n };\r\n\r\n // Start with root groups (parentGroupId is null or parent not in current filtered list)\r\n const itemIds = new Set(items.map(i => i.id));\r\n const roots = items.filter(i => !i.parentGroupId || !itemIds.has(i.parentGroupId));\r\n for (const root of roots) {\r\n result.push({ item: root, depth: 0 });\r\n addChildren(root.id, 1);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function UsersGroupsPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'common']);\r\n const navigate = useNavigate();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const [loading, setLoading] = useState(true);\r\n const [groups, setGroups] = useState<GroupWithDetails[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [selectedGroup, setSelectedGroup] = useState<GroupWithDetails | null>(null);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [showCreateModal, setShowCreateModal] = useState(false);\r\n const [expandedGroupId, setExpandedGroupId] = useState<string | null>(null);\r\n const [members, setMembers] = useState<Record<string, GroupMemberDto[]>>({});\r\n const [loadingMembers, setLoadingMembers] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [groupTypeFilter, setGroupTypeFilter] = useState<GroupTypeFilter>('all');\r\n const [syncFilter, setSyncFilter] = useState<SyncFilter>('all');\r\n\r\n // Create group form state\r\n const [newGroupName, setNewGroupName] = useState('');\r\n const [newGroupDescription, setNewGroupDescription] = useState('');\r\n const [newGroupIsSecurityGroup, setNewGroupIsSecurityGroup] = useState(true);\r\n const [newGroupParentId, setNewGroupParentId] = useState<string>('');\r\n const [creating, setCreating] = useState(false);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n setGroups(Array.isArray(groupsData) ? groupsData : []);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load groups:', err);\r\n setGroups([]);\r\n setRoles([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('admin:groups.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n // TENANT ISOLATION: Re-fetch when tenant changes\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData, currentTenant?.id, isGlobalView]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await groupsApi.getMembers(groupId);\r\n setMembers(prev => ({ ...prev, [groupId]: data }));\r\n setExpandedGroupId(groupId);\r\n } catch (err) {\r\n console.error('Failed to load members:', err);\r\n setError(t('admin:groups.loadError'));\r\n } finally {\r\n setLoadingMembers(null);\r\n }\r\n };\r\n\r\n const reloadGroupsAndRoles = useCallback(async () => {\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n const safeGroupsData = Array.isArray(groupsData) ? groupsData : [];\r\n setGroups(safeGroupsData);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n return safeGroupsData;\r\n }, []);\r\n\r\n const handleCreateGroup = async () => {\r\n if (!newGroupName.trim()) return;\r\n\r\n setCreating(true);\r\n try {\r\n await groupsApi.create({\r\n name: newGroupName.trim(),\r\n description: newGroupDescription.trim() || undefined,\r\n isSecurityGroup: newGroupIsSecurityGroup,\r\n parentGroupId: newGroupParentId || undefined,\r\n });\r\n await loadData();\r\n setShowCreateModal(false);\r\n setNewGroupName('');\r\n setNewGroupDescription('');\r\n setNewGroupIsSecurityGroup(true);\r\n setNewGroupParentId('');\r\n } catch (err) {\r\n console.error('Failed to create group:', err);\r\n const axiosError = err as { response?: { status?: number; data?: { message?: string } } };\r\n if (axiosError.response?.status === 409) {\r\n setError(axiosError.response.data?.message || t('admin:groups.createError'));\r\n } else {\r\n setError(t('admin:groups.createError'));\r\n }\r\n } finally {\r\n setCreating(false);\r\n }\r\n };\r\n\r\n const handleDeleteGroup = async (groupId: string, groupName: string, isSyncedFromEntra: boolean = false) => {\r\n const confirmMessage = isSyncedFromEntra\r\n ? t('admin:groups.deleteConfirmEntra', { name: groupName, defaultValue: `Le groupe \"${groupName}\" est synchronisé depuis Entra ID. Il sera recréé lors de la prochaine synchronisation.\\n\\nÊtes-vous sûr de vouloir le supprimer ?` })\r\n : t('admin:groups.deleteConfirm', { name: groupName });\r\n\r\n if (!confirm(confirmMessage)) return;\r\n\r\n try {\r\n await groupsApi.delete(groupId);\r\n await loadData();\r\n } catch (err) {\r\n console.error('Failed to delete group:', err);\r\n setError(t('admin:groups.deleteError'));\r\n }\r\n };\r\n\r\n const handleAssignRole = async (roleId: string) => {\r\n if (!selectedGroup) return;\r\n try {\r\n await groupsApi.assignRole(selectedGroup.id, { roleId });\r\n const safeGroupsData = await reloadGroupsAndRoles();\r\n const updatedGroup = safeGroupsData.find(g => g.id === selectedGroup.id);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('admin:groups.assignError'));\r\n }\r\n };\r\n\r\n const filteredGroups = groups.filter((g) => {\r\n const matchesSearch =\r\n g.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\r\n g.description?.toLowerCase().includes(searchQuery.toLowerCase());\r\n\r\n const matchesType =\r\n groupTypeFilter === 'all' ||\r\n (groupTypeFilter === 'security' && g.isSecurityGroup) ||\r\n (groupTypeFilter === 'distribution' && !g.isSecurityGroup);\r\n\r\n const matchesSync =\r\n syncFilter === 'all' ||\r\n (syncFilter === 'local' && !g.isSyncedFromEntra) ||\r\n (syncFilter === 'synced' && g.isSyncedFromEntra);\r\n\r\n return matchesSearch && matchesType && matchesSync;\r\n });\r\n\r\n const hierarchicalGroups = buildHierarchicalList(filteredGroups);\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return '-';\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('admin:header.title'), href: '/administration' },\r\n { label: t('admin:users.title', 'Users'), href: '/administration/users' },\r\n { label: t('admin:groups.title', 'Groups') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <Users className=\"w-6 h-6 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('admin:groups.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('admin:groups.subtitle', { count: groups.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n <button\r\n onClick={() => setShowCreateModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.createGroup')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"ml-auto p-1 hover:bg-[var(--error-text)]/10 rounded\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filters */}\r\n <div className=\"flex flex-col sm:flex-row gap-4\">\r\n {/* Search */}\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('admin:groups.searchPlaceholder')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Type Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={groupTypeFilter}\r\n onChange={(e) => setGroupTypeFilter(e.target.value as GroupTypeFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allTypes')}</option>\r\n <option value=\"security\">{t('admin:groups.securityGroup')}</option>\r\n <option value=\"distribution\">{t('admin:groups.distributionGroup')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Sync Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Cloud className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={syncFilter}\r\n onChange={(e) => setSyncFilter(e.target.value as SyncFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allSyncStatus')}</option>\r\n <option value=\"local\">{t('admin:groups.localOnly')}</option>\r\n <option value=\"synced\">{t('admin:groups.syncedFromEntra')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setViewMode('cards')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'cards')}`}\r\n title={t('admin:groups.cardView')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'table')}`}\r\n title={t('admin:groups.tableView')}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Groups List */}\r\n {filteredGroups.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {searchQuery || groupTypeFilter !== 'all' || syncFilter !== 'all'\r\n ? t('admin:groups.noResults')\r\n : t('admin:groups.noGroups')}\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-secondary)]\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.groupName')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.parentGroup')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:type')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.source')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.members')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.assignedRoles')}\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:actionsColumn')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {hierarchicalGroups.map(({ item: group, depth }) => (\r\n <tr key={group.id} className=\"hover:bg-[var(--bg-hover)] cursor-pointer\" onClick={() => navigate(`/administration/users/groups/${group.id}`)}>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\" style={{ paddingLeft: `${depth * 24}px` }}>\r\n {depth > 0 && (\r\n <CornerDownRight className=\"w-4 h-4 text-[var(--text-tertiary)] flex-shrink-0\" />\r\n )}\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-4 h-4\" />\r\n ) : (\r\n <Building2 className=\"w-4 h-4\" />\r\n )}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] hover:text-[var(--color-accent-500)] hover:underline\">{group.name}</span>\r\n {group.childCount > 0 && (\r\n <span className=\"flex items-center gap-0.5 px-1.5 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.childCount}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate max-w-xs\">\r\n {group.description}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {group.parentGroupName ? (\r\n <span className=\"text-[var(--text-secondary)]\">{group.parentGroupName}</span>\r\n ) : (\r\n <span className=\"text-[var(--text-tertiary)]\">-</span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"flex items-center gap-1 text-sm text-blue-500\">\r\n <Cloud className=\"w-4 h-4\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"flex items-center gap-1 text-sm text-[var(--text-tertiary)]\">\r\n <CloudOff className=\"w-4 h-4\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n <span className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n {group.memberCount}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {group.roles.slice(0, 2).map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\"\r\n >\r\n {role}\r\n </span>\r\n ))}\r\n {group.roles.length > 2 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n +{group.roles.length - 2}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-right\" onClick={(e) => e.stopPropagation()}>\r\n <div className=\"flex items-center justify-end gap-2\">\r\n <button\r\n onClick={() => {\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n title={t('admin:groups.assignRole')}\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra)}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n title={t('common:delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode !== 'table' && (\r\n /* Cards View */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {hierarchicalGroups.map(({ item: group }) => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={group.id}\r\n className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)] overflow-hidden hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left flex flex-col\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/users/groups/${group.id}`); } }}\r\n >\r\n {/* Card Header */}\r\n <div className=\"p-4 flex-1\">\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2.5 rounded-[var(--radius-button)] flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-5 h-5\" />\r\n ) : (\r\n <Building2 className=\"w-5 h-5\" />\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <span className=\"font-semibold text-[var(--text-primary)] truncate\">\r\n {group.name}\r\n </span>\r\n {group.isSecurityGroup && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20\">\r\n {t('admin:groups.securityGroup')}\r\n </span>\r\n )}\r\n {!group.isActive && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n {t('common:inactive')}\r\n </span>\r\n )}\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20 flex items-center gap-1\">\r\n <Cloud className=\"w-3 h-3\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CloudOff className=\"w-3 h-3\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n {group.parentGroupName && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CornerDownRight className=\"w-3 h-3\" />\r\n {group.parentGroupName}\r\n </span>\r\n )}\r\n {group.childCount > 0 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('admin:groups.childGroupCount', { count: group.childCount })}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1 line-clamp-2\">\r\n {group.description}\r\n </p>\r\n )}\r\n <div className=\"flex items-center gap-4 mt-2 text-sm text-[var(--text-tertiary)] flex-wrap\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); loadMembers(group.id); }}\r\n className=\"flex items-center gap-1 hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.memberCount', { count: group.memberCount })}\r\n {loadingMembers === group.id && (\r\n <Loader2 className=\"w-3 h-3 animate-spin ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId === group.id && (\r\n <ChevronUp className=\"w-3 h-3 ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId !== group.id && (\r\n <ChevronDown className=\"w-3 h-3 ml-1\" />\r\n )}\r\n </button>\r\n </div>\r\n {group.isSyncedFromEntra && group.lastEntraSyncAt && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.lastSynced', { date: formatDate(group.lastEntraSyncAt) })}\r\n </p>\r\n )}\r\n {!group.isSyncedFromEntra && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.createdAt', { date: formatDate(group.createdAt) })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"flex flex-col gap-2 flex-shrink-0\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); setSelectedGroup(group); setShowAssignModal(true); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.assignRole')}\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--error-border)] text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n {t('common:delete')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Assigned Roles */}\r\n {group.roles.length > 0 && (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {t('admin:groups.assignedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {group.roles.map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-badge)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Shield className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n <span className=\"text-sm text-[var(--text-primary)]\">{role}</span>\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Members Panel */}\r\n {expandedGroupId === group.id && members[group.id] && (\r\n <div className=\"border-t border-[var(--border-color)] bg-[var(--bg-primary)]\">\r\n <div className=\"p-4\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center gap-2\">\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.members')} ({members[group.id].length})\r\n </h4>\r\n {members[group.id].length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.noMembers')}\r\n </p>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-64 overflow-y-auto\">\r\n {members[group.id].slice(0, 10).map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0).toUpperCase()}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">\r\n {member.email}\r\n </p>\r\n </div>\r\n </Link>\r\n ))}\r\n </div>\r\n )}\r\n {members[group.id].length > 10 && (\r\n <p className=\"mt-3 text-center text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.showingMembers', {\r\n shown: 10,\r\n total: members[group.id].length,\r\n })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Create Group Modal */}\r\n {showCreateModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.createGroup')}\r\n </h2>\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4 space-y-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.groupName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newGroupName}\r\n onChange={(e) => setNewGroupName(e.target.value)}\r\n placeholder={t('admin:groups.groupNamePlaceholder')}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('common:description')}\r\n </label>\r\n <textarea\r\n value={newGroupDescription}\r\n onChange={(e) => setNewGroupDescription(e.target.value)}\r\n placeholder={t('admin:groups.descriptionPlaceholder')}\r\n rows={3}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setNewGroupIsSecurityGroup(!newGroupIsSecurityGroup)}\r\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\r\n newGroupIsSecurityGroup\r\n ? 'bg-[var(--color-accent-500)]'\r\n : 'bg-[var(--bg-tertiary)]'\r\n }`}\r\n >\r\n <span\r\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\r\n newGroupIsSecurityGroup ? 'translate-x-6' : 'translate-x-1'\r\n }`}\r\n />\r\n </button>\r\n <span className=\"text-sm text-[var(--text-primary)]\">\r\n {t('admin:groups.isSecurityGroup')}\r\n </span>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.parentGroup')}\r\n </label>\r\n <select\r\n value={newGroupParentId}\r\n onChange={(e) => setNewGroupParentId(e.target.value)}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"\">{t('admin:groups.noParent')}</option>\r\n {groups.filter(g => g.isActive).map(g => (\r\n <option key={g.id} value={g.id}>{g.name}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-end gap-3 p-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common:cancel')}\r\n </button>\r\n <button\r\n onClick={handleCreateGroup}\r\n disabled={!newGroupName.trim() || creating}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {creating ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Check className=\"w-4 h-4\" />\r\n )}\r\n {t('common:create')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {showAssignModal && selectedGroup && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.assignRoleTitle')}\r\n </h2>\r\n <button\r\n onClick={() => {\r\n setShowAssignModal(false);\r\n setSelectedGroup(null);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4\">\r\n <p className=\"text-sm text-[var(--text-secondary)] mb-4\">\r\n {t('admin:groups.assignRoleDescription', { group: selectedGroup.name })}\r\n </p>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {roles\r\n .filter((role) => !selectedGroup.roles.includes(role.name))\r\n .map((role) => (\r\n <button\r\n key={role.id}\r\n onClick={() => handleAssignRole(role.id)}\r\n className=\"w-full flex items-center gap-3 p-3 rounded-[var(--radius-button)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n <div>\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n </button>\r\n ))}\r\n {roles.filter((role) => !selectedGroup.roles.includes(role.name)).length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('admin:groups.allRolesAssigned')}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["getViewModeButtonClass","isActive","buildHierarchicalList","items","childrenMap","item","parentId","result","addChildren","depth","children","child","itemIds","roots","root","UsersGroupsPage","useTranslation","navigate","useNavigate","currentTenant","isGlobalView","useTenant","loading","setLoading","useState","groups","setGroups","roles","setRoles","error","setError","searchQuery","setSearchQuery","selectedGroup","setSelectedGroup","showAssignModal","setShowAssignModal","showCreateModal","setShowCreateModal","expandedGroupId","setExpandedGroupId","members","setMembers","loadingMembers","setLoadingMembers","viewMode","setViewMode","groupTypeFilter","setGroupTypeFilter","syncFilter","setSyncFilter","newGroupName","setNewGroupName","newGroupDescription","setNewGroupDescription","newGroupIsSecurityGroup","setNewGroupIsSecurityGroup","newGroupParentId","setNewGroupParentId","creating","setCreating","loadData","useCallback","groupsData","rolesData","groupsApi","adminApi","err","axiosError","useEffect","loadMembers","groupId","data","prev","reloadGroupsAndRoles","safeGroupsData","handleCreateGroup","handleDeleteGroup","groupName","isSyncedFromEntra","confirmMessage","handleAssignRole","roleId","updatedGroup","g","filteredGroups","matchesSearch","matchesType","matchesSync","hierarchicalGroups","formatDate","date","jsx","Loader2","jsxs","Breadcrumb","Users","RefreshCw","Plus","AlertTriangle","X","Search","e","Filter","Cloud","LayoutGrid","List","group","CornerDownRight","Shield","Building2","GitBranch","CloudOff","role","index","Trash2","ChevronUp","ChevronDown","member","Link","Check"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UsersGroupsPage-c28vYHN9.js","sources":["../../src/pages/platform/administration/users/UsersGroupsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link, useNavigate } from 'react-router-dom';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport {\r\n Building2,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n Search,\r\n Users,\r\n Shield,\r\n Plus,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n LayoutGrid,\r\n List,\r\n Filter,\r\n Cloud,\r\n CloudOff,\r\n Trash2,\r\n Check,\r\n GitBranch,\r\n CornerDownRight,\r\n} from 'lucide-react';\r\nimport {\r\n groupsApi,\r\n type GroupListDto,\r\n type GroupMemberDto,\r\n type GroupRoleDto,\r\n} from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\n\r\ntype ViewMode = 'cards' | 'table';\r\ntype GroupTypeFilter = 'all' | 'security' | 'distribution';\r\ntype SyncFilter = 'all' | 'local' | 'synced';\r\n\r\ninterface GroupWithDetails extends GroupListDto {\r\n membersLoaded?: GroupMemberDto[];\r\n rolesLoaded?: GroupRoleDto[];\r\n}\r\n\r\nconst getViewModeButtonClass = (isActive: boolean): string => {\r\n if (isActive) {\r\n return 'bg-[var(--color-accent-500)] text-white';\r\n }\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]';\r\n};\r\n\r\n/** Build a hierarchical list: root groups first, then their children indented, recursively */\r\nfunction buildHierarchicalList<T extends { id: string; parentGroupId: string | null }>(\r\n items: T[]\r\n): { item: T; depth: number }[] {\r\n const childrenMap = new Map<string | null, T[]>();\r\n for (const item of items) {\r\n const parentId = item.parentGroupId;\r\n if (!childrenMap.has(parentId)) childrenMap.set(parentId, []);\r\n childrenMap.get(parentId)!.push(item);\r\n }\r\n\r\n const result: { item: T; depth: number }[] = [];\r\n const addChildren = (parentId: string | null, depth: number) => {\r\n const children = childrenMap.get(parentId) || [];\r\n for (const child of children) {\r\n result.push({ item: child, depth });\r\n addChildren(child.id, depth + 1);\r\n }\r\n };\r\n\r\n // Start with root groups (parentGroupId is null or parent not in current filtered list)\r\n const itemIds = new Set(items.map(i => i.id));\r\n const roots = items.filter(i => !i.parentGroupId || !itemIds.has(i.parentGroupId));\r\n for (const root of roots) {\r\n result.push({ item: root, depth: 0 });\r\n addChildren(root.id, 1);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function UsersGroupsPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'common']);\r\n const navigate = useNavigate();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const [loading, setLoading] = useState(true);\r\n const [groups, setGroups] = useState<GroupWithDetails[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [selectedGroup, setSelectedGroup] = useState<GroupWithDetails | null>(null);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [showCreateModal, setShowCreateModal] = useState(false);\r\n const [expandedGroupId, setExpandedGroupId] = useState<string | null>(null);\r\n const [members, setMembers] = useState<Record<string, GroupMemberDto[]>>({});\r\n const [loadingMembers, setLoadingMembers] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [groupTypeFilter, setGroupTypeFilter] = useState<GroupTypeFilter>('all');\r\n const [syncFilter, setSyncFilter] = useState<SyncFilter>('all');\r\n\r\n // Create group form state\r\n const [newGroupName, setNewGroupName] = useState('');\r\n const [newGroupDescription, setNewGroupDescription] = useState('');\r\n const [newGroupIsSecurityGroup, setNewGroupIsSecurityGroup] = useState(true);\r\n const [newGroupParentId, setNewGroupParentId] = useState<string>('');\r\n const [creating, setCreating] = useState(false);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n setGroups(Array.isArray(groupsData) ? groupsData : []);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load groups:', err);\r\n setGroups([]);\r\n setRoles([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('admin:groups.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [t]);\r\n\r\n // TENANT ISOLATION: Re-fetch when tenant changes\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData, currentTenant?.id, isGlobalView]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await groupsApi.getMembers(groupId);\r\n setMembers(prev => ({ ...prev, [groupId]: data }));\r\n setExpandedGroupId(groupId);\r\n } catch (err) {\r\n console.error('Failed to load members:', err);\r\n setError(t('admin:groups.loadError'));\r\n } finally {\r\n setLoadingMembers(null);\r\n }\r\n };\r\n\r\n const reloadGroupsAndRoles = useCallback(async () => {\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n const safeGroupsData = Array.isArray(groupsData) ? groupsData : [];\r\n setGroups(safeGroupsData);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n return safeGroupsData;\r\n }, []);\r\n\r\n const handleCreateGroup = async () => {\r\n if (!newGroupName.trim()) return;\r\n\r\n setCreating(true);\r\n try {\r\n await groupsApi.create({\r\n name: newGroupName.trim(),\r\n description: newGroupDescription.trim() || undefined,\r\n isSecurityGroup: newGroupIsSecurityGroup,\r\n parentGroupId: newGroupParentId || undefined,\r\n });\r\n await loadData();\r\n setShowCreateModal(false);\r\n setNewGroupName('');\r\n setNewGroupDescription('');\r\n setNewGroupIsSecurityGroup(true);\r\n setNewGroupParentId('');\r\n } catch (err) {\r\n console.error('Failed to create group:', err);\r\n const axiosError = err as { response?: { status?: number; data?: { message?: string } } };\r\n if (axiosError.response?.status === 409) {\r\n setError(axiosError.response.data?.message || t('admin:groups.createError'));\r\n } else {\r\n setError(t('admin:groups.createError'));\r\n }\r\n } finally {\r\n setCreating(false);\r\n }\r\n };\r\n\r\n const handleDeleteGroup = async (groupId: string, groupName: string, isSyncedFromEntra: boolean = false) => {\r\n const confirmMessage = isSyncedFromEntra\r\n ? t('admin:groups.deleteConfirmEntra', { name: groupName, defaultValue: `Le groupe \"${groupName}\" est synchronisé depuis Entra ID. Il sera recréé lors de la prochaine synchronisation.\\n\\nÊtes-vous sûr de vouloir le supprimer ?` })\r\n : t('admin:groups.deleteConfirm', { name: groupName });\r\n\r\n if (!confirm(confirmMessage)) return;\r\n\r\n try {\r\n await groupsApi.delete(groupId);\r\n await loadData();\r\n } catch (err) {\r\n console.error('Failed to delete group:', err);\r\n setError(t('admin:groups.deleteError'));\r\n }\r\n };\r\n\r\n const handleAssignRole = async (roleId: string) => {\r\n if (!selectedGroup) return;\r\n try {\r\n await groupsApi.assignRole(selectedGroup.id, { roleId });\r\n const safeGroupsData = await reloadGroupsAndRoles();\r\n const updatedGroup = safeGroupsData.find(g => g.id === selectedGroup.id);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('admin:groups.assignError'));\r\n }\r\n };\r\n\r\n const filteredGroups = groups.filter((g) => {\r\n const matchesSearch =\r\n g.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\r\n g.description?.toLowerCase().includes(searchQuery.toLowerCase());\r\n\r\n const matchesType =\r\n groupTypeFilter === 'all' ||\r\n (groupTypeFilter === 'security' && g.isSecurityGroup) ||\r\n (groupTypeFilter === 'distribution' && !g.isSecurityGroup);\r\n\r\n const matchesSync =\r\n syncFilter === 'all' ||\r\n (syncFilter === 'local' && !g.isSyncedFromEntra) ||\r\n (syncFilter === 'synced' && g.isSyncedFromEntra);\r\n\r\n return matchesSearch && matchesType && matchesSync;\r\n });\r\n\r\n const hierarchicalGroups = buildHierarchicalList(filteredGroups);\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return '-';\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('admin:header.title'), href: '/administration' },\r\n { label: t('admin:users.title', 'Users'), href: '/administration/users' },\r\n { label: t('admin:groups.title', 'Groups') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <Users className=\"w-6 h-6 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('admin:groups.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('admin:groups.subtitle', { count: groups.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n <button\r\n onClick={() => setShowCreateModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.createGroup')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"ml-auto p-1 hover:bg-[var(--error-text)]/10 rounded\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filters */}\r\n <div className=\"flex flex-col sm:flex-row gap-4\">\r\n {/* Search */}\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('admin:groups.searchPlaceholder')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Type Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={groupTypeFilter}\r\n onChange={(e) => setGroupTypeFilter(e.target.value as GroupTypeFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allTypes')}</option>\r\n <option value=\"security\">{t('admin:groups.securityGroup')}</option>\r\n <option value=\"distribution\">{t('admin:groups.distributionGroup')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Sync Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Cloud className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={syncFilter}\r\n onChange={(e) => setSyncFilter(e.target.value as SyncFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allSyncStatus')}</option>\r\n <option value=\"local\">{t('admin:groups.localOnly')}</option>\r\n <option value=\"synced\">{t('admin:groups.syncedFromEntra')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setViewMode('cards')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'cards')}`}\r\n title={t('admin:groups.cardView')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'table')}`}\r\n title={t('admin:groups.tableView')}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Groups List */}\r\n {filteredGroups.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {searchQuery || groupTypeFilter !== 'all' || syncFilter !== 'all'\r\n ? t('admin:groups.noResults')\r\n : t('admin:groups.noGroups')}\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-secondary)]\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.groupName')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.parentGroup')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:type')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.source')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.members')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.assignedRoles')}\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:actionsColumn')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {hierarchicalGroups.map(({ item: group, depth }) => (\r\n <tr key={group.id} className=\"hover:bg-[var(--bg-hover)] cursor-pointer\" onClick={() => navigate(`/administration/users/groups/${group.id}`)}>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\" style={{ paddingLeft: `${depth * 24}px` }}>\r\n {depth > 0 && (\r\n <CornerDownRight className=\"w-4 h-4 text-[var(--text-tertiary)] flex-shrink-0\" />\r\n )}\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-4 h-4\" />\r\n ) : (\r\n <Building2 className=\"w-4 h-4\" />\r\n )}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] hover:text-[var(--color-accent-500)] hover:underline\">{group.name}</span>\r\n {group.childCount > 0 && (\r\n <span className=\"flex items-center gap-0.5 px-1.5 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.childCount}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate max-w-xs\">\r\n {group.description}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {group.parentGroupName ? (\r\n <span className=\"text-[var(--text-secondary)]\">{group.parentGroupName}</span>\r\n ) : (\r\n <span className=\"text-[var(--text-tertiary)]\">-</span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"flex items-center gap-1 text-sm text-blue-500\">\r\n <Cloud className=\"w-4 h-4\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"flex items-center gap-1 text-sm text-[var(--text-tertiary)]\">\r\n <CloudOff className=\"w-4 h-4\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n <span className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n {group.memberCount}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {group.roles.slice(0, 2).map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\"\r\n >\r\n {role}\r\n </span>\r\n ))}\r\n {group.roles.length > 2 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n +{group.roles.length - 2}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-right\" onClick={(e) => e.stopPropagation()}>\r\n <div className=\"flex items-center justify-end gap-2\">\r\n <button\r\n onClick={() => {\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n title={t('admin:groups.assignRole')}\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra)}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n title={t('common:delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode !== 'table' && (\r\n /* Cards View */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {hierarchicalGroups.map(({ item: group }) => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={group.id}\r\n className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)] overflow-hidden hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left flex flex-col\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/users/groups/${group.id}`); } }}\r\n >\r\n {/* Card Header */}\r\n <div className=\"p-4 flex-1\">\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2.5 rounded-[var(--radius-button)] flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-5 h-5\" />\r\n ) : (\r\n <Building2 className=\"w-5 h-5\" />\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <span className=\"font-semibold text-[var(--text-primary)] truncate\">\r\n {group.name}\r\n </span>\r\n {group.isSecurityGroup && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20\">\r\n {t('admin:groups.securityGroup')}\r\n </span>\r\n )}\r\n {!group.isActive && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n {t('common:inactive')}\r\n </span>\r\n )}\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20 flex items-center gap-1\">\r\n <Cloud className=\"w-3 h-3\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CloudOff className=\"w-3 h-3\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n {group.parentGroupName && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CornerDownRight className=\"w-3 h-3\" />\r\n {group.parentGroupName}\r\n </span>\r\n )}\r\n {group.childCount > 0 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('admin:groups.childGroupCount', { count: group.childCount })}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1 line-clamp-2\">\r\n {group.description}\r\n </p>\r\n )}\r\n <div className=\"flex items-center gap-4 mt-2 text-sm text-[var(--text-tertiary)] flex-wrap\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); loadMembers(group.id); }}\r\n className=\"flex items-center gap-1 hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.memberCount', { count: group.memberCount })}\r\n {loadingMembers === group.id && (\r\n <Loader2 className=\"w-3 h-3 animate-spin ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId === group.id && (\r\n <ChevronUp className=\"w-3 h-3 ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId !== group.id && (\r\n <ChevronDown className=\"w-3 h-3 ml-1\" />\r\n )}\r\n </button>\r\n </div>\r\n {group.isSyncedFromEntra && group.lastEntraSyncAt && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.lastSynced', { date: formatDate(group.lastEntraSyncAt) })}\r\n </p>\r\n )}\r\n {!group.isSyncedFromEntra && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.createdAt', { date: formatDate(group.createdAt) })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"flex flex-col gap-2 flex-shrink-0\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); setSelectedGroup(group); setShowAssignModal(true); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.assignRole')}\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--error-border)] text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n {t('common:delete')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Assigned Roles */}\r\n {group.roles.length > 0 && (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {t('admin:groups.assignedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {group.roles.map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-badge)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Shield className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n <span className=\"text-sm text-[var(--text-primary)]\">{role}</span>\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Members Panel */}\r\n {expandedGroupId === group.id && members[group.id] && (\r\n <div className=\"border-t border-[var(--border-color)] bg-[var(--bg-primary)]\">\r\n <div className=\"p-4\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center gap-2\">\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.members')} ({members[group.id].length})\r\n </h4>\r\n {members[group.id].length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.noMembers')}\r\n </p>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-64 overflow-y-auto\">\r\n {members[group.id].slice(0, 10).map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0).toUpperCase()}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">\r\n {member.email}\r\n </p>\r\n </div>\r\n </Link>\r\n ))}\r\n </div>\r\n )}\r\n {members[group.id].length > 10 && (\r\n <p className=\"mt-3 text-center text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.showingMembers', {\r\n shown: 10,\r\n total: members[group.id].length,\r\n })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Create Group Modal */}\r\n {showCreateModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.createGroup')}\r\n </h2>\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4 space-y-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.groupName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newGroupName}\r\n onChange={(e) => setNewGroupName(e.target.value)}\r\n placeholder={t('admin:groups.groupNamePlaceholder')}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('common:description')}\r\n </label>\r\n <textarea\r\n value={newGroupDescription}\r\n onChange={(e) => setNewGroupDescription(e.target.value)}\r\n placeholder={t('admin:groups.descriptionPlaceholder')}\r\n rows={3}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setNewGroupIsSecurityGroup(!newGroupIsSecurityGroup)}\r\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\r\n newGroupIsSecurityGroup\r\n ? 'bg-[var(--color-accent-500)]'\r\n : 'bg-[var(--bg-tertiary)]'\r\n }`}\r\n >\r\n <span\r\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\r\n newGroupIsSecurityGroup ? 'translate-x-6' : 'translate-x-1'\r\n }`}\r\n />\r\n </button>\r\n <span className=\"text-sm text-[var(--text-primary)]\">\r\n {t('admin:groups.isSecurityGroup')}\r\n </span>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.parentGroup')}\r\n </label>\r\n <select\r\n value={newGroupParentId}\r\n onChange={(e) => setNewGroupParentId(e.target.value)}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"\">{t('admin:groups.noParent')}</option>\r\n {groups.filter(g => g.isActive).map(g => (\r\n <option key={g.id} value={g.id}>{g.name}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-end gap-3 p-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common:cancel')}\r\n </button>\r\n <button\r\n onClick={handleCreateGroup}\r\n disabled={!newGroupName.trim() || creating}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {creating ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Check className=\"w-4 h-4\" />\r\n )}\r\n {t('common:create')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {showAssignModal && selectedGroup && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.assignRoleTitle')}\r\n </h2>\r\n <button\r\n onClick={() => {\r\n setShowAssignModal(false);\r\n setSelectedGroup(null);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4\">\r\n <p className=\"text-sm text-[var(--text-secondary)] mb-4\">\r\n {t('admin:groups.assignRoleDescription', { group: selectedGroup.name })}\r\n </p>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {roles\r\n .filter((role) => !selectedGroup.roles.includes(role.name))\r\n .map((role) => (\r\n <button\r\n key={role.id}\r\n onClick={() => handleAssignRole(role.id)}\r\n className=\"w-full flex items-center gap-3 p-3 rounded-[var(--radius-button)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n <div>\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n </button>\r\n ))}\r\n {roles.filter((role) => !selectedGroup.roles.includes(role.name)).length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('admin:groups.allRolesAssigned')}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["getViewModeButtonClass","isActive","buildHierarchicalList","items","childrenMap","item","parentId","result","addChildren","depth","children","child","itemIds","roots","root","UsersGroupsPage","useTranslation","navigate","useNavigate","currentTenant","isGlobalView","useTenant","loading","setLoading","useState","groups","setGroups","roles","setRoles","error","setError","searchQuery","setSearchQuery","selectedGroup","setSelectedGroup","showAssignModal","setShowAssignModal","showCreateModal","setShowCreateModal","expandedGroupId","setExpandedGroupId","members","setMembers","loadingMembers","setLoadingMembers","viewMode","setViewMode","groupTypeFilter","setGroupTypeFilter","syncFilter","setSyncFilter","newGroupName","setNewGroupName","newGroupDescription","setNewGroupDescription","newGroupIsSecurityGroup","setNewGroupIsSecurityGroup","newGroupParentId","setNewGroupParentId","creating","setCreating","loadData","useCallback","groupsData","rolesData","groupsApi","adminApi","err","axiosError","useEffect","loadMembers","groupId","data","prev","reloadGroupsAndRoles","safeGroupsData","handleCreateGroup","handleDeleteGroup","groupName","isSyncedFromEntra","confirmMessage","handleAssignRole","roleId","updatedGroup","g","filteredGroups","matchesSearch","matchesType","matchesSync","hierarchicalGroups","formatDate","date","jsx","Loader2","jsxs","Breadcrumb","Users","RefreshCw","Plus","AlertTriangle","X","Search","e","Filter","Cloud","LayoutGrid","List","group","CornerDownRight","Shield","Building2","GitBranch","CloudOff","role","index","Trash2","ChevronUp","ChevronDown","member","Link","Check"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react"),Z=require("react-router-dom"),_=require("react-i18next"),l=require("lucide-react"),i=require("./index-XOOiD_zY.js");function ye(){const{currentTenant:a,hasGlobalRoles:d,isGlobalView:c}=i.useTenant(),{currentModuleCode:j,getCurrentModule:y,isLoading:P,menu:B}=i.useNavigation();return d&&!c&&a&&j&&!P&&B?{isRestrictedModule:!y(),tenantName:a?.name||null}:{isRestrictedModule:!1,tenantName:null}}function Ne(){const{t:a}=_.useTranslation("admin"),{isRestrictedModule:d,tenantName:c}=ye();return d?e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 border bg-amber-500/10 border-amber-500/20 rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-amber-500/10 rounded-[var(--radius-card)]",children:e.jsx(l.AlertTriangle,{className:"w-4 h-4 text-amber-600"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("span",{className:"font-medium text-amber-700",children:a("scope.banner.restrictedModule","Module restreint")}),e.jsx("p",{className:"text-xs text-amber-600/70 mt-0.5",children:a("scope.banner.restrictedModuleDesc",`Le tenant "{{tenantName}}" n'a pas accès à ce module. Données affichées grâce à vos privilèges administrateur.`,{tenantName:c})})]})]}):null}function we(a,d){const[c,j]=o.useState(a);return o.useEffect(()=>{const y=setTimeout(()=>j(a),d);return()=>clearTimeout(y)},[a,d]),c}const Ce={search:"",status:"all",roleId:"",source:"all",userType:"",sortBy:"lastname",sortDesc:!1};function ke(){const{t:a}=_.useTranslation("admin"),d=Z.useNavigate(),[c,j]=Z.useSearchParams(),y=i.useTableColumnExtensions("users"),{currentTenant:P,isGlobalView:B}=i.useTenant(),{hasPermission:S}=i.useAuth(),A=S("administration.users.create"),x=S("administration.users.update"),N=S("administration.users.delete"),ee=o.useMemo(()=>({search:c.get("search")||"",status:c.get("status")||"all",roleId:c.get("roleId")||"",source:c.get("source")||"all",userType:c.get("userType")||"",sortBy:c.get("sortBy")||"lastname",sortDesc:c.get("sortDesc")==="true"}),[c]),[u,te]=o.useState([]),[F,se]=o.useState([]),[g,O]=o.useState(!0),[r,M]=o.useState(ee),[T,q]=o.useState(!1),[b,D]=o.useState(parseInt(c.get("page")||"1")),[ae,re]=o.useState(1),[L,le]=o.useState(0),[ie,w]=o.useState(!1),[h,G]=o.useState(null),[m,p]=o.useState({email:"",password:"",firstName:"",lastName:"",roleIds:[]}),[$,V]=o.useState(!1),[K,I]=o.useState(null),[C,ne]=o.useState("table");o.useEffect(()=>{const t={search:c.get("search")||"",status:c.get("status")||"all",roleId:c.get("roleId")||"",source:c.get("source")||"all",userType:c.get("userType")||"",sortBy:c.get("sortBy")||"lastname",sortDesc:c.get("sortDesc")==="true"};JSON.stringify(t)!==JSON.stringify(r)&&M(t);const s=parseInt(c.get("page")||"1");s!==b&&D(s)},[c]);const z=we(r.search,300),k=o.useMemo(()=>{let t=0;return r.status!=="all"&&t++,r.roleId&&t++,r.source!=="all"&&t++,r.userType&&t++,t},[r]),f=o.useCallback(async()=>{try{O(!0);const t=await i.adminApi.users.getAll({page:b,pageSize:20,search:z||void 0,isActive:r.status==="all"?void 0:r.status==="active",entraOnly:r.source==="entra"?!0:void 0,roleId:r.roleId||void 0,userType:r.userType||void 0,sortBy:r.sortBy||void 0,sortDesc:r.sortDesc});te(t.items),re(t.totalPages),le(t.totalCount)}catch(t){console.error("Failed to load users:",t)}finally{O(!1)}},[b,z,r.status,r.source,r.roleId,r.userType,r.sortBy,r.sortDesc]);o.useEffect(()=>{const t=new URLSearchParams;r.search&&t.set("search",r.search),r.status!=="all"&&t.set("status",r.status),r.roleId&&t.set("roleId",r.roleId),r.source!=="all"&&t.set("source",r.source),r.userType&&t.set("userType",r.userType),r.sortBy!=="lastname"&&t.set("sortBy",r.sortBy),r.sortDesc&&t.set("sortDesc","true"),b>1&&t.set("page",b.toString()),j(t,{replace:!0})},[r,b,j]);const ce=async()=>{try{const t=await i.adminApi.roles.getAll();se(t)}catch(t){console.error("Failed to load roles:",t)}};o.useEffect(()=>{f()},[f,P?.id,B]),o.useEffect(()=>{ce()},[]);const oe=()=>{M(Ce),D(1)},v=(t,s)=>{M(n=>({...n,[t]:s})),D(1)},de=()=>{G(null),p({email:"",password:"",firstName:"",lastName:"",roleIds:[]}),I(null),w(!0)},W=async t=>{try{const s=await i.adminApi.users.getById(t.id);G(t),p({email:s.email,password:"",firstName:s.firstName,lastName:s.lastName,roleIds:s.roles.map(n=>n.id)}),I(null),w(!0)}catch(s){console.error("Failed to load user details:",s)}},xe=async t=>{t.preventDefault(),V(!0),I(null);try{if(h){const s={email:m.email!==h.email?m.email:void 0,firstName:m.firstName,lastName:m.lastName,roleIds:m.roleIds};await i.adminApi.users.update(h.id,s)}else await i.adminApi.users.create(m);w(!1),f()}catch(s){const n=s instanceof Error?s.message:"An error occurred";I(n)}finally{V(!1)}},R=async(t,s)=>{s?.stopPropagation();try{t.isActive?await i.adminApi.users.deactivate(t.id):await i.adminApi.users.activate(t.id),f()}catch(n){console.error("Failed to toggle user status:",n)}},X=async(t,s)=>{if(s?.stopPropagation(),!!confirm(a("users.confirmDelete",{name:t.fullName})))try{await i.adminApi.users.delete(t.id),f()}catch(n){console.error("Failed to delete user:",n)}},me=t=>{p(s=>({...s,roleIds:s.roleIds?.includes(t)?s.roleIds.filter(n=>n!==t):[...s.roleIds||[],t]}))},U=u.filter(t=>t.isActive),E=u.filter(t=>!t.isActive),ue=Math.floor(U.length*.3),J=(t,s)=>t?s?"text-[var(--text-tertiary)] hover:text-[var(--warning-text)] hover:bg-[var(--warning-bg)]":"text-[var(--text-tertiary)] hover:text-[var(--success-text)] hover:bg-[var(--success-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]",H=(t,s,n)=>t?n(s?"users.deactivate":"users.activate"):n("common.noPermission","Permission insuffisante"),he=t=>t?"text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]",pe=(t,s)=>t?s("common.edit"):s("common.noPermission","Permission insuffisante"),ve=t=>t?"text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]",ge=(t,s)=>t?s("common.delete"):s("common.noPermission","Permission insuffisante"),be=t=>{const s={Direct:"bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300",Group:"bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300",Both:"bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300"},n={Direct:a("users.membershipDirect","Direct"),Group:a("users.membershipGroup","Via groupe"),Both:a("users.membershipBoth","Mixte")};return{color:s[t]||"",label:n[t]||""}},fe=()=>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:"w-12 px-4 py-3",children:e.jsx("input",{type:"checkbox",className:"w-4 h-4 rounded border-[var(--border-color)]"})}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:a("users.columns.name")}),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:a("users.columns.email")}),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:a("users.columns.role")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:a("users.columns.status")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell",children:a("users.columns.source","Source")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell",children:a("users.columns.group","Groupe")}),y.map(t=>e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell",style:t.width?{width:t.width}:void 0,children:t.label},t.key)),e.jsx("th",{className:"w-32 px-4 py-3"})]})}),e.jsxs("tbody",{className:"divide-y divide-[var(--border-color)]",children:[g&&e.jsx("tr",{children:e.jsx("td",{colSpan:8,className:"px-6 py-16 text-center",children:e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsx(l.Loader2,{className:"w-8 h-8 animate-spin text-primary-500"}),e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:"Chargement..."})]})})}),!g&&u.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:8,className:"px-6 py-16 text-center",children:e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsx("div",{className:"w-16 h-16 rounded-full bg-[var(--bg-secondary)] flex items-center justify-center",children:e.jsx(l.Search,{className:"w-8 h-8 text-[var(--text-tertiary)]"})}),e.jsx("span",{className:"text-[var(--text-secondary)]",children:a("users.noUsers")})]})})}),!g&&u.length>0&&u.map(t=>e.jsxs("tr",{className:"group hover:bg-[var(--bg-hover)] transition-all cursor-pointer",onClick:()=>d(`/administration/users/${t.id}`),children:[e.jsx("td",{className:"px-4 py-3",onClick:s=>s.stopPropagation(),children:e.jsx("input",{type:"checkbox",className:"w-4 h-4 rounded border-[var(--border-color)]"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-2.5 h-2.5 text-white"})})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"font-medium text-[var(--text-primary)] group-hover:text-primary-600 transition-colors truncate",children:t.fullName}),t.entraObjectId&&e.jsxs("span",{className:"hidden sm:inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400",children:[e.jsx(l.Cloud,{className:"w-2.5 h-2.5"}),"AAD"]})]}),e.jsxs("p",{className:"text-sm text-[var(--text-tertiary)] truncate md:hidden flex items-center gap-1",children:[e.jsx(l.Mail,{className:"w-3 h-3"}),t.email]})]})]})}),e.jsx("td",{className:"px-4 py-3 hidden md:table-cell",children:e.jsxs("div",{className:"flex items-center gap-2 text-[var(--text-secondary)]",children:[e.jsx(l.Mail,{className:"w-4 h-4 text-[var(--text-tertiary)]"}),e.jsx("span",{className:"truncate",children:t.email})]})}),e.jsx("td",{className:"px-4 py-3 hidden lg:table-cell",children:e.jsx("div",{className:"flex flex-wrap gap-1.5",children:t.roles.length>0?t.roles.map((s,n)=>e.jsx(i.RoleBadge,{role:s,variant:s.toLowerCase().includes("admin")?"accent":"default",icon:e.jsx(l.Shield,{className:"w-3 h-3"})},`${s}-${n}`)):e.jsx("span",{className:"text-sm text-[var(--text-tertiary)] italic",children:"Aucun rôle"})})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx(i.StatusBadge,{status:t.isActive?"active":"inactive",label:t.isActive?a("users.status.active"):a("users.status.inactive")})}),e.jsx("td",{className:"px-4 py-3 hidden xl:table-cell",children:(()=>{const{color:s,label:n}=be(t.membershipSource);return e.jsx("span",{className:`inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium ${s}`,children:n})})()}),e.jsx("td",{className:"px-4 py-3 hidden xl:table-cell",children:t.primaryGroupId?e.jsxs("button",{onClick:s=>{s.stopPropagation(),d(`/administration/groups/${t.primaryGroupId}`)},className:"inline-flex items-center gap-1.5 px-2 py-1 rounded-md text-xs font-medium bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-primary-600 transition-colors",children:[e.jsx(l.Users,{className:"w-3 h-3"}),t.primaryGroupName]}):e.jsx("span",{className:"text-[var(--text-tertiary)]",children:"—"})}),y.map(s=>e.jsx("td",{className:"px-4 py-3 hidden xl:table-cell text-[var(--text-secondary)]",children:s.render(t,{tableId:"users",rowIndex:u.indexOf(t)})},s.key)),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center justify-end gap-1",onClick:s=>s.stopPropagation(),children:[e.jsx("button",{onClick:()=>d(`/administration/users/${t.id}`),className:"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all",title:a("users.view"),children:e.jsx(l.Eye,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>{s.stopPropagation(),W(t)},disabled:!x,className:`p-2 rounded-lg transition-all ${x?"text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]"}`,title:x?a("common.edit"):a("common.noPermission","Permission insuffisante"),children:e.jsx(l.Edit2,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>R(t,s),disabled:!x,className:`p-2 rounded-lg transition-all ${J(x,t.isActive)}`,title:H(x,t.isActive,a),children:t.isActive?e.jsx(l.UserX,{className:"w-4 h-4"}):e.jsx(l.UserCheck,{className:"w-4 h-4"})}),t.userType!=="System"&&t.userType!=="LocalAdmin"&&e.jsx("button",{onClick:s=>X(t,s),disabled:!N,className:`p-2 rounded-lg transition-all ${N?"text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]"}`,title:N?a("common.delete"):a("common.noPermission","Permission insuffisante"),children:e.jsx(l.Trash2,{className:"w-4 h-4"})}),e.jsx(i.Slot,{name:"users.table.row.actions",context:{user:t,reload:f}})]})})]},t.id))]})]})}),Q=()=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:[g&&e.jsxs("div",{className:"col-span-full flex flex-col items-center justify-center py-16",children:[e.jsx(l.Loader2,{className:"w-8 h-8 animate-spin text-primary-500"}),e.jsx("span",{className:"mt-3 text-sm text-[var(--text-secondary)]",children:"Chargement..."})]}),!g&&u.length===0&&e.jsxs("div",{className:"col-span-full flex flex-col items-center justify-center py-16",children:[e.jsx("div",{className:"w-16 h-16 rounded-lg bg-[var(--bg-secondary)] flex items-center justify-center mb-3",children:e.jsx(l.Search,{className:"w-8 h-8 text-[var(--text-tertiary)]"})}),e.jsx("span",{className:"text-[var(--text-secondary)]",children:a("users.noUsers")})]}),!g&&u.length>0&&u.map(t=>e.jsxs("div",{role:"button",tabIndex:0,onClick:()=>d(`/administration/users/${t.id}`),onKeyDown:s=>{(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),d(`/administration/users/${t.id}`))},className:"bg-[var(--bg-card)] border-2 border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)] rounded-[var(--radius-card)] overflow-hidden transition-all hover:shadow-lg hover:border-[var(--color-accent-400)] cursor-pointer flex flex-col text-left",children:[e.jsx("div",{className:"bg-[var(--color-accent-50)] dark:bg-[var(--color-accent-900)]/20 p-4 border-b border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)]",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName,size:"lg",className:"rounded-lg"}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-5 h-5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-3 h-3 text-white"})})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)] truncate",children:t.fullName}),e.jsxs("p",{className:"text-xs text-[var(--text-tertiary)] truncate flex items-center gap-1",children:[e.jsx(l.Mail,{className:"w-3 h-3"}),t.email]})]})]}),e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[e.jsx("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 text-xs rounded-full font-medium ${t.isActive?"bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400":"bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400"}`,children:t.isActive?a("users.status.active"):a("users.status.inactive")}),t.entraObjectId&&e.jsxs("span",{className:"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400",children:[e.jsx(l.Cloud,{className:"w-2.5 h-2.5"}),"AAD"]})]})]})}),e.jsxs("div",{className:"p-4 flex flex-col flex-1",children:[e.jsxs("div",{className:"flex flex-wrap gap-1 mb-3",children:[t.roles.length>0?t.roles.slice(0,2).map(s=>e.jsx(i.RoleBadge,{role:s,variant:s.toLowerCase().includes("admin")?"accent":"default",icon:e.jsx(l.Shield,{className:"w-3 h-3"})},s)):e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"Aucun rôle"}),t.roles.length>2&&e.jsxs("span",{className:"text-xs px-2 py-0.5 rounded-md bg-[var(--bg-secondary)] text-[var(--text-muted)]",children:["+",t.roles.length-2]})]}),e.jsx(i.Slot,{name:"users.card.content",context:{user:t}}),e.jsx("div",{className:"flex-1"}),e.jsxs("div",{className:"flex items-center justify-end gap-1 pt-3 border-t border-[var(--border-color)]",onClick:s=>s.stopPropagation(),children:[e.jsx("button",{onClick:()=>d(`/administration/users/${t.id}`),className:"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all",title:a("users.view"),children:e.jsx(l.Eye,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>{s.stopPropagation(),W(t)},disabled:!x,className:`p-2 rounded-lg transition-all ${he(x)}`,title:pe(x,a),children:e.jsx(l.Edit2,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>R(t,s),disabled:!x,className:`p-2 rounded-lg transition-all ${J(x,t.isActive)}`,title:H(x,t.isActive,a),children:t.isActive?e.jsx(l.UserX,{className:"w-4 h-4"}):e.jsx(l.UserCheck,{className:"w-4 h-4"})}),t.userType!=="System"&&t.userType!=="LocalAdmin"&&e.jsx("button",{onClick:s=>X(t,s),disabled:!N,className:`p-2 rounded-lg transition-all ${ve(N)}`,title:ge(N,a),children:e.jsx(l.Trash2,{className:"w-4 h-4"})})]})]})]},t.id))]}),je=()=>e.jsx("div",{className:"flex gap-6 overflow-x-auto pb-4",children:g?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center py-16",children:[e.jsx(l.Loader2,{className:"w-8 h-8 animate-spin text-primary-500"}),e.jsx("span",{className:"mt-3 text-sm text-[var(--text-secondary)]",children:"Chargement..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(i.KanbanColumn,{title:"Actifs",count:U.length,color:"success",children:U.map(t=>e.jsxs(i.KanbanCard,{onClick:()=>d(`/administration/users/${t.id}`),children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName,size:"sm"}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-2 h-2 text-white"})})]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium text-sm text-[var(--text-primary)] truncate",children:t.fullName}),e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] truncate",children:t.email})]})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[t.roles.length>0?e.jsx(i.RoleBadge,{role:t.roles[0],variant:t.roles[0].toLowerCase().includes("admin")?"accent":"default"}):e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"-"}),e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"En ligne"})]})]},t.id))}),e.jsxs(i.KanbanColumn,{title:"Inactifs",count:E.length,color:"error",children:[E.map(t=>e.jsxs(i.KanbanCard,{onClick:()=>d(`/administration/users/${t.id}`),children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName,size:"sm"}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-2 h-2 text-white"})})]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium text-sm text-[var(--text-primary)] truncate",children:t.fullName}),e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] truncate",children:t.email})]})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[t.roles.length>0?e.jsx(i.RoleBadge,{role:t.roles[0]}):e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"-"}),e.jsx("button",{onClick:s=>R(t,s),disabled:!x,className:`text-xs px-2 py-1 rounded transition-opacity ${x?"bg-[var(--success-bg)] text-[var(--success-text)] hover:opacity-80":"opacity-50 cursor-not-allowed bg-[var(--bg-secondary)] text-[var(--text-tertiary)]"}`,title:x?void 0:a("common.noPermission","Permission insuffisante"),children:"Réactiver"})]})]},t.id)),E.length===0&&e.jsxs("div",{className:"border border-dashed border-[var(--border-color)] rounded-lg p-6 text-center",children:[e.jsx(l.UserCheck,{className:"w-6 h-6 mx-auto mb-2 text-[var(--text-muted)]"}),e.jsx("p",{className:"text-xs text-[var(--text-muted)]",children:"Aucun utilisateur inactif"})]})]})]})});return e.jsxs("div",{className:"space-y-6",children:[e.jsx(i.Breadcrumb,{items:[{label:a("header.title"),href:"/administration"},{label:a("users.title")}]}),e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:a("users.title")}),e.jsxs("p",{className:"text-sm text-[var(--text-tertiary)] mt-1",children:[L," utilisateurs • ",ue," en ligne"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(i.Slot,{name:"users.header.actions",context:{users:u,totalCount:L,reload:f}}),e.jsxs("button",{onClick:de,disabled:!A,className:`btn btn-primary ${A?"":"opacity-50 cursor-not-allowed"}`,title:A?void 0:a("common.noPermission","Permission insuffisante"),children:[e.jsx(l.Plus,{className:"w-4 h-4"}),a("users.create")]})]})]}),e.jsx(Ne,{}),e.jsx("div",{className:"card p-4",children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-col md:flex-row md:items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3 flex-1",children:[e.jsxs("div",{className:"relative flex-1 max-w-md",children:[!r.search&&e.jsx(l.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)] pointer-events-none"}),e.jsx("input",{type:"text",value:r.search,onChange:t=>v("search",t.target.value),placeholder:a("users.filters.searchPlaceholder"),className:"input w-full",style:r.search?void 0:{paddingLeft:"2.5rem"}}),r.search&&e.jsx("button",{onClick:()=>v("search",""),className:"absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-[var(--bg-secondary)]",children:e.jsx(l.X,{className:"w-3 h-3 text-[var(--text-tertiary)]"})})]}),e.jsxs("button",{onClick:()=>q(!T),className:`btn ${T?"btn-primary":"btn-secondary"} relative`,children:[e.jsx(l.Filter,{className:"w-4 h-4"}),e.jsx("span",{className:"hidden sm:inline",children:a("users.filters.title")}),k>0&&e.jsx("span",{className:"absolute -top-1.5 -right-1.5 w-5 h-5 rounded-full bg-[var(--color-accent-500)] text-white text-xs flex items-center justify-center",children:k})]}),k>0&&e.jsx("button",{onClick:oe,className:"btn btn-ghost text-[var(--text-tertiary)] hover:text-[var(--text-primary)]",title:a("users.filters.reset"),children:e.jsx(l.RotateCcw,{className:"w-4 h-4"})})]}),e.jsx("div",{className:"hidden md:block",children:e.jsx(i.ViewToggle,{viewMode:C,onChange:ne,tableLabel:"Table",cardsLabel:"Cards",kanbanLabel:"Kanban"})})]}),T&&e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 pt-4 border-t border-[var(--border-color)]",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.status")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.status,onChange:t=>v("status",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"all",children:a("users.filters.allStatuses")}),e.jsx("option",{value:"active",children:a("users.filters.activeOnly")}),e.jsx("option",{value:"inactive",children:a("users.filters.inactiveOnly")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.role")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.roleId,onChange:t=>v("roleId",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"",children:a("users.filters.allRoles")}),F.map(t=>e.jsx("option",{value:t.id,children:t.name},t.id))]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.source")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.source,onChange:t=>v("source",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"all",children:a("users.filters.allSources")}),e.jsx("option",{value:"entra",children:a("users.filters.entraOnly")}),e.jsx("option",{value:"local",children:a("users.filters.localOnly")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.userType")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.userType,onChange:t=>v("userType",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"",children:a("users.filters.allTypes")}),e.jsx("option",{value:"User",children:a("users.filters.typeUser")}),e.jsx("option",{value:"System",children:a("users.filters.typeSystem")}),e.jsx("option",{value:"LocalAdmin",children:a("users.filters.typeLocalAdmin")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.sortBy")}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsxs("select",{value:r.sortBy,onChange:t=>v("sortBy",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"lastname",children:a("users.filters.sortName")}),e.jsx("option",{value:"email",children:a("users.filters.sortEmail")}),e.jsx("option",{value:"lastlogin",children:a("users.filters.sortLastLogin")}),e.jsx("option",{value:"createdat",children:a("users.filters.sortCreatedAt")}),e.jsx("option",{value:"status",children:a("users.filters.sortStatus")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]}),e.jsx("button",{onClick:()=>v("sortDesc",!r.sortDesc),className:`btn ${r.sortDesc?"btn-primary":"btn-secondary"} px-2.5`,title:r.sortDesc?a("users.filters.sortDesc"):a("users.filters.sortAsc"),children:e.jsx(l.ArrowUpDown,{className:"w-4 h-4"})})]})]})]}),k>0&&!T&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-[var(--text-tertiary)]",children:[e.jsx(l.Filter,{className:"w-4 h-4"}),e.jsx("span",{children:a("users.filters.activeFilters",{count:k})}),e.jsx("button",{onClick:()=>q(!0),className:"text-[var(--color-accent-600)] hover:underline",children:a("users.filters.title")})]})]})}),e.jsx("div",{className:"md:hidden",children:Q()}),e.jsxs("div",{className:"hidden md:block",children:[C==="table"&&fe(),C==="cards"&&Q(),C==="kanban"&&je()]}),C!=="kanban"&&e.jsx(i.Pagination,{page:b,totalPages:ae,totalCount:L,pageSize:20,onPageChange:D,itemLabel:"utilisateurs"}),ie&&e.jsx("div",{className:"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50",children:e.jsxs("div",{className:"card w-full max-w-lg p-6 m-4 max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:a(h?"users.edit":"users.create")}),e.jsx("button",{onClick:()=>w(!1),className:"btn btn-ghost p-2",children:e.jsx(l.X,{className:"w-5 h-5"})})]}),K&&e.jsx("div",{className:"mb-4 p-3 rounded-lg bg-[var(--error-bg)] text-[var(--error-text)] text-sm border border-[var(--error-border)]",children:K}),e.jsxs("form",{onSubmit:xe,className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.form.firstName")}),e.jsx("input",{type:"text",required:!0,value:m.firstName,onChange:t=>p(s=>({...s,firstName:t.target.value})),className:"input w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.form.lastName")}),e.jsx("input",{type:"text",required:!0,value:m.lastName,onChange:t=>p(s=>({...s,lastName:t.target.value})),className:"input w-full"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.columns.email")}),e.jsx("input",{type:"email",required:!0,value:m.email,onChange:t=>p(s=>({...s,email:t.target.value})),className:"input w-full"})]}),!h&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.form.password")}),e.jsx("input",{type:"password",required:!h,value:m.password,onChange:t=>p(s=>({...s,password:t.target.value})),autoComplete:"new-password",className:"input w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-2",children:a("users.form.roles")}),e.jsx("div",{className:"space-y-2 max-h-48 overflow-y-auto p-3 border border-[var(--border-color)] rounded-lg bg-[var(--bg-secondary)]",children:F.map(t=>e.jsxs("label",{className:"flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors",children:[e.jsx("input",{type:"checkbox",checked:m.roleIds?.includes(t.id)||!1,onChange:()=>me(t.id),className:"w-4 h-4 rounded border-[var(--border-color)] text-primary-600 focus:ring-primary-500"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-[var(--text-primary)] font-medium",children:t.name}),t.description&&e.jsx("p",{className:"text-xs text-[var(--text-tertiary)]",children:t.description})]})]},t.id))})]}),e.jsx(i.Slot,{name:"users.form.fields.after",context:{formData:m,onChange:(t,s)=>{if(t.startsWith("ext.")){const n=t.substring(4);p(Y=>({...Y,ext:{...Y.ext||{},[n]:s}}))}else p(n=>({...n,[t]:s}))},disabled:$,isEditing:!!h,user:h}}),e.jsxs("div",{className:"flex justify-end gap-2 pt-4",children:[e.jsx("button",{type:"button",onClick:()=>w(!1),className:"btn btn-secondary",children:a("common.cancel")}),e.jsxs("button",{type:"submit",disabled:$,className:"btn btn-primary disabled:opacity-50",children:[$&&e.jsx(l.Loader2,{className:"w-4 h-4 animate-spin"}),a(h?"common.save":"common.create")]})]})]})]})})]})}exports.UsersPage=ke;
|
|
2
|
-
//# sourceMappingURL=UsersPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react"),Z=require("react-router-dom"),_=require("react-i18next"),l=require("lucide-react"),i=require("./index-BDRogQH_.js");function ye(){const{currentTenant:a,hasGlobalRoles:d,isGlobalView:c}=i.useTenant(),{currentModuleCode:j,getCurrentModule:y,isLoading:P,menu:B}=i.useNavigation();return d&&!c&&a&&j&&!P&&B?{isRestrictedModule:!y(),tenantName:a?.name||null}:{isRestrictedModule:!1,tenantName:null}}function Ne(){const{t:a}=_.useTranslation("admin"),{isRestrictedModule:d,tenantName:c}=ye();return d?e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5 border bg-amber-500/10 border-amber-500/20 rounded-[var(--radius-card)]",children:[e.jsx("div",{className:"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-amber-500/10 rounded-[var(--radius-card)]",children:e.jsx(l.AlertTriangle,{className:"w-4 h-4 text-amber-600"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("span",{className:"font-medium text-amber-700",children:a("scope.banner.restrictedModule","Module restreint")}),e.jsx("p",{className:"text-xs text-amber-600/70 mt-0.5",children:a("scope.banner.restrictedModuleDesc",`Le tenant "{{tenantName}}" n'a pas accès à ce module. Données affichées grâce à vos privilèges administrateur.`,{tenantName:c})})]})]}):null}function we(a,d){const[c,j]=o.useState(a);return o.useEffect(()=>{const y=setTimeout(()=>j(a),d);return()=>clearTimeout(y)},[a,d]),c}const Ce={search:"",status:"all",roleId:"",source:"all",userType:"",sortBy:"lastname",sortDesc:!1};function ke(){const{t:a}=_.useTranslation("admin"),d=Z.useNavigate(),[c,j]=Z.useSearchParams(),y=i.useTableColumnExtensions("users"),{currentTenant:P,isGlobalView:B}=i.useTenant(),{hasPermission:S}=i.useAuth(),A=S("administration.users.create"),x=S("administration.users.update"),N=S("administration.users.delete"),ee=o.useMemo(()=>({search:c.get("search")||"",status:c.get("status")||"all",roleId:c.get("roleId")||"",source:c.get("source")||"all",userType:c.get("userType")||"",sortBy:c.get("sortBy")||"lastname",sortDesc:c.get("sortDesc")==="true"}),[c]),[u,te]=o.useState([]),[F,se]=o.useState([]),[g,O]=o.useState(!0),[r,M]=o.useState(ee),[T,q]=o.useState(!1),[b,D]=o.useState(parseInt(c.get("page")||"1")),[ae,re]=o.useState(1),[L,le]=o.useState(0),[ie,w]=o.useState(!1),[h,G]=o.useState(null),[m,p]=o.useState({email:"",password:"",firstName:"",lastName:"",roleIds:[]}),[$,V]=o.useState(!1),[K,I]=o.useState(null),[C,ne]=o.useState("table");o.useEffect(()=>{const t={search:c.get("search")||"",status:c.get("status")||"all",roleId:c.get("roleId")||"",source:c.get("source")||"all",userType:c.get("userType")||"",sortBy:c.get("sortBy")||"lastname",sortDesc:c.get("sortDesc")==="true"};JSON.stringify(t)!==JSON.stringify(r)&&M(t);const s=parseInt(c.get("page")||"1");s!==b&&D(s)},[c]);const z=we(r.search,300),k=o.useMemo(()=>{let t=0;return r.status!=="all"&&t++,r.roleId&&t++,r.source!=="all"&&t++,r.userType&&t++,t},[r]),f=o.useCallback(async()=>{try{O(!0);const t=await i.adminApi.users.getAll({page:b,pageSize:20,search:z||void 0,isActive:r.status==="all"?void 0:r.status==="active",entraOnly:r.source==="entra"?!0:void 0,roleId:r.roleId||void 0,userType:r.userType||void 0,sortBy:r.sortBy||void 0,sortDesc:r.sortDesc});te(t.items),re(t.totalPages),le(t.totalCount)}catch(t){console.error("Failed to load users:",t)}finally{O(!1)}},[b,z,r.status,r.source,r.roleId,r.userType,r.sortBy,r.sortDesc]);o.useEffect(()=>{const t=new URLSearchParams;r.search&&t.set("search",r.search),r.status!=="all"&&t.set("status",r.status),r.roleId&&t.set("roleId",r.roleId),r.source!=="all"&&t.set("source",r.source),r.userType&&t.set("userType",r.userType),r.sortBy!=="lastname"&&t.set("sortBy",r.sortBy),r.sortDesc&&t.set("sortDesc","true"),b>1&&t.set("page",b.toString()),j(t,{replace:!0})},[r,b,j]);const ce=async()=>{try{const t=await i.adminApi.roles.getAll();se(t)}catch(t){console.error("Failed to load roles:",t)}};o.useEffect(()=>{f()},[f,P?.id,B]),o.useEffect(()=>{ce()},[]);const oe=()=>{M(Ce),D(1)},v=(t,s)=>{M(n=>({...n,[t]:s})),D(1)},de=()=>{G(null),p({email:"",password:"",firstName:"",lastName:"",roleIds:[]}),I(null),w(!0)},W=async t=>{try{const s=await i.adminApi.users.getById(t.id);G(t),p({email:s.email,password:"",firstName:s.firstName,lastName:s.lastName,roleIds:s.roles.map(n=>n.id)}),I(null),w(!0)}catch(s){console.error("Failed to load user details:",s)}},xe=async t=>{t.preventDefault(),V(!0),I(null);try{if(h){const s={email:m.email!==h.email?m.email:void 0,firstName:m.firstName,lastName:m.lastName,roleIds:m.roleIds};await i.adminApi.users.update(h.id,s)}else await i.adminApi.users.create(m);w(!1),f()}catch(s){const n=s instanceof Error?s.message:"An error occurred";I(n)}finally{V(!1)}},R=async(t,s)=>{s?.stopPropagation();try{t.isActive?await i.adminApi.users.deactivate(t.id):await i.adminApi.users.activate(t.id),f()}catch(n){console.error("Failed to toggle user status:",n)}},X=async(t,s)=>{if(s?.stopPropagation(),!!confirm(a("users.confirmDelete",{name:t.fullName})))try{await i.adminApi.users.delete(t.id),f()}catch(n){console.error("Failed to delete user:",n)}},me=t=>{p(s=>({...s,roleIds:s.roleIds?.includes(t)?s.roleIds.filter(n=>n!==t):[...s.roleIds||[],t]}))},U=u.filter(t=>t.isActive),E=u.filter(t=>!t.isActive),ue=Math.floor(U.length*.3),J=(t,s)=>t?s?"text-[var(--text-tertiary)] hover:text-[var(--warning-text)] hover:bg-[var(--warning-bg)]":"text-[var(--text-tertiary)] hover:text-[var(--success-text)] hover:bg-[var(--success-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]",H=(t,s,n)=>t?n(s?"users.deactivate":"users.activate"):n("common.noPermission","Permission insuffisante"),he=t=>t?"text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]",pe=(t,s)=>t?s("common.edit"):s("common.noPermission","Permission insuffisante"),ve=t=>t?"text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]",ge=(t,s)=>t?s("common.delete"):s("common.noPermission","Permission insuffisante"),be=t=>{const s={Direct:"bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300",Group:"bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300",Both:"bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300"},n={Direct:a("users.membershipDirect","Direct"),Group:a("users.membershipGroup","Via groupe"),Both:a("users.membershipBoth","Mixte")};return{color:s[t]||"",label:n[t]||""}},fe=()=>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:"w-12 px-4 py-3",children:e.jsx("input",{type:"checkbox",className:"w-4 h-4 rounded border-[var(--border-color)]"})}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:a("users.columns.name")}),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:a("users.columns.email")}),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:a("users.columns.role")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider",children:a("users.columns.status")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell",children:a("users.columns.source","Source")}),e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell",children:a("users.columns.group","Groupe")}),y.map(t=>e.jsx("th",{className:"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell",style:t.width?{width:t.width}:void 0,children:t.label},t.key)),e.jsx("th",{className:"w-32 px-4 py-3"})]})}),e.jsxs("tbody",{className:"divide-y divide-[var(--border-color)]",children:[g&&e.jsx("tr",{children:e.jsx("td",{colSpan:8,className:"px-6 py-16 text-center",children:e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsx(l.Loader2,{className:"w-8 h-8 animate-spin text-primary-500"}),e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:"Chargement..."})]})})}),!g&&u.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:8,className:"px-6 py-16 text-center",children:e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsx("div",{className:"w-16 h-16 rounded-full bg-[var(--bg-secondary)] flex items-center justify-center",children:e.jsx(l.Search,{className:"w-8 h-8 text-[var(--text-tertiary)]"})}),e.jsx("span",{className:"text-[var(--text-secondary)]",children:a("users.noUsers")})]})})}),!g&&u.length>0&&u.map(t=>e.jsxs("tr",{className:"group hover:bg-[var(--bg-hover)] transition-all cursor-pointer",onClick:()=>d(`/administration/users/${t.id}`),children:[e.jsx("td",{className:"px-4 py-3",onClick:s=>s.stopPropagation(),children:e.jsx("input",{type:"checkbox",className:"w-4 h-4 rounded border-[var(--border-color)]"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-2.5 h-2.5 text-white"})})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"font-medium text-[var(--text-primary)] group-hover:text-primary-600 transition-colors truncate",children:t.fullName}),t.entraObjectId&&e.jsxs("span",{className:"hidden sm:inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400",children:[e.jsx(l.Cloud,{className:"w-2.5 h-2.5"}),"AAD"]})]}),e.jsxs("p",{className:"text-sm text-[var(--text-tertiary)] truncate md:hidden flex items-center gap-1",children:[e.jsx(l.Mail,{className:"w-3 h-3"}),t.email]})]})]})}),e.jsx("td",{className:"px-4 py-3 hidden md:table-cell",children:e.jsxs("div",{className:"flex items-center gap-2 text-[var(--text-secondary)]",children:[e.jsx(l.Mail,{className:"w-4 h-4 text-[var(--text-tertiary)]"}),e.jsx("span",{className:"truncate",children:t.email})]})}),e.jsx("td",{className:"px-4 py-3 hidden lg:table-cell",children:e.jsx("div",{className:"flex flex-wrap gap-1.5",children:t.roles.length>0?t.roles.map((s,n)=>e.jsx(i.RoleBadge,{role:s,variant:s.toLowerCase().includes("admin")?"accent":"default",icon:e.jsx(l.Shield,{className:"w-3 h-3"})},`${s}-${n}`)):e.jsx("span",{className:"text-sm text-[var(--text-tertiary)] italic",children:"Aucun rôle"})})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx(i.StatusBadge,{status:t.isActive?"active":"inactive",label:t.isActive?a("users.status.active"):a("users.status.inactive")})}),e.jsx("td",{className:"px-4 py-3 hidden xl:table-cell",children:(()=>{const{color:s,label:n}=be(t.membershipSource);return e.jsx("span",{className:`inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium ${s}`,children:n})})()}),e.jsx("td",{className:"px-4 py-3 hidden xl:table-cell",children:t.primaryGroupId?e.jsxs("button",{onClick:s=>{s.stopPropagation(),d(`/administration/groups/${t.primaryGroupId}`)},className:"inline-flex items-center gap-1.5 px-2 py-1 rounded-md text-xs font-medium bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-primary-600 transition-colors",children:[e.jsx(l.Users,{className:"w-3 h-3"}),t.primaryGroupName]}):e.jsx("span",{className:"text-[var(--text-tertiary)]",children:"—"})}),y.map(s=>e.jsx("td",{className:"px-4 py-3 hidden xl:table-cell text-[var(--text-secondary)]",children:s.render(t,{tableId:"users",rowIndex:u.indexOf(t)})},s.key)),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center justify-end gap-1",onClick:s=>s.stopPropagation(),children:[e.jsx("button",{onClick:()=>d(`/administration/users/${t.id}`),className:"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all",title:a("users.view"),children:e.jsx(l.Eye,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>{s.stopPropagation(),W(t)},disabled:!x,className:`p-2 rounded-lg transition-all ${x?"text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]"}`,title:x?a("common.edit"):a("common.noPermission","Permission insuffisante"),children:e.jsx(l.Edit2,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>R(t,s),disabled:!x,className:`p-2 rounded-lg transition-all ${J(x,t.isActive)}`,title:H(x,t.isActive,a),children:t.isActive?e.jsx(l.UserX,{className:"w-4 h-4"}):e.jsx(l.UserCheck,{className:"w-4 h-4"})}),t.userType!=="System"&&t.userType!=="LocalAdmin"&&e.jsx("button",{onClick:s=>X(t,s),disabled:!N,className:`p-2 rounded-lg transition-all ${N?"text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]":"opacity-50 cursor-not-allowed text-[var(--text-tertiary)]"}`,title:N?a("common.delete"):a("common.noPermission","Permission insuffisante"),children:e.jsx(l.Trash2,{className:"w-4 h-4"})}),e.jsx(i.Slot,{name:"users.table.row.actions",context:{user:t,reload:f}})]})})]},t.id))]})]})}),Q=()=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",children:[g&&e.jsxs("div",{className:"col-span-full flex flex-col items-center justify-center py-16",children:[e.jsx(l.Loader2,{className:"w-8 h-8 animate-spin text-primary-500"}),e.jsx("span",{className:"mt-3 text-sm text-[var(--text-secondary)]",children:"Chargement..."})]}),!g&&u.length===0&&e.jsxs("div",{className:"col-span-full flex flex-col items-center justify-center py-16",children:[e.jsx("div",{className:"w-16 h-16 rounded-lg bg-[var(--bg-secondary)] flex items-center justify-center mb-3",children:e.jsx(l.Search,{className:"w-8 h-8 text-[var(--text-tertiary)]"})}),e.jsx("span",{className:"text-[var(--text-secondary)]",children:a("users.noUsers")})]}),!g&&u.length>0&&u.map(t=>e.jsxs("div",{role:"button",tabIndex:0,onClick:()=>d(`/administration/users/${t.id}`),onKeyDown:s=>{(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),d(`/administration/users/${t.id}`))},className:"bg-[var(--bg-card)] border-2 border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)] rounded-[var(--radius-card)] overflow-hidden transition-all hover:shadow-lg hover:border-[var(--color-accent-400)] cursor-pointer flex flex-col text-left",children:[e.jsx("div",{className:"bg-[var(--color-accent-50)] dark:bg-[var(--color-accent-900)]/20 p-4 border-b border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)]",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName,size:"lg",className:"rounded-lg"}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-5 h-5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-3 h-3 text-white"})})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-[var(--text-primary)] truncate",children:t.fullName}),e.jsxs("p",{className:"text-xs text-[var(--text-tertiary)] truncate flex items-center gap-1",children:[e.jsx(l.Mail,{className:"w-3 h-3"}),t.email]})]})]}),e.jsxs("div",{className:"flex flex-col items-end gap-1",children:[e.jsx("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 text-xs rounded-full font-medium ${t.isActive?"bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400":"bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400"}`,children:t.isActive?a("users.status.active"):a("users.status.inactive")}),t.entraObjectId&&e.jsxs("span",{className:"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400",children:[e.jsx(l.Cloud,{className:"w-2.5 h-2.5"}),"AAD"]})]})]})}),e.jsxs("div",{className:"p-4 flex flex-col flex-1",children:[e.jsxs("div",{className:"flex flex-wrap gap-1 mb-3",children:[t.roles.length>0?t.roles.slice(0,2).map(s=>e.jsx(i.RoleBadge,{role:s,variant:s.toLowerCase().includes("admin")?"accent":"default",icon:e.jsx(l.Shield,{className:"w-3 h-3"})},s)):e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"Aucun rôle"}),t.roles.length>2&&e.jsxs("span",{className:"text-xs px-2 py-0.5 rounded-md bg-[var(--bg-secondary)] text-[var(--text-muted)]",children:["+",t.roles.length-2]})]}),e.jsx(i.Slot,{name:"users.card.content",context:{user:t}}),e.jsx("div",{className:"flex-1"}),e.jsxs("div",{className:"flex items-center justify-end gap-1 pt-3 border-t border-[var(--border-color)]",onClick:s=>s.stopPropagation(),children:[e.jsx("button",{onClick:()=>d(`/administration/users/${t.id}`),className:"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all",title:a("users.view"),children:e.jsx(l.Eye,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>{s.stopPropagation(),W(t)},disabled:!x,className:`p-2 rounded-lg transition-all ${he(x)}`,title:pe(x,a),children:e.jsx(l.Edit2,{className:"w-4 h-4"})}),e.jsx("button",{onClick:s=>R(t,s),disabled:!x,className:`p-2 rounded-lg transition-all ${J(x,t.isActive)}`,title:H(x,t.isActive,a),children:t.isActive?e.jsx(l.UserX,{className:"w-4 h-4"}):e.jsx(l.UserCheck,{className:"w-4 h-4"})}),t.userType!=="System"&&t.userType!=="LocalAdmin"&&e.jsx("button",{onClick:s=>X(t,s),disabled:!N,className:`p-2 rounded-lg transition-all ${ve(N)}`,title:ge(N,a),children:e.jsx(l.Trash2,{className:"w-4 h-4"})})]})]})]},t.id))]}),je=()=>e.jsx("div",{className:"flex gap-6 overflow-x-auto pb-4",children:g?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center py-16",children:[e.jsx(l.Loader2,{className:"w-8 h-8 animate-spin text-primary-500"}),e.jsx("span",{className:"mt-3 text-sm text-[var(--text-secondary)]",children:"Chargement..."})]}):e.jsxs(e.Fragment,{children:[e.jsx(i.KanbanColumn,{title:"Actifs",count:U.length,color:"success",children:U.map(t=>e.jsxs(i.KanbanCard,{onClick:()=>d(`/administration/users/${t.id}`),children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName,size:"sm"}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-2 h-2 text-white"})})]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium text-sm text-[var(--text-primary)] truncate",children:t.fullName}),e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] truncate",children:t.email})]})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[t.roles.length>0?e.jsx(i.RoleBadge,{role:t.roles[0],variant:t.roles[0].toLowerCase().includes("admin")?"accent":"default"}):e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"-"}),e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"En ligne"})]})]},t.id))}),e.jsxs(i.KanbanColumn,{title:"Inactifs",count:E.length,color:"error",children:[E.map(t=>e.jsxs(i.KanbanCard,{onClick:()=>d(`/administration/users/${t.id}`),children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(i.Avatar,{name:t.fullName,size:"sm"}),t.entraObjectId&&e.jsx("div",{className:"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]",title:a("users.syncedWithAad"),children:e.jsx(l.Cloud,{className:"w-2 h-2 text-white"})})]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium text-sm text-[var(--text-primary)] truncate",children:t.fullName}),e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] truncate",children:t.email})]})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[t.roles.length>0?e.jsx(i.RoleBadge,{role:t.roles[0]}):e.jsx("span",{className:"text-xs text-[var(--text-muted)]",children:"-"}),e.jsx("button",{onClick:s=>R(t,s),disabled:!x,className:`text-xs px-2 py-1 rounded transition-opacity ${x?"bg-[var(--success-bg)] text-[var(--success-text)] hover:opacity-80":"opacity-50 cursor-not-allowed bg-[var(--bg-secondary)] text-[var(--text-tertiary)]"}`,title:x?void 0:a("common.noPermission","Permission insuffisante"),children:"Réactiver"})]})]},t.id)),E.length===0&&e.jsxs("div",{className:"border border-dashed border-[var(--border-color)] rounded-lg p-6 text-center",children:[e.jsx(l.UserCheck,{className:"w-6 h-6 mx-auto mb-2 text-[var(--text-muted)]"}),e.jsx("p",{className:"text-xs text-[var(--text-muted)]",children:"Aucun utilisateur inactif"})]})]})]})});return e.jsxs("div",{className:"space-y-6",children:[e.jsx(i.Breadcrumb,{items:[{label:a("header.title"),href:"/administration"},{label:a("users.title")}]}),e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:a("users.title")}),e.jsxs("p",{className:"text-sm text-[var(--text-tertiary)] mt-1",children:[L," utilisateurs • ",ue," en ligne"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(i.Slot,{name:"users.header.actions",context:{users:u,totalCount:L,reload:f}}),e.jsxs("button",{onClick:de,disabled:!A,className:`btn btn-primary ${A?"":"opacity-50 cursor-not-allowed"}`,title:A?void 0:a("common.noPermission","Permission insuffisante"),children:[e.jsx(l.Plus,{className:"w-4 h-4"}),a("users.create")]})]})]}),e.jsx(Ne,{}),e.jsx("div",{className:"card p-4",children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-col md:flex-row md:items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3 flex-1",children:[e.jsxs("div",{className:"relative flex-1 max-w-md",children:[!r.search&&e.jsx(l.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)] pointer-events-none"}),e.jsx("input",{type:"text",value:r.search,onChange:t=>v("search",t.target.value),placeholder:a("users.filters.searchPlaceholder"),className:"input w-full",style:r.search?void 0:{paddingLeft:"2.5rem"}}),r.search&&e.jsx("button",{onClick:()=>v("search",""),className:"absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-[var(--bg-secondary)]",children:e.jsx(l.X,{className:"w-3 h-3 text-[var(--text-tertiary)]"})})]}),e.jsxs("button",{onClick:()=>q(!T),className:`btn ${T?"btn-primary":"btn-secondary"} relative`,children:[e.jsx(l.Filter,{className:"w-4 h-4"}),e.jsx("span",{className:"hidden sm:inline",children:a("users.filters.title")}),k>0&&e.jsx("span",{className:"absolute -top-1.5 -right-1.5 w-5 h-5 rounded-full bg-[var(--color-accent-500)] text-white text-xs flex items-center justify-center",children:k})]}),k>0&&e.jsx("button",{onClick:oe,className:"btn btn-ghost text-[var(--text-tertiary)] hover:text-[var(--text-primary)]",title:a("users.filters.reset"),children:e.jsx(l.RotateCcw,{className:"w-4 h-4"})})]}),e.jsx("div",{className:"hidden md:block",children:e.jsx(i.ViewToggle,{viewMode:C,onChange:ne,tableLabel:"Table",cardsLabel:"Cards",kanbanLabel:"Kanban"})})]}),T&&e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 pt-4 border-t border-[var(--border-color)]",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.status")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.status,onChange:t=>v("status",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"all",children:a("users.filters.allStatuses")}),e.jsx("option",{value:"active",children:a("users.filters.activeOnly")}),e.jsx("option",{value:"inactive",children:a("users.filters.inactiveOnly")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.role")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.roleId,onChange:t=>v("roleId",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"",children:a("users.filters.allRoles")}),F.map(t=>e.jsx("option",{value:t.id,children:t.name},t.id))]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.source")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.source,onChange:t=>v("source",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"all",children:a("users.filters.allSources")}),e.jsx("option",{value:"entra",children:a("users.filters.entraOnly")}),e.jsx("option",{value:"local",children:a("users.filters.localOnly")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.userType")}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{value:r.userType,onChange:t=>v("userType",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"",children:a("users.filters.allTypes")}),e.jsx("option",{value:"User",children:a("users.filters.typeUser")}),e.jsx("option",{value:"System",children:a("users.filters.typeSystem")}),e.jsx("option",{value:"LocalAdmin",children:a("users.filters.typeLocalAdmin")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5",children:a("users.filters.sortBy")}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsxs("select",{value:r.sortBy,onChange:t=>v("sortBy",t.target.value),className:"input w-full appearance-none pr-8",children:[e.jsx("option",{value:"lastname",children:a("users.filters.sortName")}),e.jsx("option",{value:"email",children:a("users.filters.sortEmail")}),e.jsx("option",{value:"lastlogin",children:a("users.filters.sortLastLogin")}),e.jsx("option",{value:"createdat",children:a("users.filters.sortCreatedAt")}),e.jsx("option",{value:"status",children:a("users.filters.sortStatus")})]}),e.jsx(l.ChevronDown,{className:"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none"})]}),e.jsx("button",{onClick:()=>v("sortDesc",!r.sortDesc),className:`btn ${r.sortDesc?"btn-primary":"btn-secondary"} px-2.5`,title:r.sortDesc?a("users.filters.sortDesc"):a("users.filters.sortAsc"),children:e.jsx(l.ArrowUpDown,{className:"w-4 h-4"})})]})]})]}),k>0&&!T&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-[var(--text-tertiary)]",children:[e.jsx(l.Filter,{className:"w-4 h-4"}),e.jsx("span",{children:a("users.filters.activeFilters",{count:k})}),e.jsx("button",{onClick:()=>q(!0),className:"text-[var(--color-accent-600)] hover:underline",children:a("users.filters.title")})]})]})}),e.jsx("div",{className:"md:hidden",children:Q()}),e.jsxs("div",{className:"hidden md:block",children:[C==="table"&&fe(),C==="cards"&&Q(),C==="kanban"&&je()]}),C!=="kanban"&&e.jsx(i.Pagination,{page:b,totalPages:ae,totalCount:L,pageSize:20,onPageChange:D,itemLabel:"utilisateurs"}),ie&&e.jsx("div",{className:"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50",children:e.jsxs("div",{className:"card w-full max-w-lg p-6 m-4 max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsx("h2",{className:"text-xl font-bold text-[var(--text-primary)]",children:a(h?"users.edit":"users.create")}),e.jsx("button",{onClick:()=>w(!1),className:"btn btn-ghost p-2",children:e.jsx(l.X,{className:"w-5 h-5"})})]}),K&&e.jsx("div",{className:"mb-4 p-3 rounded-lg bg-[var(--error-bg)] text-[var(--error-text)] text-sm border border-[var(--error-border)]",children:K}),e.jsxs("form",{onSubmit:xe,className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.form.firstName")}),e.jsx("input",{type:"text",required:!0,value:m.firstName,onChange:t=>p(s=>({...s,firstName:t.target.value})),className:"input w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.form.lastName")}),e.jsx("input",{type:"text",required:!0,value:m.lastName,onChange:t=>p(s=>({...s,lastName:t.target.value})),className:"input w-full"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.columns.email")}),e.jsx("input",{type:"email",required:!0,value:m.email,onChange:t=>p(s=>({...s,email:t.target.value})),className:"input w-full"})]}),!h&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-1",children:a("users.form.password")}),e.jsx("input",{type:"password",required:!h,value:m.password,onChange:t=>p(s=>({...s,password:t.target.value})),autoComplete:"new-password",className:"input w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-secondary)] mb-2",children:a("users.form.roles")}),e.jsx("div",{className:"space-y-2 max-h-48 overflow-y-auto p-3 border border-[var(--border-color)] rounded-lg bg-[var(--bg-secondary)]",children:F.map(t=>e.jsxs("label",{className:"flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors",children:[e.jsx("input",{type:"checkbox",checked:m.roleIds?.includes(t.id)||!1,onChange:()=>me(t.id),className:"w-4 h-4 rounded border-[var(--border-color)] text-primary-600 focus:ring-primary-500"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-[var(--text-primary)] font-medium",children:t.name}),t.description&&e.jsx("p",{className:"text-xs text-[var(--text-tertiary)]",children:t.description})]})]},t.id))})]}),e.jsx(i.Slot,{name:"users.form.fields.after",context:{formData:m,onChange:(t,s)=>{if(t.startsWith("ext.")){const n=t.substring(4);p(Y=>({...Y,ext:{...Y.ext||{},[n]:s}}))}else p(n=>({...n,[t]:s}))},disabled:$,isEditing:!!h,user:h}}),e.jsxs("div",{className:"flex justify-end gap-2 pt-4",children:[e.jsx("button",{type:"button",onClick:()=>w(!1),className:"btn btn-secondary",children:a("common.cancel")}),e.jsxs("button",{type:"submit",disabled:$,className:"btn btn-primary disabled:opacity-50",children:[$&&e.jsx(l.Loader2,{className:"w-4 h-4 animate-spin"}),a(h?"common.save":"common.create")]})]})]})]})})]})}exports.UsersPage=ke;
|
|
2
|
+
//# sourceMappingURL=UsersPage-1sLlq9QD.js.map
|