162 lines
6.1 KiB
HTML
162 lines
6.1 KiB
HTML
<main class="users-page">
|
|
<a mat-button routerLink="/" class="back-link"><mat-icon>arrow_back</mat-icon>Zurück</a>
|
|
<header class="page-header">
|
|
<p class="eyebrow">Organisation</p>
|
|
<h1>Benutzer</h1>
|
|
<p>Konten und sichtbare Teamzuordnungen im Überblick.</p>
|
|
</header>
|
|
|
|
<form class="directory-search" (submit)="submitSearch(); $event.preventDefault()" role="search">
|
|
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
<mat-label>Benutzer suchen</mat-label>
|
|
<mat-icon matPrefix>search</mat-icon>
|
|
<input
|
|
matInput
|
|
type="search"
|
|
name="directorySearch"
|
|
[value]="searchDraft()"
|
|
[disabled]="assignmentBusyUserId() !== null"
|
|
(input)="searchDraft.set($any($event.target).value)"
|
|
/>
|
|
</mat-form-field>
|
|
<button mat-stroked-button type="submit" [disabled]="loading() || assignmentBusyUserId() !== null">Suchen</button>
|
|
</form>
|
|
|
|
@if (mutationError()) {
|
|
<div class="message message--error" role="alert">{{ mutationError() }}</div>
|
|
}
|
|
|
|
@if (loading()) {
|
|
<div class="page-state" aria-live="polite">
|
|
<mat-spinner diameter="36" />
|
|
<span>Benutzer werden geladen …</span>
|
|
</div>
|
|
} @else if (loadError()) {
|
|
<div class="page-state page-state--error" role="alert">
|
|
<mat-icon>error_outline</mat-icon>
|
|
<strong>{{ loadError() }}</strong>
|
|
<button mat-stroked-button type="button" (click)="loadDirectory()">Erneut versuchen</button>
|
|
</div>
|
|
} @else if (directory()?.data?.length === 0) {
|
|
<div class="page-state">
|
|
<mat-icon>group_off</mat-icon>
|
|
<strong>Keine Benutzer gefunden</strong>
|
|
<span>Versuche einen anderen Suchbegriff.</span>
|
|
</div>
|
|
} @else if (directory()) {
|
|
<div class="directory" aria-live="polite">
|
|
@for (user of directory()!.data; track user.id) {
|
|
<article
|
|
class="user-row"
|
|
[attr.data-user-id]="user.id"
|
|
[attr.aria-busy]="pendingUserId() === user.id ? 'true' : null"
|
|
[class.user-row--inactive]="user.status?.id === 2"
|
|
>
|
|
<div class="user-row__summary">
|
|
<div class="avatar" aria-hidden="true">{{ initials(user) }}</div>
|
|
<div class="user-row__identity">
|
|
<div class="user-row__name">
|
|
<h2>{{ fullName(user) }}</h2>
|
|
<span class="status" [class.status--inactive]="user.status?.id === 2">
|
|
{{ statusName(user.status?.id) }}
|
|
</span>
|
|
</div>
|
|
@if (adminDetails(user); as details) {
|
|
<span>{{ details.email ?? 'Keine E-Mail' }} · {{ roleName(details.role?.id) }}</span>
|
|
}
|
|
@if (user.assignments.length === 0) {
|
|
<span>Keine Spielerzuordnung sichtbar</span>
|
|
} @else {
|
|
<div class="assignment-summary">
|
|
@for (assignment of user.assignments; track assignment.id) {
|
|
<span>
|
|
{{ assignment.team.name }} · {{ assignment.firstName }} {{ assignment.lastName }} ·
|
|
{{ teamRoleName(assignment.teamRole?.name) }}
|
|
@if (!assignment.active) { · Inaktiv }
|
|
</span>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@if (adminDetails(user); as details) {
|
|
<div class="user-row__actions">
|
|
<button mat-button type="button" [disabled]="assignmentBusyUserId() !== null" (click)="toggleEdit(user.id)">
|
|
Bearbeiten
|
|
</button>
|
|
<button
|
|
mat-button
|
|
type="button"
|
|
[disabled]="assignmentBusyUserId() !== null"
|
|
(click)="toggleAssignments(user.id)"
|
|
>
|
|
Zuordnungen verwalten
|
|
</button>
|
|
<button
|
|
mat-stroked-button
|
|
type="button"
|
|
[disabled]="isSelf(user) || pendingUserId() !== null"
|
|
[attr.title]="isSelf(user) ? 'Das eigene Konto kann nicht deaktiviert werden.' : null"
|
|
[attr.aria-describedby]="isSelf(user) ? 'self-status-note-' + user.id : null"
|
|
(click)="changeStatus(details)"
|
|
>
|
|
{{
|
|
pendingUserId() === user.id
|
|
? 'Status wird geändert …'
|
|
: user.status?.id === 2
|
|
? 'Aktivieren'
|
|
: 'Deaktivieren'
|
|
}}
|
|
</button>
|
|
</div>
|
|
@if (isSelf(user)) {
|
|
<p class="self-status-note" [id]="'self-status-note-' + user.id">
|
|
Das eigene Konto kann nicht deaktiviert werden.
|
|
</p>
|
|
}
|
|
|
|
@if (editingUserId() === user.id) {
|
|
<app-user-edit
|
|
[user]="details"
|
|
[self]="isSelf(user)"
|
|
[saving]="pendingUserId() === user.id"
|
|
(saved)="saveEdit(details, $event)"
|
|
(cancel)="editingUserId.set(null)"
|
|
/>
|
|
}
|
|
@if (assignmentUserId() === user.id) {
|
|
<app-player-assignments
|
|
[user]="details"
|
|
(directoryChanged)="assignmentsChanged()"
|
|
(closed)="assignmentUserId.set(null)"
|
|
(busyChange)="assignmentBusyChanged(user.id, $event)"
|
|
/>
|
|
}
|
|
}
|
|
</article>
|
|
}
|
|
</div>
|
|
|
|
<nav class="pagination" aria-label="Benutzerseiten">
|
|
<button
|
|
mat-button
|
|
type="button"
|
|
[disabled]="directory()!.page <= 1 || loading() || assignmentBusyUserId() !== null"
|
|
(click)="previousPage()"
|
|
>
|
|
<mat-icon>chevron_left</mat-icon>Zurück
|
|
</button>
|
|
<span>Seite {{ directory()!.page }} · {{ directory()!.total }} Benutzer</span>
|
|
<button
|
|
mat-button
|
|
type="button"
|
|
[disabled]="!directory()!.hasNextPage || loading() || assignmentBusyUserId() !== null"
|
|
(click)="nextPage()"
|
|
>
|
|
Weiter<mat-icon>chevron_right</mat-icon>
|
|
</button>
|
|
</nav>
|
|
}
|
|
</main>
|