New programming screen

This commit is contained in:
2026-06-21 21:55:55 +00:00
parent 96d0fef792
commit e627fe3637
24 changed files with 1297 additions and 122 deletions
+153
View File
@@ -0,0 +1,153 @@
import { Component, EventEmitter, inject, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { firstValueFrom } from 'rxjs';
import { Show } from '../interfaces/show';
import { ShowService, ShowScheduleCreate, ShowCreatePayload, ShowUpdatePayload } from '../services/show.service';
@Component({
selector: 'app-admin-show-form',
standalone: true,
imports: [CommonModule, FormsModule],
templateUrl: './admin-show-form.component.html',
styleUrl: './admin-show-form.component.scss',
})
export class AdminShowFormComponent implements OnChanges {
private showService = inject(ShowService);
@Input() editItem: Show | null = null;
@Output() saved = new EventEmitter<void>();
@Output() closed = new EventEmitter<void>();
readonly days = [
{ value: 1, label: 'Monday' },
{ value: 2, label: 'Tuesday' },
{ value: 3, label: 'Wednesday' },
{ value: 4, label: 'Thursday' },
{ value: 5, label: 'Friday' },
{ value: 6, label: 'Saturday' },
{ value: 7, label: 'Sunday' },
];
id: number | null = null;
title = '';
description = '';
host = '';
genre = '';
show_art_url = '';
hero_image_url = '';
display_order = 0;
schedules: ShowScheduleCreate[] = [
{ day_of_week: 1, time: '' },
];
loading = false;
error = '';
submitted = false;
ngOnChanges(changes: SimpleChanges): void {
if (changes['editItem'] && this.editItem) {
this.edit(this.editItem);
}
}
edit(show: Show): void {
this.id = show.id;
this.title = show.title;
this.description = show.description;
this.host = show.host;
this.genre = show.genre;
this.show_art_url = show.show_art_url || '';
this.hero_image_url = show.hero_image_url || '';
this.display_order = show.display_order;
this.schedules = show.schedules.map((s) => ({
day_of_week: s.day_of_week,
time: s.time,
}));
}
formatError(err: any): string {
if (err?.error?.detail) return err.error.detail;
if (err?.error?.message) return err.error.message;
if (err?.message) return err.message;
return 'Failed to save. Please try again.';
}
reset(): void {
this.id = null;
this.title = '';
this.description = '';
this.host = '';
this.genre = '';
this.show_art_url = '';
this.hero_image_url = '';
this.display_order = 0;
this.schedules = [{ day_of_week: 1, time: '' }];
this.error = '';
this.submitted = false;
}
onClose(): void {
this.closed.emit();
this.reset();
}
/** Add a new empty schedule slot row. */
addScheduleSlot(): void {
this.schedules.push({ day_of_week: 1, time: '' });
}
/** Remove a schedule slot row by index. */
removeScheduleSlot(index: number): void {
this.schedules.splice(index, 1);
}
async onSubmit(): Promise<void> {
this.submitted = true;
// Validate required fields
if (!this.title || !this.host || !this.genre) {
this.error = 'Please fill in all required fields.';
return;
}
// Validate schedules
const validSchedules = this.schedules.filter(
(s) => s.day_of_week && s.time,
);
if (validSchedules.length === 0) {
this.error = 'Add at least one schedule slot with a day and time.';
return;
}
this.loading = true;
this.error = '';
const payload = {
title: this.title,
description: this.description,
host: this.host,
genre: this.genre,
show_art_url: this.show_art_url || null,
hero_image_url: this.hero_image_url || null,
display_order: this.display_order,
schedules: validSchedules,
};
try {
if (this.id) {
const updatePayload: ShowUpdatePayload = { ...payload };
await firstValueFrom(this.showService.updateShow(this.id, updatePayload));
} else {
await firstValueFrom(this.showService.createShow(payload as ShowCreatePayload));
}
this.saved.emit();
this.reset();
} catch (err: any) {
this.error = this.formatError(err);
} finally {
this.loading = false;
}
}
}