Files
marketplaces/src/app/features/admin/users/facade/admin-users.facade.ts
sdarbinyan 23d9f2f66f refactor: rename duplicate AdminRole interface, type sellerId as UUID
AdminRole was defined twice with unrelated shapes (core/auth's real
JWT role union vs. the Users admin page's display interface), flagged
in BACKEND-API-REFERENCE.md \u00a72b as needing a rename. Renamed the
Users-page one to AdminUserRoleRecord.

sellerId was bare string in admin-order/admin-product/item models
while core/sellers/models/seller-scope.model.ts already used the
shared UUID alias. Aligned all three to UUID for consistency (UUID is
currently just = string, so this is a documentation-level type change,
not a behavior change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 11:16:16 +04:00

92 lines
3.3 KiB
TypeScript

import { Injectable, inject, signal } from '@angular/core';
import { take } from 'rxjs/operators';
import { AdminInvitation, AdminUserRoleRecord, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
import { AdminUsersLocalGateway } from '../services/admin-users-local.gateway';
@Injectable({ providedIn: 'root' })
export class AdminUsersFacade {
private readonly gateway = inject(AdminUsersLocalGateway);
readonly users = signal<AdminUser[]>([]);
readonly roles = signal<AdminUserRoleRecord[]>([]);
readonly invitations = signal<AdminInvitation[]>([]);
readonly loading = signal(false);
readonly error = signal(false);
readonly mutationError = signal<string | null>(null);
readonly sessionsTarget = signal<AdminUser | null>(null);
readonly sessions = signal<AdminSession[]>([]);
readonly auditTarget = signal<AdminUser | null>(null);
readonly audit = signal<AdminUserAuditEntry[]>([]);
loadAll(): void {
this.loading.set(true);
this.error.set(false);
this.gateway.loadUsers().pipe(take(1)).subscribe({
next: users => { this.users.set(users); this.loading.set(false); },
error: () => { this.users.set([]); this.loading.set(false); this.error.set(true); }
});
this.gateway.loadRoles().pipe(take(1)).subscribe(roles => this.roles.set(roles));
this.gateway.loadInvitations().pipe(take(1)).subscribe(invitations => this.invitations.set(invitations));
}
roleName(roleId: string): string {
return this.roles().find(role => role.id === roleId)?.name ?? roleId;
}
setRole(userId: string, roleId: string): void {
this.mutationError.set(null);
this.gateway.setUserRole(userId, roleId).pipe(take(1)).subscribe({
next: () => this.loadAll(),
error: () => this.mutationError.set('common.errorDescription')
});
}
setStatus(userId: string, status: AdminUserStatus): void {
this.mutationError.set(null);
this.gateway.setUserStatus(userId, status).pipe(take(1)).subscribe({
next: () => this.loadAll(),
error: () => this.mutationError.set('common.errorDescription')
});
}
invite(email: string, roleId: string, scope: AdminUserScope): void {
if (!email.trim()) return;
this.mutationError.set(null);
this.gateway.inviteUser(email.trim(), roleId, scope).pipe(take(1)).subscribe({
next: () => this.loadAll(),
error: () => this.mutationError.set('common.errorDescription')
});
}
revokeInvitation(id: string): void {
this.gateway.revokeInvitation(id).pipe(take(1)).subscribe({ next: () => this.loadAll() });
}
openSessions(user: AdminUser): void {
this.sessionsTarget.set(user);
this.gateway.loadSessions(user.id).pipe(take(1)).subscribe(sessions => this.sessions.set(sessions));
}
closeSessions(): void {
this.sessionsTarget.set(null);
}
revokeSession(sessionId: string): void {
this.gateway.revokeSession(sessionId).pipe(take(1)).subscribe({
next: () => {
const user = this.sessionsTarget();
if (user) this.openSessions(user);
}
});
}
openAudit(user: AdminUser): void {
this.auditTarget.set(user);
this.gateway.loadAudit(user.id).pipe(take(1)).subscribe(entries => this.audit.set(entries));
}
closeAudit(): void {
this.auditTarget.set(null);
}
}