709 lines
24 KiB
HTML
709 lines
24 KiB
HTML
<div class="container-fluid">
|
|
<app-page-title
|
|
[title]="pageTitle"
|
|
[subTitle]="pageSubtitle"
|
|
[badge]="badge"
|
|
/>
|
|
|
|
<!-- Indicateur de permissions -->
|
|
@if (currentUserRole) {
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<div class="alert alert-info py-2">
|
|
<div class="d-flex align-items-center">
|
|
<ng-icon name="lucideInfo" class="me-2"></ng-icon>
|
|
<div class="flex-grow-1">
|
|
<small>
|
|
<strong>Rôle actuel :</strong>
|
|
<span class="badge" [ngClass]="getRoleBadgeClass(currentUserRole)">
|
|
{{ getRoleLabel(currentUserRole) }}
|
|
</span>
|
|
@if (!canCreateUsers) {
|
|
<span class="text-warning ms-2">
|
|
<ng-icon name="lucideShield" class="me-1"></ng-icon>
|
|
Permissions limitées
|
|
</span>
|
|
}
|
|
</small>
|
|
</div>
|
|
@if (canCreateUsers) {
|
|
<button
|
|
class="btn btn-primary btn-sm"
|
|
(click)="openCreateUserModal()"
|
|
>
|
|
<ng-icon name="lucideUserPlus" class="me-1"></ng-icon>
|
|
Nouvel Utilisateur
|
|
</button>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- Navigation par onglets -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<ul
|
|
ngbNav
|
|
#usersNav="ngbNav"
|
|
[activeId]="activeTab"
|
|
[destroyOnHide]="false"
|
|
class="nav nav-tabs nav-justified nav-bordered nav-bordered-primary mb-3"
|
|
>
|
|
<li [ngbNavItem]="'list'">
|
|
<a ngbNavLink (click)="showTab('list')">
|
|
<ng-icon name="lucideUsers" class="fs-lg me-md-1 d-inline-flex align-middle" />
|
|
<span class="d-none d-md-inline-block align-middle">Équipe Marchande</span>
|
|
</a>
|
|
<ng-template ngbNavContent>
|
|
<app-merchant-users-list
|
|
#merchantUsersList
|
|
[canCreateUsers]="canCreateUsers"
|
|
[canDeleteUsers]="canDeleteUsers"
|
|
(userSelected)="onUserSelected($event)"
|
|
(openCreateUserModal)="openCreateUserModal()"
|
|
(resetPasswordRequested)="onResetPasswordRequested($event)"
|
|
(deleteUserRequested)="onDeleteUserRequested($event)"
|
|
/>
|
|
</ng-template>
|
|
</li>
|
|
|
|
<li [ngbNavItem]="'user-profile'" [hidden]="activeTab !== 'user-profile'">
|
|
<a ngbNavLink (click)="showTab('user-profile')">
|
|
<ng-icon name="lucideUser" class="fs-lg me-md-1 d-inline-flex align-middle" />
|
|
<span class="d-none d-md-inline-block align-middle">Profil Utilisateur</span>
|
|
</a>
|
|
<ng-template ngbNavContent>
|
|
@if (selectedUserId) {
|
|
<app-merchant-user-profile
|
|
[userId]="selectedUserId"
|
|
(resetPasswordRequested)="onResetPasswordRequested($event)"
|
|
(back)="backToList()"
|
|
/>
|
|
} @else {
|
|
<div class="alert alert-warning text-center">
|
|
<ng-icon name="lucideAlertCircle" class="me-2"></ng-icon>
|
|
Aucun utilisateur sélectionné
|
|
</div>
|
|
}
|
|
</ng-template>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="tab-content" [ngbNavOutlet]="usersNav"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal de création d'utilisateur Merchant -->
|
|
<ng-template #createUserModal let-modal>
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">
|
|
<ng-icon name="lucideUserPlus" class="me-2"></ng-icon>
|
|
Créer un nouvel utilisateur marchand
|
|
</h4>
|
|
<button
|
|
type="button"
|
|
class="btn-close"
|
|
(click)="modal.dismiss()"
|
|
[disabled]="creatingUser"
|
|
aria-label="Fermer"
|
|
></button>
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
<!-- Message d'erreur -->
|
|
@if (createUserError) {
|
|
<div class="alert alert-danger d-flex align-items-center">
|
|
<ng-icon name="lucideAlertCircle" class="me-2"></ng-icon>
|
|
<div>{{ createUserError }}</div>
|
|
</div>
|
|
}
|
|
|
|
<form (ngSubmit)="createUser()" #userForm="ngForm">
|
|
<div class="row g-3">
|
|
<!-- Pour les Hub Admin/Support : afficher la liste déroulante -->
|
|
<div *ngIf="isMerchantRole(newUser.role) && !(isMerchantUser && currentUserType === UserType.MERCHANT_PARTNER)" class="mb-3">
|
|
<label class="form-label">Merchant *</label>
|
|
|
|
<div *ngIf="loadingMerchantPartners" class="text-muted">
|
|
Chargement des merchants...
|
|
</div>
|
|
|
|
<div *ngIf="merchantPartnersError" class="alert alert-danger">
|
|
{{ merchantPartnersError }}
|
|
</div>
|
|
|
|
<select
|
|
class="form-select"
|
|
[(ngModel)]="selectedMerchantPartnerId"
|
|
(ngModelChange)="onMerchantSelected($event)"
|
|
[disabled]="loadingMerchantPartners"
|
|
name="merchantPartnerId">
|
|
<option value="">Sélectionner un merchant</option>
|
|
<option *ngFor="let merchant of merchantPartners" [value]="merchant.id">
|
|
{{ merchant.name }} ({{ merchant.id }})
|
|
</option>
|
|
</select>
|
|
|
|
<small class="form-text text-muted">
|
|
Sélectionnez le merchant auquel associer cet utilisateur
|
|
</small>
|
|
</div>
|
|
|
|
<!-- Pour les Merchant users : afficher un message informatif -->
|
|
<div *ngIf="isMerchantRole(newUser.role) && isMerchantUser && currentUserType === UserType.MERCHANT_PARTNER" class="alert alert-info">
|
|
<i class="bi bi-info-circle"></i>
|
|
<ng-container *ngIf="loadingMerchantPartners">
|
|
Chargement de votre merchant...
|
|
</ng-container>
|
|
<ng-container *ngIf="!loadingMerchantPartners && merchantPartnersError">
|
|
<span class="text-danger">{{ merchantPartnersError }}</span>
|
|
</ng-container>
|
|
<ng-container *ngIf="!loadingMerchantPartners && !merchantPartnersError">
|
|
Cet utilisateur sera automatiquement associé à votre merchant :
|
|
<strong>{{ getCurrentUserMerchantName() }}</strong>
|
|
</ng-container>
|
|
</div>
|
|
|
|
<!-- Informations de base -->
|
|
<div class="col-md-6">
|
|
<label class="form-label">
|
|
Prénom <span class="text-danger">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
placeholder="Entrez le prénom"
|
|
[(ngModel)]="newUser.firstName"
|
|
name="firstName"
|
|
required
|
|
[disabled]="creatingUser"
|
|
#firstName="ngModel"
|
|
>
|
|
@if (firstName.invalid && firstName.touched) {
|
|
<div class="text-danger small">
|
|
Le prénom est requis
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">
|
|
Nom <span class="text-danger">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
placeholder="Entrez le nom"
|
|
[(ngModel)]="newUser.lastName"
|
|
name="lastName"
|
|
required
|
|
[disabled]="creatingUser"
|
|
#lastName="ngModel"
|
|
>
|
|
@if (lastName.invalid && lastName.touched) {
|
|
<div class="text-danger small">
|
|
Le nom est requis
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">
|
|
Nom d'utilisateur <span class="text-danger">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
placeholder="Nom d'utilisateur unique"
|
|
[(ngModel)]="newUser.username"
|
|
name="username"
|
|
required
|
|
[disabled]="creatingUser"
|
|
#username="ngModel"
|
|
>
|
|
<div class="form-text">Doit être unique dans le système</div>
|
|
@if (username.invalid && username.touched) {
|
|
<div class="text-danger small">
|
|
Le nom d'utilisateur est requis
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">
|
|
Email <span class="text-danger">*</span>
|
|
</label>
|
|
<input
|
|
type="email"
|
|
class="form-control"
|
|
placeholder="email@exemple.com"
|
|
[(ngModel)]="newUser.email"
|
|
name="email"
|
|
required
|
|
email
|
|
[disabled]="creatingUser"
|
|
#email="ngModel"
|
|
>
|
|
@if (email.invalid && email.touched) {
|
|
<div class="text-danger small">
|
|
@if (email.errors?.['required']) {
|
|
L'email est requis
|
|
}
|
|
@if (email.errors?.['email']) {
|
|
Format d'email invalide
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<label class="form-label">
|
|
Mot de passe <span class="text-danger">*</span>
|
|
</label>
|
|
<div class="input-group">
|
|
<input
|
|
[type]="showPassword ? 'text' : 'password'"
|
|
class="form-control"
|
|
placeholder="Mot de passe sécurisé"
|
|
[(ngModel)]="newUser.password"
|
|
name="password"
|
|
required
|
|
minlength="8"
|
|
[disabled]="creatingUser"
|
|
#password="ngModel"
|
|
>
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
(click)="showPassword = !showPassword"
|
|
[disabled]="creatingUser"
|
|
>
|
|
<ng-icon [name]="showPassword ? 'lucideEyeOff' : 'lucideEye'"></ng-icon>
|
|
</button>
|
|
</div>
|
|
<div class="form-text">
|
|
Le mot de passe doit contenir au moins 8 caractères.
|
|
</div>
|
|
@if (password.invalid && password.touched) {
|
|
<div class="text-danger small">
|
|
@if (password.errors?.['required']) {
|
|
Le mot de passe est requis
|
|
}
|
|
@if (password.errors?.['minlength']) {
|
|
Le mot de passe doit contenir au moins 8 caractères
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<!-- Sélection du rôle unique -->
|
|
<div class="col-12">
|
|
<label class="form-label">
|
|
Rôle Principal <span class="text-danger">*</span>
|
|
</label>
|
|
<select
|
|
class="form-select"
|
|
[value]="newUser.role"
|
|
(change)="onRoleSelectionChange($any($event.target).value)"
|
|
name="role"
|
|
required
|
|
[disabled]="creatingUser"
|
|
>
|
|
<option value="" >Sélectionnez un rôle</option>
|
|
@for (role of availableRoles; track role.value) {
|
|
<option
|
|
[value]="role.value"
|
|
>
|
|
{{ role.label }} - {{ role.description }}
|
|
</option>
|
|
}
|
|
</select>
|
|
<div class="form-text">
|
|
Sélectionnez le rôle principal à assigner à cet utilisateur
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Type d'utilisateur automatique -->
|
|
<div class="col-12">
|
|
<label class="form-label">Type d'utilisateur</label>
|
|
<div class="form-control-plaintext">
|
|
<span class="badge bg-success">
|
|
Utilisateur Marchand
|
|
</span>
|
|
</div>
|
|
<div class="form-text">
|
|
Tous les utilisateurs créés ici sont des utilisateurs Marchands
|
|
</div>
|
|
</div>
|
|
|
|
@if (newUser.role) {
|
|
<div class="col-12">
|
|
<div class="alert alert-info">
|
|
<div class="d-flex align-items-center">
|
|
<ng-icon
|
|
[name]="getRoleIcon(newUser.role)"
|
|
class="me-2"
|
|
></ng-icon>
|
|
<div>
|
|
<strong>Rôle sélectionné :</strong>
|
|
<span class="badge ms-2" [ngClass]="getRoleBadgeClass(newUser.role)">
|
|
{{ getRoleLabel(newUser.role) }}
|
|
</span>
|
|
<br>
|
|
<small class="text-muted">
|
|
{{ getRoleDescription(newUser.role) }}
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- Configuration du compte -->
|
|
<div class="col-md-6">
|
|
<div class="form-check form-switch">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="enabledSwitch"
|
|
[(ngModel)]="newUser.enabled"
|
|
name="enabled"
|
|
[disabled]="creatingUser"
|
|
checked
|
|
>
|
|
<label class="form-check-label" for="enabledSwitch">
|
|
Compte activé
|
|
</label>
|
|
</div>
|
|
<div class="form-text">L'utilisateur peut se connecter immédiatement</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="form-check form-switch">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="emailVerifiedSwitch"
|
|
[(ngModel)]="newUser.emailVerified"
|
|
name="emailVerified"
|
|
[disabled]="creatingUser"
|
|
>
|
|
<label class="form-check-label" for="emailVerifiedSwitch">
|
|
Email vérifié
|
|
</label>
|
|
</div>
|
|
<div class="form-text">L'utilisateur n'aura pas à vérifier son email</div>
|
|
</div>
|
|
|
|
<!-- Informations système (lecture seule) -->
|
|
<div class="col-12">
|
|
<div class="alert alert-light">
|
|
<small class="text-muted">
|
|
<strong>Informations système :</strong><br>
|
|
• Type d'utilisateur : MERCHANT<br>
|
|
• Créé par : Utilisateur courant<br>
|
|
• Votre rôle : {{ currentUserRole || 'Non défini' }}
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-footer mt-4">
|
|
<button
|
|
type="button"
|
|
class="btn btn-light"
|
|
(click)="modal.dismiss()"
|
|
[disabled]="creatingUser"
|
|
>
|
|
<ng-icon name="lucideX" class="me-1"></ng-icon>
|
|
Annuler
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
class="btn btn-primary"
|
|
[disabled]="!userForm.form.valid || creatingUser"
|
|
>
|
|
@if (creatingUser) {
|
|
<div class="spinner-border spinner-border-sm me-2" role="status">
|
|
<span class="visually-hidden">Chargement...</span>
|
|
</div>
|
|
Création...
|
|
} @else {
|
|
<ng-icon name="lucideUserPlus" class="me-1"></ng-icon>
|
|
Créer l'utilisateur Marchand
|
|
}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</ng-template>
|
|
|
|
|
|
<!-- Modal de réinitialisation de mot de passe -->
|
|
<ng-template #resetPasswordModal let-modal>
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">
|
|
<ng-icon name="lucideKey" class="me-2"></ng-icon>
|
|
Réinitialiser le mot de passe
|
|
</h4>
|
|
<button
|
|
type="button"
|
|
class="btn-close"
|
|
(click)="modal.dismiss()"
|
|
[disabled]="resettingPassword"
|
|
aria-label="Fermer"
|
|
></button>
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
<!-- Message de succès -->
|
|
@if (resetPasswordSuccess) {
|
|
<div class="alert alert-success d-flex align-items-center">
|
|
<ng-icon name="lucideCheckCircle" class="me-2"></ng-icon>
|
|
<div>{{ resetPasswordSuccess }}</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- Message d'erreur -->
|
|
@if (resetPasswordError) {
|
|
<div class="alert alert-danger d-flex align-items-center">
|
|
<ng-icon name="lucideAlertCircle" class="me-2"></ng-icon>
|
|
<div>{{ resetPasswordError }}</div>
|
|
</div>
|
|
}
|
|
|
|
@if (!resetPasswordSuccess && selectedUserForReset) {
|
|
<div class="alert alert-info">
|
|
<div class="d-flex align-items-center">
|
|
<div class="avatar-sm bg-primary bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center me-3">
|
|
<span class="text-primary fw-bold">{{ getUserInitials(selectedUserForReset) }}</span>
|
|
</div>
|
|
<div>
|
|
<strong>{{ selectedUserForReset.username }}</strong>
|
|
@if (selectedUserForReset.firstName || selectedUserForReset.lastName) {
|
|
<br>
|
|
{{ selectedUserForReset.firstName }} {{ selectedUserForReset.lastName }}
|
|
}
|
|
<br>
|
|
<small class="text-muted">
|
|
<span class="badge" [ngClass]="getRoleBadgeClass(selectedUserForReset.role)">
|
|
{{ getRoleLabel(selectedUserForReset.role) }}
|
|
</span>
|
|
• Type: Hub
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<form (ngSubmit)="confirmResetPassword()" #resetForm="ngForm">
|
|
<div class="mb-3">
|
|
<label class="form-label">
|
|
Nouveau mot de passe <span class="text-danger">*</span>
|
|
</label>
|
|
<div class="input-group">
|
|
<input
|
|
[type]="showNewPassword ? 'text' : 'password'"
|
|
class="form-control"
|
|
placeholder="Entrez le nouveau mot de passe"
|
|
[(ngModel)]="newPassword"
|
|
name="newPassword"
|
|
required
|
|
minlength="8"
|
|
[disabled]="resettingPassword"
|
|
#newPasswordInput="ngModel"
|
|
>
|
|
<button
|
|
type="button"
|
|
class="btn btn-outline-secondary"
|
|
(click)="showNewPassword = !showNewPassword"
|
|
[disabled]="resettingPassword"
|
|
>
|
|
<ng-icon [name]="showNewPassword ? 'lucideEyeOff' : 'lucideEye'"></ng-icon>
|
|
</button>
|
|
</div>
|
|
<div class="form-text">
|
|
Le mot de passe doit contenir au moins 8 caractères.
|
|
</div>
|
|
@if (newPasswordInput.invalid && newPasswordInput.touched) {
|
|
<div class="text-danger small">
|
|
@if (newPasswordInput.errors?.['required']) {
|
|
Le mot de passe est requis
|
|
}
|
|
@if (newPasswordInput.errors?.['minlength']) {
|
|
Le mot de passe doit contenir au moins 8 caractères
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input
|
|
class="form-check-input"
|
|
type="checkbox"
|
|
id="temporaryPassword"
|
|
[(ngModel)]="temporaryPassword"
|
|
name="temporaryPassword"
|
|
[disabled]="resettingPassword"
|
|
checked
|
|
>
|
|
<label class="form-check-label" for="temporaryPassword">
|
|
Mot de passe temporaire
|
|
</label>
|
|
</div>
|
|
<div class="form-text">
|
|
L'utilisateur devra changer son mot de passe à la prochaine connexion.
|
|
</div>
|
|
</div>
|
|
</form>
|
|
} @else if (!selectedUserForReset) {
|
|
<div class="alert alert-warning text-center">
|
|
<ng-icon name="lucideAlertTriangle" class="me-2"></ng-icon>
|
|
Aucun utilisateur sélectionné pour la réinitialisation
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
@if (resetPasswordSuccess) {
|
|
<button
|
|
type="button"
|
|
class="btn btn-success"
|
|
(click)="modal.close()"
|
|
>
|
|
<ng-icon name="lucideCheck" class="me-1"></ng-icon>
|
|
Fermer
|
|
</button>
|
|
} @else {
|
|
<button
|
|
type="button"
|
|
class="btn btn-light"
|
|
(click)="modal.dismiss()"
|
|
[disabled]="resettingPassword"
|
|
>
|
|
Annuler
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="btn btn-primary"
|
|
(click)="confirmResetPassword()"
|
|
[disabled]="!newPassword || newPassword.length < 8 || resettingPassword || !selectedUserForReset"
|
|
>
|
|
@if (resettingPassword) {
|
|
<div class="spinner-border spinner-border-sm me-2" role="status">
|
|
<span class="visually-hidden">Chargement...</span>
|
|
</div>
|
|
Réinitialisation...
|
|
} @else {
|
|
<ng-icon name="lucideKey" class="me-1"></ng-icon>
|
|
Réinitialiser le mot de passe
|
|
}
|
|
</button>
|
|
}
|
|
</div>
|
|
</ng-template>
|
|
|
|
<!-- Modal de confirmation de suppression -->
|
|
<ng-template #deleteUserModal let-modal>
|
|
<div class="modal-header">
|
|
<h4 class="modal-title text-danger">
|
|
<ng-icon name="lucideTrash2" class="me-2"></ng-icon>
|
|
Confirmer la suppression
|
|
</h4>
|
|
<button
|
|
type="button"
|
|
class="btn-close"
|
|
(click)="modal.dismiss()"
|
|
aria-label="Fermer"
|
|
></button>
|
|
</div>
|
|
|
|
<div class="modal-body text-center">
|
|
<div class="mb-4">
|
|
<div class="avatar-lg mx-auto mb-3 bg-danger bg-opacity-10 rounded-circle d-flex align-items-center justify-content-center">
|
|
<ng-icon name="lucideUserX" class="text-danger" style="font-size: 2rem;"></ng-icon>
|
|
</div>
|
|
<h5 class="text-danger mb-2">Êtes-vous sûr de vouloir supprimer cet utilisateur Hub ?</h5>
|
|
<p class="text-muted mb-0">
|
|
Cette action est irréversible. Toutes les données de
|
|
@if (selectedUserForDelete) {
|
|
<strong>{{ selectedUserForDelete.username }}</strong>
|
|
}
|
|
seront définitivement perdues.
|
|
</p>
|
|
</div>
|
|
|
|
@if (selectedUserForDelete) {
|
|
<div class="alert alert-warning">
|
|
<div class="d-flex align-items-start">
|
|
<ng-icon name="lucideAlertTriangle" class="me-2 mt-1 text-warning"></ng-icon>
|
|
<div>
|
|
<strong>Utilisateur :</strong> {{ selectedUserForDelete.username }}
|
|
@if (selectedUserForDelete.firstName || selectedUserForDelete.lastName) {
|
|
<br>
|
|
<strong>Nom :</strong> {{ selectedUserForDelete.firstName }} {{ selectedUserForDelete.lastName }}
|
|
}
|
|
<br>
|
|
<strong>Email :</strong> {{ selectedUserForDelete.email }}
|
|
<br>
|
|
<strong>Rôle Principal :</strong>
|
|
<span class="badge" [ngClass]="getRoleBadgeClass(selectedUserForDelete.role)">
|
|
{{ getRoleLabel(selectedUserForDelete.role) }}
|
|
</span>
|
|
@if (selectedUserForDelete.role && selectedUserForDelete.role.length > 1) {
|
|
<br>
|
|
<strong>Rôles supplémentaires :</strong>
|
|
{{ selectedUserForDelete.role.length - 1 }}
|
|
}
|
|
<br>
|
|
<strong>Type :</strong> Utilisateur Hub
|
|
</div>
|
|
</div>
|
|
</div>
|
|
} @else {
|
|
<div class="alert alert-warning">
|
|
<ng-icon name="lucideAlertCircle" class="me-2"></ng-icon>
|
|
Aucun utilisateur sélectionné pour la suppression
|
|
</div>
|
|
}
|
|
|
|
<!-- Message d'erreur -->
|
|
@if (deleteUserError) {
|
|
<div class="alert alert-danger d-flex align-items-center">
|
|
<ng-icon name="lucideAlertCircle" class="me-2"></ng-icon>
|
|
<div>{{ deleteUserError }}</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button
|
|
type="button"
|
|
class="btn btn-light"
|
|
(click)="modal.dismiss()"
|
|
[disabled]="deletingUser"
|
|
>
|
|
<ng-icon name="lucideX" class="me-1"></ng-icon>
|
|
Annuler
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="btn btn-danger"
|
|
(click)="confirmDeleteUser()"
|
|
[disabled]="deletingUser || !selectedUserForDelete || !canDeleteUsers"
|
|
>
|
|
@if (deletingUser) {
|
|
<div class="spinner-border spinner-border-sm me-2" role="status">
|
|
<span class="visually-hidden">Suppression...</span>
|
|
</div>
|
|
Suppression...
|
|
} @else {
|
|
<ng-icon name="lucideTrash2" class="me-1"></ng-icon>
|
|
Supprimer définitivement
|
|
}
|
|
</button>
|
|
</div>
|
|
</ng-template> |