diff --git a/admin/src/app/app.ts b/admin/src/app/app.ts index b002de5..ccef7e0 100644 --- a/admin/src/app/app.ts +++ b/admin/src/app/app.ts @@ -3,11 +3,12 @@ import { Router, RouterOutlet } from '@angular/router'; import { AuthService } from './auth/auth.service'; import { AdminLayoutRs1 } from '../../projects/rschneider/ng-daisyui/src/lib/layout'; import { Menu, MenuItem } from './components/menu/menu'; +import { SingleEventDashboardCard } from './features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card'; @Component({ selector: 'app-root', - imports: [RouterOutlet, AdminLayoutRs1, Menu], + imports: [RouterOutlet, AdminLayoutRs1, Menu, SingleEventDashboardCard], // Import it here templateUrl: './app.html', styleUrl: './app.css', }) @@ -74,8 +75,6 @@ export class App { } logout(): void { - // With the interceptor fixed, this is now the correct and robust way. - // The error from a failed server logout will propagate here. this.authService.serverSideLogout().subscribe({ next: () => { console.log('Server-side logout successful.'); diff --git a/admin/src/app/components/detail-view/detail-view.html b/admin/src/app/components/detail-view/detail-view.html index 586fe53..3928a2d 100644 --- a/admin/src/app/components/detail-view/detail-view.html +++ b/admin/src/app/components/detail-view/detail-view.html @@ -1,7 +1,6 @@ -{{config().data}} @if (config().data){
- +
@for (row of config().rows; track row.attribute) { diff --git a/admin/src/app/features/calendar/components/calendar-view/calendar-view.html b/admin/src/app/features/calendar/components/calendar-view/calendar-view.html index 3daf11d..890b3cc 100644 --- a/admin/src/app/features/calendar/components/calendar-view/calendar-view.html +++ b/admin/src/app/features/calendar/components/calendar-view/calendar-view.html @@ -17,7 +17,7 @@ @if (workflow() == 'event-dashboard' && selectedEvent()) { - + } diff --git a/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts b/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts index 907590f..9187ee3 100644 --- a/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts +++ b/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts @@ -12,10 +12,11 @@ import { CalendarService } from '../../services/calendar.service'; import { CalendarEventDto, EventsInRangeDTO } from '../../models/events-in-range-dto.model'; import { map } from 'rxjs'; import { SingleEventDashboard } from './single-event-dashboard/single-event-dashboard'; +import { JsonPipe } from '@angular/common'; @Component({ selector: 'app-calendar-view', - imports: [FullCalendarModule, Modal, CreateEventForm, SingleEventDashboard], + imports: [FullCalendarModule, Modal, CreateEventForm, SingleEventDashboard, JsonPipe], templateUrl: './calendar-view.html', styleUrl: './calendar-view.css', }) @@ -86,7 +87,7 @@ export class CalendarView implements OnInit, AfterViewInit { // end: model.end_time, title: model.title, extendedProps: { - event: value + event: model } }; if ( model.eventType){ diff --git a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.css b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.css new file mode 100644 index 0000000..e69de29 diff --git a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.html b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.html new file mode 100644 index 0000000..22c9c74 --- /dev/null +++ b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.html @@ -0,0 +1,15 @@ +
+
+

{{ title() }}

+

{{ description() }}

+
+ +
+
+
diff --git a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.spec.ts b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.spec.ts new file mode 100644 index 0000000..e38a2db --- /dev/null +++ b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SingleEventDashboardCard } from './single-event-dashboard-card'; + +describe('SingleEventDashboardCard', () => { + let component: SingleEventDashboardCard; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SingleEventDashboardCard] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SingleEventDashboardCard); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.ts b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.ts new file mode 100644 index 0000000..fd2f8f0 --- /dev/null +++ b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard-card/single-event-dashboard-card.ts @@ -0,0 +1,44 @@ +import { Component, computed, HostBinding, input } from '@angular/core'; +import { SafeHtmlPipe } from '../../../../../pipes/safe-html-pipe'; + +@Component({ + selector: 'app-single-event-dashboard-card', + standalone: true, + imports: [ + SafeHtmlPipe, + ], // CommonModule is no longer needed + templateUrl: './single-event-dashboard-card.html', + styleUrl: './single-event-dashboard-card.css', +}) +export class SingleEventDashboardCard { + title= input(); + description= input(); + buttonTitle= input(); + svgIcon= input(); + + // 1. Define the Input Signal to receive class names as a string or array + // Example: 'grow-2 align-center' + public customClasses = input(null); + + // 2. Create a computed signal that filters out any null/undefined and returns the class string + private hostClasses = computed(() => { + // We append a base class that should always be present (e.g., 'flex-item') + const classes = ['flex-item']; + + const custom = this.customClasses(); + if (custom) { + // Split the input string and add the class names + classes.push(...custom.trim().split(/\s+/)); + } + + // Return a single space-separated string + return classes.join(' '); + }); + + // 3. Use @HostBinding to bind the computed string to the host element's 'class' attribute + @HostBinding('class') + get classAttribute(): string { + return this.hostClasses(); + } + +} diff --git a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.html b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.html index fce4be3..70233d5 100644 --- a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.html +++ b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.html @@ -1,3 +1,23 @@ - +

Esemény

+ +@if (config) { + +} + +
+ @for (card of cards; let i = $index; track i) { + + + + } + +
diff --git a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.ts b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.ts index 5f3b128..cb74713 100644 --- a/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.ts +++ b/admin/src/app/features/calendar/components/calendar-view/single-event-dashboard/single-event-dashboard.ts @@ -1,11 +1,18 @@ -import { Component, input, signal } from '@angular/core'; +import { Component, effect, input, signal } from '@angular/core'; import { CalendarEventDto, EventsInRangeDTO } from '../../../models/events-in-range-dto.model'; import { DetailView, DetailViewConfig } from '../../../../../components/detail-view/detail-view'; +import { JsonPipe } from '@angular/common'; +import { SvgIcons } from '../../../../../svg-icons'; +import { SafeHtmlPipe } from '../../../../../pipes/safe-html-pipe'; +import { SingleEventDashboardCard } from '../single-event-dashboard-card/single-event-dashboard-card'; @Component({ selector: 'app-single-event-dashboard', imports: [ DetailView, + JsonPipe, + SafeHtmlPipe, + SingleEventDashboardCard, ], templateUrl: './single-event-dashboard.html', styleUrl: './single-event-dashboard.css', @@ -13,16 +20,75 @@ import { DetailView, DetailViewConfig } from '../../../../../components/detail-v export class SingleEventDashboard { event = input(); + config: DetailViewConfig | undefined; - config: DetailViewConfig; - constructor() { - this.config = { - data: this.event()!, - - rows: [{ - attribute: 'title', - getTitle: 'title', - }] + cards: CardConfig[] = [ + { + buttonTitle: 'Szerkesztés', + title: 'Szerkesztés', + svgIcon: SvgIcons.heorPencilSquare, + description: 'Az esemény módosítása' + }, + { + buttonTitle: 'Esemény lemondása', + title: 'Esemény lemondása', + svgIcon: SvgIcons.heroXcircle, + description: 'Az esemény lemondása' + }, + { + buttonTitle: 'Esemény törlése', + title: 'Esemény törlése', + svgIcon: SvgIcons.heroTrash, + description: 'Az esemény törlése' + }, + { + buttonTitle: 'Bejelentkezés', + title: 'Időpont foglalás', + svgIcon: SvgIcons.heroTrash, + description: 'Időpont foglalása eseményre' + }, + { + buttonTitle: 'Lemondás', + title: 'Időpont lemondása', + svgIcon: SvgIcons.heroTrash, + description: 'Az időpont lemondása' } + ]; + + constructor() { + effect(() => { + this.config = { + data: this.event()!, + + rows: [{ + attribute: 'id', + getTitle: 'Esemény azonosító', + }, + { + attribute: 'title', + getTitle: 'Esemény neve', + }, + { + attribute: 'startTime', + getTitle: 'Kezdési időpont', + format: 'datetime' + }, + { + attribute: 'eventType', + getTitle: 'Esemény típusa', + getValue: obj => obj.eventType.name, + + } + ], + }; + }); } + + protected readonly SvgIcons = SvgIcons; +} +export interface CardConfig{ + title?: string; + description?: string; + buttonTitle?: string; + svgIcon?: string; } diff --git a/admin/src/app/features/calendar/models/events-in-range-dto.model.ts b/admin/src/app/features/calendar/models/events-in-range-dto.model.ts index b08ed0c..21a1b2d 100644 --- a/admin/src/app/features/calendar/models/events-in-range-dto.model.ts +++ b/admin/src/app/features/calendar/models/events-in-range-dto.model.ts @@ -18,6 +18,7 @@ export type BookingWithUserDto = { // The final shape of a calendar event occurrence export type CalendarEventDto = { + id: number; title: string; startTime: string, endTime: string, diff --git a/admin/src/app/svg-icons.ts b/admin/src/app/svg-icons.ts index c48b7d3..3c2fa06 100644 --- a/admin/src/app/svg-icons.ts +++ b/admin/src/app/svg-icons.ts @@ -12,6 +12,16 @@ export class SvgIcons { +`; + + public static heorPencilSquare = ` + + + `; + + public static heroXcircle = ` + + `; }