@atlashub/smartstack 3.29.0 → 3.30.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-ChykpPZx.js → AgentSkillsPage-CVq3qZoe.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ChykpPZx.js.map → AgentSkillsPage-CVq3qZoe.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-ABpqnnyK.js → AgentSkillsPage-DJb49NMA.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ABpqnnyK.js.map → AgentSkillsPage-DJb49NMA.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BltzNlXI.js → AgentWorkloadPage-D_nk3gKj.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BltzNlXI.js.map → AgentWorkloadPage-D_nk3gKj.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BI5QWJyQ.js → AgentWorkloadPage-oHEi-sFh.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BI5QWJyQ.js.map → AgentWorkloadPage-oHEi-sFh.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BaheZKBq.js → ApiCatalogDetailPage-Cr0q2HnB.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-BaheZKBq.js.map → ApiCatalogDetailPage-Cr0q2HnB.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-CsRxlHwO.js → ApiCatalogDetailPage-DX8buBkV.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-CsRxlHwO.js.map → ApiCatalogDetailPage-DX8buBkV.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-CqmmHpQ4.js → ApiCatalogPage-DN7sazvI.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-CqmmHpQ4.js.map → ApiCatalogPage-DN7sazvI.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-B0yIz8-U.js → ApiCatalogPage-DqboIzZE.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-B0yIz8-U.js.map → ApiCatalogPage-DqboIzZE.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CngD5JSN.js → ApplicationDetailPage--9YwwS5A.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage-CngD5JSN.js.map → ApplicationDetailPage--9YwwS5A.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CdT6KNd7.js → ApplicationDetailPage-CCNjr64K.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-CdT6KNd7.js.map → ApplicationDetailPage-CCNjr64K.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-DHmnjk2O.js → ApplicationsDashboardPage-BSsHN3Yj.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-DHmnjk2O.js.map → ApplicationsDashboardPage-BSsHN3Yj.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-1V4iQ6eY.js → ApplicationsDashboardPage-Bs-Xgca4.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-1V4iQ6eY.js.map → ApplicationsDashboardPage-Bs-Xgca4.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-Bo3NDnBF.js → ApplicationsGridPage-DDysNWJ5.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-Bo3NDnBF.js.map → ApplicationsGridPage-DDysNWJ5.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-CiMJFlB_.js → ApplicationsGridPage-s1WEzOXS.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-CiMJFlB_.js.map → ApplicationsGridPage-s1WEzOXS.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-L2_S23aN.js → ApplicationsListPage-B3CSMiV0.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-L2_S23aN.js.map → ApplicationsListPage-B3CSMiV0.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-De8jQ1Cm.js → ApplicationsListPage-B6ZCecIl.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-De8jQ1Cm.js.map → ApplicationsListPage-B6ZCecIl.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-DBq7_Sm8.js → ApplicationsPage-BBaiBM--.js} +2 -2
- package/dist/chunks/{ApplicationsPage-DBq7_Sm8.js.map → ApplicationsPage-BBaiBM--.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-CiNI-b0R.js → ApplicationsPage-ztPwoAGt.js} +4 -4
- package/dist/chunks/{ApplicationsPage-CiNI-b0R.js.map → ApplicationsPage-ztPwoAGt.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-DFsO4ZES.js → AssignmentRulesPage-CK4L4rBO.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-DFsO4ZES.js.map → AssignmentRulesPage-CK4L4rBO.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-C8rfUsMB.js → AssignmentRulesPage-DFSVFFXr.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-C8rfUsMB.js.map → AssignmentRulesPage-DFSVFFXr.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-78C_EBsw.js → AssignmentsPage-Bp7oQD7Q.js} +2 -2
- package/dist/chunks/{AssignmentsPage-78C_EBsw.js.map → AssignmentsPage-Bp7oQD7Q.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-COCikISI.js → AssignmentsPage-JCLpyg94.js} +2 -2
- package/dist/chunks/{AssignmentsPage-COCikISI.js.map → AssignmentsPage-JCLpyg94.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-DqT6ueVi.js → AuthCallbackPage-Bl9xlJ3h.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-DqT6ueVi.js.map → AuthCallbackPage-Bl9xlJ3h.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BF4bkTnR.js → AuthCallbackPage-CzMHz4jy.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BF4bkTnR.js.map → AuthCallbackPage-CzMHz4jy.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-Bh_K5qJn.js → ConfirmEmailPage-D_8T1vqV.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-Bh_K5qJn.js.map → ConfirmEmailPage-D_8T1vqV.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-DJy4idrf.js → ConfirmEmailPage-M7mJgXvn.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-DJy4idrf.js.map → ConfirmEmailPage-M7mJgXvn.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-pL7jbG9o.js → CreateSupportTicketPage-BNEGavlu.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-pL7jbG9o.js.map → CreateSupportTicketPage-BNEGavlu.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-AVTwXbJd.js → CreateSupportTicketPage-C2X2mfds.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-AVTwXbJd.js.map → CreateSupportTicketPage-C2X2mfds.js.map} +1 -1
- package/dist/chunks/{DashboardPage-DdQlTLw0.js → DashboardPage-4oy2YqvT.js} +2 -2
- package/dist/chunks/{DashboardPage-DdQlTLw0.js.map → DashboardPage-4oy2YqvT.js.map} +1 -1
- package/dist/chunks/{DashboardPage-C55mIiB6.js → DashboardPage-CO-8B8EI.js} +3 -3
- package/dist/chunks/{DashboardPage-C55mIiB6.js.map → DashboardPage-CO-8B8EI.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CcCnUl7s.js → DashboardPage-CPArUG-S.js} +2 -2
- package/dist/chunks/{DashboardPage-CcCnUl7s.js.map → DashboardPage-CPArUG-S.js.map} +1 -1
- package/dist/chunks/{DashboardPage-DOitDfGV.js → DashboardPage-D5MRMxEV.js} +3 -3
- package/dist/chunks/{DashboardPage-DOitDfGV.js.map → DashboardPage-D5MRMxEV.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-DNnZftCH.js → EscalationConfigPage-CwdnfJbJ.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-DNnZftCH.js.map → EscalationConfigPage-CwdnfJbJ.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-DRr55328.js → EscalationConfigPage-DnjLFXnL.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-DRr55328.js.map → EscalationConfigPage-DnjLFXnL.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-1SCOPIqK.js → ForceChangePasswordPage-ZEIfyqwE.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-1SCOPIqK.js.map → ForceChangePasswordPage-ZEIfyqwE.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-DBeG_HRO.js → ForceChangePasswordPage-sh-3h_H9.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-DBeG_HRO.js.map → ForceChangePasswordPage-sh-3h_H9.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-Dlb6wKfC.js → ForgotPasswordPage-B4M6-xeM.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-Dlb6wKfC.js.map → ForgotPasswordPage-B4M6-xeM.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-DffYfXva.js → ForgotPasswordPage-MIu-U7p0.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-DffYfXva.js.map → ForgotPasswordPage-MIu-U7p0.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-C9nRbeHI.js → GroupDetailPage-4XK3Bs_r.js} +5 -5
- package/dist/chunks/{GroupDetailPage-C9nRbeHI.js.map → GroupDetailPage-4XK3Bs_r.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-CPPUWzXf.js → GroupDetailPage-C-kvtd2T.js} +2 -2
- package/dist/chunks/{GroupDetailPage-CPPUWzXf.js.map → GroupDetailPage-C-kvtd2T.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-BAX0xwJX.js → MyAccessRequestsPage-CP41FzHi.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-BAX0xwJX.js.map → MyAccessRequestsPage-CP41FzHi.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-BMY1V631.js → MyAccessRequestsPage-DzrXTrVi.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-BMY1V631.js.map → MyAccessRequestsPage-DzrXTrVi.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-Bbn4HxN2.js → MyTenantsPage-CZRkMbh8.js} +2 -2
- package/dist/chunks/{MyTenantsPage-Bbn4HxN2.js.map → MyTenantsPage-CZRkMbh8.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BHtp67SD.js → MyTenantsPage-V_SwYio2.js} +3 -3
- package/dist/chunks/{MyTenantsPage-BHtp67SD.js.map → MyTenantsPage-V_SwYio2.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-BvZeiTXu.js → MyTicketsPage-DOUhaLal.js} +2 -2
- package/dist/chunks/{MyTicketsPage-BvZeiTXu.js.map → MyTicketsPage-DOUhaLal.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-D9IGVofj.js → MyTicketsPage-DnvAIeyr.js} +2 -2
- package/dist/chunks/{MyTicketsPage-D9IGVofj.js.map → MyTicketsPage-DnvAIeyr.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-DiPBCsAF.js → NavigationAppsPage-DXvpLsbt.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-DiPBCsAF.js.map → NavigationAppsPage-DXvpLsbt.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-ChtMK1yt.js → NavigationAppsPage-DfTa4jCG.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-ChtMK1yt.js.map → NavigationAppsPage-DfTa4jCG.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BxCiGzHk.js → NotificationsPage-D76MdAs-.js} +2 -2
- package/dist/chunks/{NotificationsPage-BxCiGzHk.js.map → NotificationsPage-D76MdAs-.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BCnL9oPb.js → NotificationsPage-I1yCk7tk.js} +2 -2
- package/dist/chunks/{NotificationsPage-BCnL9oPb.js.map → NotificationsPage-I1yCk7tk.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-CV_cxq7k.js → OnboardingWizardPage-BRUzcl1A.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-CV_cxq7k.js.map → OnboardingWizardPage-BRUzcl1A.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-Du-tQ2ag.js → OnboardingWizardPage-DtWUPCh3.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-Du-tQ2ag.js.map → OnboardingWizardPage-DtWUPCh3.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-C1iuWv0G.js → PermissionDetailPage-CUNKbl7t.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-C1iuWv0G.js.map → PermissionDetailPage-CUNKbl7t.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Ds4Jt1os.js → PermissionDetailPage-DJJGbXoX.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Ds4Jt1os.js.map → PermissionDetailPage-DJJGbXoX.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-BGI2nxCn.js → PermissionsPage-B8wmawPV.js} +2 -2
- package/dist/chunks/{PermissionsPage-BGI2nxCn.js.map → PermissionsPage-B8wmawPV.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-sauv7ct1.js → PermissionsPage-Dbjcctuh.js} +2 -2
- package/dist/chunks/{PermissionsPage-sauv7ct1.js.map → PermissionsPage-Dbjcctuh.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-CQWEcghD.js → PortalDashboardPage-BeNfBZmb.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-CQWEcghD.js.map → PortalDashboardPage-BeNfBZmb.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-2kCbJw9w.js → PortalDashboardPage-zii0ll57.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-2kCbJw9w.js.map → PortalDashboardPage-zii0ll57.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Bu4gaDRb.js → PreferencesPage-BCpuIGzv.js} +2 -2
- package/dist/chunks/{PreferencesPage-Bu4gaDRb.js.map → PreferencesPage-BCpuIGzv.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Dbg0bEYD.js → PreferencesPage-BmvrBaAD.js} +2 -2
- package/dist/chunks/{PreferencesPage-Dbg0bEYD.js.map → PreferencesPage-BmvrBaAD.js.map} +1 -1
- package/dist/chunks/{ProfilePage-C5QS7tsh.js → ProfilePage-eowQd59_.js} +2 -2
- package/dist/chunks/{ProfilePage-C5QS7tsh.js.map → ProfilePage-eowQd59_.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DfiBhOUt.js → ProfilePage-mf5wI0-n.js} +2 -2
- package/dist/chunks/{ProfilePage-DfiBhOUt.js.map → ProfilePage-mf5wI0-n.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-Bs0mapj8.js → ReferencesManagementPage-8UPgkVE8.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-Bs0mapj8.js.map → ReferencesManagementPage-8UPgkVE8.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-C0RgHbJb.js → ReferencesManagementPage-CLsaUNqA.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-C0RgHbJb.js.map → ReferencesManagementPage-CLsaUNqA.js.map} +1 -1
- package/dist/chunks/{RegisterPage-DS1chV_A.js → RegisterPage-57X-ILDb.js} +2 -2
- package/dist/chunks/{RegisterPage-DS1chV_A.js.map → RegisterPage-57X-ILDb.js.map} +1 -1
- package/dist/chunks/{RegisterPage-DoeIiJt0.js → RegisterPage-CNyHSbqs.js} +2 -2
- package/dist/chunks/{RegisterPage-DoeIiJt0.js.map → RegisterPage-CNyHSbqs.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-3KEk3zj5.js → ResetPasswordPage-CyV8l-Zo.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-3KEk3zj5.js.map → ResetPasswordPage-CyV8l-Zo.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-C_VQSFB5.js → ResetPasswordPage-JW8-mh_k.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-C_VQSFB5.js.map → ResetPasswordPage-JW8-mh_k.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-S6URD--N.js → ResolutionModal-CjwE73NX.js} +2 -2
- package/dist/chunks/{ResolutionModal-S6URD--N.js.map → ResolutionModal-CjwE73NX.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-BzI1x79r.js → ResolutionModal-wddG59kg.js} +2 -2
- package/dist/chunks/{ResolutionModal-BzI1x79r.js.map → ResolutionModal-wddG59kg.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-SXK9cq_3.js → RoleDetailPage-CrioVHFI.js} +3 -3
- package/dist/chunks/{RoleDetailPage-SXK9cq_3.js.map → RoleDetailPage-CrioVHFI.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-DvEEWPKr.js → RoleDetailPage-TUOGR1ow.js} +2 -2
- package/dist/chunks/{RoleDetailPage-DvEEWPKr.js.map → RoleDetailPage-TUOGR1ow.js.map} +1 -1
- package/dist/chunks/{RolesPage-B75lCugt.js → RolesPage-CAcols3D.js} +2 -2
- package/dist/chunks/{RolesPage-B75lCugt.js.map → RolesPage-CAcols3D.js.map} +1 -1
- package/dist/chunks/{RolesPage-C5gYJxAl.js → RolesPage-sJBWaNff.js} +2 -2
- package/dist/chunks/{RolesPage-C5gYJxAl.js.map → RolesPage-sJBWaNff.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BqXHATb6.js → SlaConfigPage-BPGRloOS.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BqXHATb6.js.map → SlaConfigPage-BPGRloOS.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-DZ4P1FFW.js → SlaConfigPage-D5TRn7Ir.js} +2 -2
- package/dist/chunks/{SlaConfigPage-DZ4P1FFW.js.map → SlaConfigPage-D5TRn7Ir.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-B4xy_pCQ.js → SupportPermissionsPage-Dc2bWTzG.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-B4xy_pCQ.js.map → SupportPermissionsPage-Dc2bWTzG.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-DW7KJjYK.js → SupportPermissionsPage-UXmYLrIq.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-DW7KJjYK.js.map → SupportPermissionsPage-UXmYLrIq.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DZa0PQTE.js → TemplatesPage-dmPlqqiD.js} +2 -2
- package/dist/chunks/{TemplatesPage-DZa0PQTE.js.map → TemplatesPage-dmPlqqiD.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-m5-sLJ7F.js → TemplatesPage-nTY85sNA.js} +2 -2
- package/dist/chunks/{TemplatesPage-m5-sLJ7F.js.map → TemplatesPage-nTY85sNA.js.map} +1 -1
- package/dist/chunks/{TenantCard-BJQi7Oew.js → TenantCard-BUXfstRZ.js} +2 -2
- package/dist/chunks/{TenantCard-BJQi7Oew.js.map → TenantCard-BUXfstRZ.js.map} +1 -1
- package/dist/chunks/{TenantCard-CqfifMrM.js → TenantCard-BhT-31ls.js} +2 -2
- package/dist/chunks/{TenantCard-CqfifMrM.js.map → TenantCard-BhT-31ls.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-CdiYJvuH.js → TenantScopeSelector-3_mzBLNI.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-CdiYJvuH.js.map → TenantScopeSelector-3_mzBLNI.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Cl5DD318.js → TenantScopeSelector-B-SRDR2R.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Cl5DD318.js.map → TenantScopeSelector-B-SRDR2R.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-BOC9rHu3.js → TicketDetailPage-B4cR3rOC.js} +2 -2
- package/dist/chunks/{TicketDetailPage-BOC9rHu3.js.map → TicketDetailPage-B4cR3rOC.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-C1UuMxD8.js → TicketDetailPage-xN3wPnFL.js} +2 -2
- package/dist/chunks/{TicketDetailPage-C1UuMxD8.js.map → TicketDetailPage-xN3wPnFL.js.map} +1 -1
- package/dist/chunks/{TicketsPage-BCgHZA-m.js → TicketsPage-CkHgXSxU.js} +2 -2
- package/dist/chunks/{TicketsPage-BCgHZA-m.js.map → TicketsPage-CkHgXSxU.js.map} +1 -1
- package/dist/chunks/{TicketsPage-BjaN4Baq.js → TicketsPage-Dwi2xpMI.js} +2 -2
- package/dist/chunks/{TicketsPage-BjaN4Baq.js.map → TicketsPage-Dwi2xpMI.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-ChQL1mVY.js → UserCreateTicketPage-D2a3EOey.js} +3 -3
- package/dist/chunks/UserCreateTicketPage-D2a3EOey.js.map +1 -0
- package/dist/chunks/{UserCreateTicketPage-DkjsHeV7.js → UserCreateTicketPage-bcbSLglE.js} +48 -48
- package/dist/chunks/UserCreateTicketPage-bcbSLglE.js.map +1 -0
- package/dist/chunks/{UserDashboardPage-BMYrtF3o.js → UserDashboardPage-DwnDRNoW.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BMYrtF3o.js.map → UserDashboardPage-DwnDRNoW.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-81-3GJAQ.js → UserDashboardPage-ZMsx8LWw.js} +2 -2
- package/dist/chunks/{UserDashboardPage-81-3GJAQ.js.map → UserDashboardPage-ZMsx8LWw.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BMW8jAWG.js → UserDetailPage-BRFowOFL.js} +2 -2
- package/dist/chunks/{UserDetailPage-BMW8jAWG.js.map → UserDetailPage-BRFowOFL.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-D6oCH2eS.js → UserDetailPage-CZyV-zsg.js} +5 -5
- package/dist/chunks/{UserDetailPage-D6oCH2eS.js.map → UserDetailPage-CZyV-zsg.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-ZH2BDWBt.js → UserTicketDetailPage-BstGk_BP.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-ZH2BDWBt.js.map → UserTicketDetailPage-BstGk_BP.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-Z_myXXJ0.js → UserTicketDetailPage-DzB_pELt.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-Z_myXXJ0.js.map → UserTicketDetailPage-DzB_pELt.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-B8Ka6uRa.js → UsersGroupsPage-BygTv_kK.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-B8Ka6uRa.js.map → UsersGroupsPage-BygTv_kK.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-xJmGib8b.js → UsersGroupsPage-DTmhzttW.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-xJmGib8b.js.map → UsersGroupsPage-DTmhzttW.js.map} +1 -1
- package/dist/chunks/{UsersPage-CQ38akZ_.js → UsersPage-DcwLyMAX.js} +2 -2
- package/dist/chunks/{UsersPage-CQ38akZ_.js.map → UsersPage-DcwLyMAX.js.map} +1 -1
- package/dist/chunks/{UsersPage-Bd2-vl39.js → UsersPage-TIqSHgHj.js} +2 -2
- package/dist/chunks/{UsersPage-Bd2-vl39.js.map → UsersPage-TIqSHgHj.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-DguOx0q0.js → accessRequestsApi-3FjMFbpa.js} +2 -2
- package/dist/chunks/{accessRequestsApi-DguOx0q0.js.map → accessRequestsApi-3FjMFbpa.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-COtWo9kC.js → accessRequestsApi-B6dsJzvH.js} +2 -2
- package/dist/chunks/{accessRequestsApi-COtWo9kC.js.map → accessRequestsApi-B6dsJzvH.js.map} +1 -1
- package/dist/chunks/{aiApi-CITiWGYX.js → aiApi-9G4wG_mT.js} +2 -2
- package/dist/chunks/{aiApi-CITiWGYX.js.map → aiApi-9G4wG_mT.js.map} +1 -1
- package/dist/chunks/{aiApi-BmZsud6O.js → aiApi-DXOdsoxr.js} +2 -2
- package/dist/chunks/{aiApi-BmZsud6O.js.map → aiApi-DXOdsoxr.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-BYoEJzSN.js → applicationAnalyticsApi-D0DEp9Y-.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-BYoEJzSN.js.map → applicationAnalyticsApi-D0DEp9Y-.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-D62lc6z4.js → applicationAnalyticsApi-DhOd6idI.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-D62lc6z4.js.map → applicationAnalyticsApi-DhOd6idI.js.map} +1 -1
- package/dist/chunks/auth-Ca2Rn6on.js +2 -0
- package/dist/chunks/auth-Ca2Rn6on.js.map +1 -0
- package/dist/chunks/auth-ClNTDOqm.js +18 -0
- package/dist/chunks/auth-ClNTDOqm.js.map +1 -0
- package/dist/chunks/auth-DECnMZjF.js +18 -0
- package/dist/chunks/auth-DECnMZjF.js.map +1 -0
- package/dist/chunks/auth-DPvxdqy4.js +18 -0
- package/dist/chunks/auth-DPvxdqy4.js.map +1 -0
- package/dist/chunks/auth-HzvnTaOm.js +2 -0
- package/dist/chunks/auth-HzvnTaOm.js.map +1 -0
- package/dist/chunks/auth-M6aNTKCH.js +2 -0
- package/dist/chunks/auth-M6aNTKCH.js.map +1 -0
- package/dist/chunks/auth-UHnAu6_e.js +2 -0
- package/dist/chunks/auth-UHnAu6_e.js.map +1 -0
- package/dist/chunks/auth-YrujJY7m.js +18 -0
- package/dist/chunks/auth-YrujJY7m.js.map +1 -0
- package/dist/chunks/{groupsApi-3CR-_g5b.js → groupsApi-Db8G2lLs.js} +2 -2
- package/dist/chunks/{groupsApi-3CR-_g5b.js.map → groupsApi-Db8G2lLs.js.map} +1 -1
- package/dist/chunks/{groupsApi-BUyBgf_N.js → groupsApi-lbxNsHFv.js} +2 -2
- package/dist/chunks/{groupsApi-BUyBgf_N.js.map → groupsApi-lbxNsHFv.js.map} +1 -1
- package/dist/chunks/{index-IJR_91Yt.js → index-BI2dc1FS.js} +2 -2
- package/dist/chunks/{index-IJR_91Yt.js.map → index-BI2dc1FS.js.map} +1 -1
- package/dist/chunks/{index-DIQ6Jmmq.js → index-Bn8HzILk.js} +4 -4
- package/dist/chunks/{index-DIQ6Jmmq.js.map → index-Bn8HzILk.js.map} +1 -1
- package/dist/chunks/{index-DA5VyW0k.js → index-CN2WRyg1.js} +2249 -2264
- package/dist/chunks/index-CN2WRyg1.js.map +1 -0
- package/dist/chunks/{index-Br2wsGE8.js → index-CTGSmYvs.js} +2 -2
- package/dist/chunks/{index-Br2wsGE8.js.map → index-CTGSmYvs.js.map} +1 -1
- package/dist/chunks/index-CUICSveU.js +2 -0
- package/dist/chunks/index-CUICSveU.js.map +1 -0
- package/dist/chunks/{index-S-X8qFYW.js → index-CgtbaFf5.js} +2 -2
- package/dist/chunks/{index-S-X8qFYW.js.map → index-CgtbaFf5.js.map} +1 -1
- package/dist/chunks/{index-_g82N2nb.js → index-D0HS542b.js} +2 -2
- package/dist/chunks/{index-_g82N2nb.js.map → index-D0HS542b.js.map} +1 -1
- package/dist/chunks/{index-BIqcvvbh.js → index-DEtq-xUL.js} +9 -8
- package/dist/chunks/index-DEtq-xUL.js.map +1 -0
- package/dist/chunks/{index-BOKR3bw6.js → index-DF93KQFR.js} +2 -2
- package/dist/chunks/{index-BOKR3bw6.js.map → index-DF93KQFR.js.map} +1 -1
- package/dist/chunks/{index-CxgEV-rT.js → index-DLekpNSE.js} +2 -2
- package/dist/chunks/{index-CxgEV-rT.js.map → index-DLekpNSE.js.map} +1 -1
- package/dist/chunks/{index-DEOBhXS_.js → index-DUS-tunb.js} +2 -2
- package/dist/chunks/{index-DEOBhXS_.js.map → index-DUS-tunb.js.map} +1 -1
- package/dist/chunks/{index-BMsjMCv9.js → index-DjC1u2hI.js} +3 -3
- package/dist/chunks/{index-BMsjMCv9.js.map → index-DjC1u2hI.js.map} +1 -1
- package/dist/chunks/{index-BxHVPJ-j.js → index-DqbVFB1H.js} +2 -2
- package/dist/chunks/{index-BxHVPJ-j.js.map → index-DqbVFB1H.js.map} +1 -1
- package/dist/chunks/{index-Djy4eIbB.js → index-DwqLhQ8S.js} +2 -2
- package/dist/chunks/{index-Djy4eIbB.js.map → index-DwqLhQ8S.js.map} +1 -1
- package/dist/chunks/{index-C1w97Ejz.js → index-HsAOBno4.js} +2 -2
- package/dist/chunks/{index-C1w97Ejz.js.map → index-HsAOBno4.js.map} +1 -1
- package/dist/chunks/{index-Czk12A3G.js → index-TiWOcC0g.js} +2 -2
- package/dist/chunks/{index-Czk12A3G.js.map → index-TiWOcC0g.js.map} +1 -1
- package/dist/chunks/{index-vXiLh35n.js → index-cAikSVW0.js} +13 -13
- package/dist/chunks/index-cAikSVW0.js.map +1 -0
- package/dist/chunks/{index-CNxx56kE.js → index-xhRXN1Jq.js} +2 -2
- package/dist/chunks/{index-CNxx56kE.js.map → index-xhRXN1Jq.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-COKA97Ug.js → tenantIconMap-CHeS7oLt.js} +2 -2
- package/dist/chunks/{tenantIconMap-COKA97Ug.js.map → tenantIconMap-CHeS7oLt.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-BuSQUUyZ.js → tenantIconMap-__FKj6CN.js} +2 -2
- package/dist/chunks/{tenantIconMap-BuSQUUyZ.js.map → tenantIconMap-__FKj6CN.js.map} +1 -1
- package/dist/chunks/{ticketingApi-DbREwHez.js → ticketingApi-Cj239hYB.js} +2 -2
- package/dist/chunks/{ticketingApi-DbREwHez.js.map → ticketingApi-Cj239hYB.js.map} +1 -1
- package/dist/chunks/{ticketingApi-C6EbupqP.js → ticketingApi-DF4RwD_6.js} +2 -2
- package/dist/chunks/{ticketingApi-C6EbupqP.js.map → ticketingApi-DF4RwD_6.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-vucIb3_w.js → useAccessRequests-CFam8zFR.js} +3 -3
- package/dist/chunks/{useAccessRequests-vucIb3_w.js.map → useAccessRequests-CFam8zFR.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-C0dY6y-4.js → useAccessRequests-CViOUwyF.js} +2 -2
- package/dist/chunks/{useAccessRequests-C0dY6y-4.js.map → useAccessRequests-CViOUwyF.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BBcw1Rk9.js → useUserAccessRequests-B-Cs6NX1.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BBcw1Rk9.js.map → useUserAccessRequests-B-Cs6NX1.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-Cj0nkesW.js → useUserAccessRequests-CslSQeBJ.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-Cj0nkesW.js.map → useUserAccessRequests-CslSQeBJ.js.map} +1 -1
- package/dist/contexts/AuthContext.d.ts.map +1 -1
- package/dist/pages/LoginPage.d.ts.map +1 -1
- package/dist/pages/platform/administration/tenants/TenantDetailPage.d.ts.map +1 -1
- package/dist/pages/platform/support/UserCreateTicketPage.d.ts.map +1 -1
- package/dist/services/api/apiClient.d.ts.map +1 -1
- package/dist/services/support/ticketDraftService.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +6 -6
- package/dist/utils/permissions.generated.d.ts +288 -0
- package/dist/utils/permissions.generated.d.ts.map +1 -0
- package/dist/utils/uuid.d.ts +6 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/chunks/UserCreateTicketPage-ChQL1mVY.js.map +0 -1
- package/dist/chunks/UserCreateTicketPage-DkjsHeV7.js.map +0 -1
- package/dist/chunks/auth-B-hELPDB.js +0 -2
- package/dist/chunks/auth-B-hELPDB.js.map +0 -1
- package/dist/chunks/auth-BYaMuq7D.js +0 -16
- package/dist/chunks/auth-BYaMuq7D.js.map +0 -1
- package/dist/chunks/auth-C5zpZ9k7.js +0 -2
- package/dist/chunks/auth-C5zpZ9k7.js.map +0 -1
- package/dist/chunks/auth-CDpRMVv1.js +0 -16
- package/dist/chunks/auth-CDpRMVv1.js.map +0 -1
- package/dist/chunks/auth-CyPkCta2.js +0 -2
- package/dist/chunks/auth-CyPkCta2.js.map +0 -1
- package/dist/chunks/auth-DL47kvnl.js +0 -2
- package/dist/chunks/auth-DL47kvnl.js.map +0 -1
- package/dist/chunks/auth-Diiv90i1.js +0 -16
- package/dist/chunks/auth-Diiv90i1.js.map +0 -1
- package/dist/chunks/auth-rog9MvUr.js +0 -16
- package/dist/chunks/auth-rog9MvUr.js.map +0 -1
- package/dist/chunks/index-BIqcvvbh.js.map +0 -1
- package/dist/chunks/index-DA5VyW0k.js.map +0 -1
- package/dist/chunks/index-Dht6EQW1.js +0 -2
- package/dist/chunks/index-Dht6EQW1.js.map +0 -1
- package/dist/chunks/index-vXiLh35n.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersGroupsPage-xJmGib8b.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 // TENANT ISOLATION: Re-fetch when tenant changes\r\n }, [t, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await 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-DTmhzttW.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 // TENANT ISOLATION: Re-fetch when tenant changes\r\n }, [t, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await 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-vXiLh35n.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",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-amber-500/10",style:{borderRadius:"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"}),[]),[u,te]=o.useState([]),[F,se]=o.useState([]),[b,O]=o.useState(!0),[r,M]=o.useState(ee),[T,q]=o.useState(!1),[g,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:[]}),[R,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!==g&&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:g,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)}},[g,z,r.status,r.source,r.roleId,r.userType,r.sortBy,r.sortDesc,P?.id,B]);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"),g>1&&t.set("page",g.toString()),j(t,{replace:!0})},[r,g,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]),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)}},$=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)]",be=(t,s)=>t?s("common.delete"):s("common.noPermission","Permission insuffisante"),ge=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:[b&&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..."})]})})}),!b&&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")})]})})}),!b&&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}=ge(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=>$(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:[b&&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..."})]}),!b&&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")})]}),!b&&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=>$(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:be(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:b?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=>$(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:g,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:R,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:R,className:"btn btn-primary disabled:opacity-50",children:[R&&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-cAikSVW0.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",style:{borderRadius:"var(--radius-card)"},children:[e.jsx("div",{className:"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-amber-500/10",style:{borderRadius:"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"}),[]),[u,te]=o.useState([]),[F,se]=o.useState([]),[b,O]=o.useState(!0),[r,M]=o.useState(ee),[T,q]=o.useState(!1),[g,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:[]}),[R,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!==g&&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:g,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)}},[g,z,r.status,r.source,r.roleId,r.userType,r.sortBy,r.sortDesc,P?.id,B]);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"),g>1&&t.set("page",g.toString()),j(t,{replace:!0})},[r,g,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]),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)}},$=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)]",be=(t,s)=>t?s("common.delete"):s("common.noPermission","Permission insuffisante"),ge=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:[b&&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..."})]})})}),!b&&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")})]})})}),!b&&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}=ge(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=>$(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:[b&&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..."})]}),!b&&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")})]}),!b&&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=>$(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:be(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:b?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=>$(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:g,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:R,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:R,className:"btn btn-primary disabled:opacity-50",children:[R&&e.jsx(l.Loader2,{className:"w-4 h-4 animate-spin"}),a(h?"common.save":"common.create")]})]})]})]})})]})}exports.UsersPage=ke;
|
|
2
|
+
//# sourceMappingURL=UsersPage-DcwLyMAX.js.map
|