Admin mode. Data driven content sections. Bugfixes.

This commit is contained in:
2026-06-19 17:36:35 +00:00
parent bd65455945
commit 266c2451f1
30 changed files with 1733 additions and 13 deletions
+166
View File
@@ -0,0 +1,166 @@
import { Component, inject, signal, OnInit } from '@angular/core';
import { CommonModule, AsyncPipe } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { Program } from '../interfaces/program';
import { Event } from '../interfaces/event';
import { Tier } from '../interfaces/tier';
import { ProgramService } from '../services/program.service';
import { EventService } from '../services/event.service';
import { TierService } from '../services/tier.service';
import { AdminProgramFormComponent } from './admin-program-form.component';
import { AdminEventFormComponent } from './admin-event-form.component';
import { AdminTierFormComponent } from './admin-tier-form.component';
type TabKey = 'programs' | 'events' | 'tiers';
@Component({
selector: 'app-admin',
standalone: true,
imports: [
CommonModule,
AsyncPipe,
FormsModule,
AdminProgramFormComponent,
AdminEventFormComponent,
AdminTierFormComponent,
],
templateUrl: './admin.component.html',
styleUrl: './admin.component.scss',
})
export class AdminComponent implements OnInit {
private programService = inject(ProgramService);
private eventService = inject(EventService);
private tierService = inject(TierService);
activeTab = signal<TabKey>('programs');
/** Item currently being edited (set by editXxx, cleared on save/close). */
editingProgram: Program | null = null;
editingEvent: Event | null = null;
editingTier: Tier | null = null;
/** BehaviorSubjects guarantee change detection via the async pipe — start empty, populated on load. */
readonly programs$ = new BehaviorSubject<Program[]>([]);
readonly events$ = new BehaviorSubject<Event[]>([]);
readonly tiers$ = new BehaviorSubject<Tier[]>([]);
showProgramForm = false;
showEventForm = false;
showTierForm = false;
ngOnInit(): void {
this.loadAll();
}
async reloadPrograms(): Promise<void> {
const data = await firstValueFrom(this.programService.getPrograms());
this.programs$.next(data);
}
async reloadEvents(): Promise<void> {
const data = await firstValueFrom(this.eventService.getEvents());
this.events$.next(data);
}
async reloadTiers(): Promise<void> {
const data = await firstValueFrom(this.tierService.getTiers());
this.tiers$.next(data);
}
async loadAll(): Promise<void> {
await Promise.all([
this.reloadPrograms(),
this.reloadEvents(),
this.reloadTiers(),
]);
}
// ── Program CRUD ────────────────────────────────────────
openProgramForm(): void {
this.editingProgram = null;
this.showProgramForm = true;
}
editProgram(program: Program): void {
this.editingProgram = program;
this.showProgramForm = true;
}
onProgramSaved(): void {
this.reloadPrograms();
this.showProgramForm = false;
this.editingProgram = null;
}
onProgramClosed(): void {
this.showProgramForm = false;
this.editingProgram = null;
}
async deleteProgram(id: number): Promise<void> {
if (!confirm('Delete this program?')) return;
await firstValueFrom(this.programService.deleteProgram(id));
await this.reloadPrograms();
}
// ── Event CRUD ──────────────────────────────────────────
openEventForm(): void {
this.editingEvent = null;
this.showEventForm = true;
}
editEvent(event: Event): void {
this.editingEvent = event;
this.showEventForm = true;
}
onEventSaved(): void {
this.reloadEvents();
this.showEventForm = false;
this.editingEvent = null;
}
onEventClosed(): void {
this.showEventForm = false;
this.editingEvent = null;
}
async deleteEvent(id: number): Promise<void> {
if (!confirm('Delete this event?')) return;
await firstValueFrom(this.eventService.deleteEvent(id));
await this.reloadEvents();
}
// ── Tier CRUD ───────────────────────────────────────────
openTierForm(): void {
this.editingTier = null;
this.showTierForm = true;
}
editTier(tier: Tier): void {
this.editingTier = tier;
this.showTierForm = true;
}
onTierSaved(): void {
this.reloadTiers();
this.showTierForm = false;
this.editingTier = null;
}
onTierClosed(): void {
this.showTierForm = false;
this.editingTier = null;
}
async deleteTier(id: number): Promise<void> {
if (!confirm('Delete this tier?')) return;
await firstValueFrom(this.tierService.deleteTier(id));
await this.reloadTiers();
}
}