97 lines
3.5 KiB
TypeScript
97 lines
3.5 KiB
TypeScript
import {
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
HostListener,
|
|
input,
|
|
output,
|
|
} from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { AdminUser } from '../../core/services/admin.service';
|
|
|
|
@Component({
|
|
selector: 'app-player-delete-modal',
|
|
standalone: true,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
imports: [CommonModule],
|
|
styles: [`
|
|
.modal-overlay {
|
|
position: fixed; inset: 0; background: rgba(0, 0, 0, 0.9);
|
|
backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1200; padding: 16px;
|
|
}
|
|
.modal {
|
|
background: #000000; color: #ffffff; border: 3px solid var(--neon-red);
|
|
padding: 24px; width: min(420px, 92vw);
|
|
box-shadow: 0 10px 40px rgba(0,0,0,0.9), 0 0 25px rgba(255, 0, 51, 0.35);
|
|
font-family: var(--font-mono);
|
|
}
|
|
h3 {
|
|
font-family: var(--font-heading, 'Chakra Petch', sans-serif);
|
|
font-size: 1.5rem; font-weight: 900; font-style: italic; text-transform: uppercase;
|
|
color: #ffffff; margin-bottom: 14px;
|
|
}
|
|
p { font-size: 0.95rem; color: #ddddee; margin-bottom: 16px; }
|
|
.actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 16px; }
|
|
.btn-cancel {
|
|
background: #000000; color: var(--neon-purple); border: 2px solid var(--neon-purple);
|
|
font-family: var(--font-mono); font-weight: 800; padding: 10px 20px; cursor: pointer;
|
|
}
|
|
.btn-cancel:hover { background: var(--neon-purple); color: #000000; }
|
|
.btn-ok {
|
|
background: var(--neon-red); color: #000000; border: 2px solid var(--neon-red);
|
|
font-family: var(--font-mono); font-weight: 800; padding: 10px 20px; cursor: pointer;
|
|
}
|
|
.btn-ok:hover:not([disabled]) { background: #000000; color: var(--neon-red); box-shadow: 0 0 15px rgba(255, 0, 51, 0.4); }
|
|
.error { color: var(--neon-red); margin-top: 8px; font-weight: bold; }
|
|
`],
|
|
template: `
|
|
@if (open()) {
|
|
<div class="modal-overlay" data-testid="player-delete-overlay" (click)="onCancel()">
|
|
<div
|
|
class="modal"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="pd-title"
|
|
data-testid="player-delete-modal"
|
|
(click)="$event.stopPropagation()"
|
|
>
|
|
<h3 id="pd-title">DELETE USER</h3>
|
|
<p>Delete this user? All associated activity will be permanently wiped.</p>
|
|
@if (errorMessage(); as msg) {
|
|
<p class="error" role="alert" data-testid="player-delete-error">{{ msg }}</p>
|
|
}
|
|
<div class="actions">
|
|
<button type="button" class="btn-cancel" (click)="onCancel()" [disabled]="submitting()" data-testid="player-delete-cancel">CANCEL</button>
|
|
<button type="button" class="btn-ok" (click)="onConfirm()" [disabled]="submitting()" data-testid="player-delete-ok">
|
|
{{ submitting() ? 'DELETING...' : 'DELETE USER' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
`,
|
|
})
|
|
export class PlayerDeleteModalComponent {
|
|
readonly open = input(false);
|
|
readonly user = input<AdminUser | null>(null);
|
|
readonly errorMessage = input<string | null>(null);
|
|
readonly submitting = input(false);
|
|
|
|
readonly cancel = output<void>();
|
|
readonly confirm = output<void>();
|
|
|
|
@HostListener('document:keydown.escape')
|
|
onEscape(): void {
|
|
if (this.open() && !this.submitting()) this.onCancel();
|
|
}
|
|
|
|
onCancel(): void {
|
|
if (this.submitting()) return;
|
|
this.cancel.emit();
|
|
}
|
|
|
|
onConfirm(): void {
|
|
if (this.submitting()) return;
|
|
this.confirm.emit();
|
|
}
|
|
}
|