eeg_portal/eeg_frontend/src/app/pages/admin-memberships/admin-memberships.ts
Bernhard Müller c66c5fddfa feat(community): add complete membership flow with unit tests
Backend:
- Add MembershipResponse and PendingMembershipResponse DTOs
- Add GET /memberships/me and GET /admin/memberships/pending endpoints
- Add findByUserIdWithDetails and findPendingWithDetails queries
- Add getOwnMemberships and getPendingMemberships service methods

Frontend:
- Add membership service for API calls
- Add join-community page for users to browse and join communities
- Add my-memberships page for users to view their memberships
- Add admin-memberships page for admins to approve/reject requests
- Add routes and navigation items

Tests:
- Add MembershipServiceTest with 13 unit tests
- All 20 tests passing (UserServiceTest + MembershipServiceTest)
2026-07-21 12:42:07 +02:00

69 lines
2.0 KiB
TypeScript

import {Component, inject, OnInit, signal} from '@angular/core';
import {MembershipService, PendingMembershipResponse} from '../../services/membership';
import {ToastService} from '../../services/toast';
@Component({
selector: 'app-admin-memberships',
standalone: true,
templateUrl: './admin-memberships.html'
})
export class AdminMembershipsComponent implements OnInit {
private membershipService = inject(MembershipService);
private toastService = inject(ToastService);
pendingMemberships = signal<PendingMembershipResponse[]>([]);
isLoading = signal(true);
isProcessing = signal<string | null>(null);
ngOnInit() {
this.loadPendingMemberships();
}
loadPendingMemberships() {
this.membershipService.getPendingMemberships().subscribe({
next: memberships => {
this.pendingMemberships.set(memberships);
this.isLoading.set(false);
},
error: () => {
this.isLoading.set(false);
this.toastService.error('Fehler beim Laden der wartenden Anträge.');
}
});
}
approveMembership(id: string) {
if (this.isProcessing()) return;
this.isProcessing.set(id);
this.membershipService.approveMembership(id).subscribe({
next: () => {
this.toastService.success('Mitgliedschaft genehmigt.');
this.loadPendingMemberships();
this.isProcessing.set(null);
},
error: (err) => {
this.isProcessing.set(null);
this.toastService.error(err.error?.message || 'Fehler bei der Genehmigung.');
}
});
}
rejectMembership(id: string) {
if (this.isProcessing()) return;
this.isProcessing.set(id);
this.membershipService.rejectMembership(id).subscribe({
next: () => {
this.toastService.success('Mitgliedschaft abgelehnt.');
this.loadPendingMemberships();
this.isProcessing.set(null);
},
error: (err) => {
this.isProcessing.set(null);
this.toastService.error(err.error?.message || 'Fehler bei der Ablehnung.');
}
});
}
}