add single calendar dialog

This commit is contained in:
Roland Schneider
2025-11-27 19:57:58 +01:00
parent e1ae0a36d7
commit 364be9976a
12 changed files with 199 additions and 21 deletions

View File

@@ -17,7 +17,7 @@
@if (workflow() == 'event-dashboard' && selectedEvent()) {
<rs-daisy-modal [isOpen]="true" (closeClick)="closeDialog()">
<rs-daisy-modal [isOpen]="true" (closeClick)="closeDialog()" [modalBoxStyleClass]="'max-w-none w-2xl'">
<app-single-event-dashboard [event]="selectedEvent()"></app-single-event-dashboard>
</rs-daisy-modal>
}

View File

@@ -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){

View File

@@ -0,0 +1,15 @@
<div class="card bg-base-100 shadow-sm" [class]="styleClass()">
<div class="card-body items-center ">
<h2 class="card-title">{{ title() }}</h2>
<p>{{ description() }}</p>
<div class="card-actions justify-end">
<button class="btn btn-primary">
<!-- Using the new @if control flow -->
@if (svgIcon()) {
<span [innerHTML]="svgIcon() | safeHtml"></span>
}
{{ buttonTitle() }}
</button>
</div>
</div>
</div>

View File

@@ -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<SingleEventDashboardCard>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SingleEventDashboardCard]
})
.compileComponents();
fixture = TestBed.createComponent(SingleEventDashboardCard);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -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<string>();
description= input<string>();
buttonTitle= input<string>();
svgIcon= input<string>();
// 1. Define the Input Signal to receive class names as a string or array
// Example: 'grow-2 align-center'
public customClasses = input<string | null>(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();
}
}

View File

@@ -1,3 +1,23 @@
<app-detail-view
[config]="config"
></app-detail-view>
<h3>Esemény</h3>
@if (config) {
<app-detail-view
[config]="config"
></app-detail-view>
}
<div class="flex mt-3 gap-2 flex-wrap ">
@for (card of cards; let i = $index; track i) {
<app-single-event-dashboard-card
[title]="card.title"
[svgIcon]="card.svgIcon"
[description]="card.description"
[buttonTitle]="card.buttonTitle"
[customClasses]="'flex-1'"
></app-single-event-dashboard-card>
<!-- [customClasses]="'flex-[50_1_0] w-50' "-->
}
</div>

View File

@@ -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<CalendarEventDto>();
config: DetailViewConfig<CalendarEventDto> | undefined;
config: DetailViewConfig<CalendarEventDto>;
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;
}