basic booking load behavior

This commit is contained in:
Roland Schneider
2025-12-19 16:23:53 +01:00
parent 72c213eaea
commit 4e77578abf
18 changed files with 335 additions and 75 deletions

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash
echo "workdir ${pwd}"
wget -O ./openapi/api.json localhost:4200/api-json
npx ng-openapi -i ./openapi/api.json -o ./src/api
wget -O ./openapi/api.json localhost:3000/api-json
npx ng-openapi -c ./openapitools.json -i ./openapi/api.json -o ./src/api

File diff suppressed because one or more lines are too long

View File

@@ -80,6 +80,34 @@ export interface CalendarCreateBookingDto {
export interface CancelBookingDto {
}
export interface UserResponseDto {
id: number;
username: string;
}
export interface BookingResponseDto {
id: number;
eventId: number;
occurrenceStartTime: Date;
notes?: string;
reservedSeatsCount: number;
canceledAt: string | null;
user: UserResponseDto;
}
export interface PaginationResponseMetaDto {
totalItems: number;
itemCount: number;
itemsPerPage: number;
totalPages: number;
currentPage: number;
}
export interface CalenderControllerGetBookingResponse {
data: Array<BookingResponseDto>;
meta: PaginationResponseMetaDto;
}
export interface CreateBookingDto {
}

View File

@@ -12,7 +12,7 @@ import { inject, Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { BASE_PATH_DEFAULT, CLIENT_CONTEXT_TOKEN_DEFAULT } from "../tokens";
import { HttpParamsBuilder } from "../utils/http-params-builder";
import { RequestOptions, CreateEventDto, CreateExceptionDto, CalendarCreateBookingDto, CancelBookingDto } from "../models";
import { RequestOptions, CreateEventDto, CreateExceptionDto, CalendarCreateBookingDto, CancelBookingDto, CalenderControllerGetBookingResponse } from "../models";
@Injectable({ providedIn: "root" })
export class CalendarService {
@@ -153,14 +153,32 @@ export class CalendarService {
return this.httpClient.patch(url, cancelBookingDto, requestOptions);
}
calendarControllerGetBookings(eventId: number, startTime: Date, observe?: 'body', options?: RequestOptions<'json'>): Observable<any>;
calendarControllerGetBookings(eventId: number, startTime: Date, observe?: 'response', options?: RequestOptions<'json'>): Observable<HttpResponse<any>>;
calendarControllerGetBookings(eventId: number, startTime: Date, observe?: 'events', options?: RequestOptions<'json'>): Observable<HttpEvent<any>>;
calendarControllerGetBookings(eventId: number, startTime: Date, observe?: 'body' | 'events' | 'response', options?: RequestOptions<'arraybuffer' | 'blob' | 'json' | 'text'>): Observable<any> {
const url = `${this.basePath}/api/calendar/bookings/${eventId}/${startTime}`;
calendarControllerGetBookings(eventId: number, startTime: string, page?: number, limit?: number, sortBy?: string, order?: 'ASC' | 'DESC', observe?: 'body', options?: RequestOptions<'json'>): Observable<CalenderControllerGetBookingResponse>;
calendarControllerGetBookings(eventId: number, startTime: string, page?: number, limit?: number, sortBy?: string, order?: 'ASC' | 'DESC', observe?: 'response', options?: RequestOptions<'json'>): Observable<HttpResponse<CalenderControllerGetBookingResponse>>;
calendarControllerGetBookings(eventId: number, startTime: string, page?: number, limit?: number, sortBy?: string, order?: 'ASC' | 'DESC', observe?: 'events', options?: RequestOptions<'json'>): Observable<HttpEvent<CalenderControllerGetBookingResponse>>;
calendarControllerGetBookings(eventId: number, startTime: string, page?: number, limit?: number, sortBy?: string, order?: 'ASC' | 'DESC', observe?: 'body' | 'events' | 'response', options?: RequestOptions<'arraybuffer' | 'blob' | 'json' | 'text'>): Observable<any> {
const url = `${this.basePath}/api/calendar/bookings/${eventId}`;
let params = new HttpParams();
if (page != null) {
params = HttpParamsBuilder.addToHttpParams(params, page, 'page');
}
if (limit != null) {
params = HttpParamsBuilder.addToHttpParams(params, limit, 'limit');
}
if (sortBy != null) {
params = HttpParamsBuilder.addToHttpParams(params, sortBy, 'sortBy');
}
if (order != null) {
params = HttpParamsBuilder.addToHttpParams(params, order, 'order');
}
if (startTime != null) {
params = HttpParamsBuilder.addToHttpParams(params, startTime, 'startTime');
}
const requestOptions: any = {
observe: observe as any,
params,
reportProgress: options?.reportProgress,
withCredentials: options?.withCredentials,
context: this.createContextWithClientId(options?.context)

View File

@@ -0,0 +1,10 @@
<!-- We use a generic container but tell the browser it is a heading -->
<div
role="heading"
[attr.aria-level]="level()"
class="text-3xl font-bold"
[class]="'h' + level()"
>
<ng-content></ng-content>
</div>

View File

@@ -0,0 +1,14 @@
import { Component, input } from '@angular/core';
export type HeadingLevel = 1|2|3|4|5|6;
@Component({
selector: 'app-heading',
imports: [],
templateUrl: './heading.html',
styleUrl: './heading.css',
})
export class Heading {
level = input.required<HeadingLevel>()
}

View File

@@ -1,11 +1,38 @@
<h1>Foglalások</h1>
<app-heading [level]="1">
Foglalások
</app-heading>
@if (bookings.isLoading()) {
<div>loading...</div>
} @else {
@for (booking of bookings.value()?.items; track booking) {
<div>
{{ booking }}
@if (bookings.value()?.data?.length) {
<div class="overflow-x-auto">
<table class="table">
<!-- head -->
<thead>
<tr>
<th>Foglalás dátuma</th>
<th>Foglalt helyek száma</th>
<th></th>
</tr>
</thead>
<tbody>
@for (booking of bookings.value()?.data; track booking) {
<tr>
<td>{{formatDateTime(booking.occurrenceStartTime)}}</td>
<td>{{booking.reservedSeatsCount}}</td>
<td><rs-daisy-button [variant]="'error'">
Lemondás
</rs-daisy-button></td>
</tr>
}
</tbody>
</table>
</div>
@if(bookings.value()?.meta?.totalPages! > 1){
<rs-daisy-pagination [pageCount]="pageCount()" [activePage]="activePage()"
(onPaginate)="paginate($event)"></rs-daisy-pagination>
}
} @else {
Nem találtunk foglalást erre az eseményre
}
<rs-daisy-pagination [pageCount]="pageCount()" [activePage]="activePage()" (onPaginate)="paginate($event)"></rs-daisy-pagination>
}

View File

@@ -1,15 +1,19 @@
import { Component, computed, inject, input, signal } from '@angular/core';
import { EventBusService } from '../../../../../services/event-bus.service';
import { CalendarEventDto } from '../../../models/events-in-range-dto.model';
import { CalendarService } from '../../../../../../api';
import { BookingResponseDto, CalendarService } from '../../../../../../api';
import { rxResource } from '@angular/core/rxjs-interop';
import { delay, of } from 'rxjs';
import { Pagination } from '@rschneider/ng-daisyui';
import { delay, of, throwError } from 'rxjs';
import { Button, Pagination } from '@rschneider/ng-daisyui';
import { Heading } from '../../../../../components/heading/heading';
import { format } from 'date-fns';
@Component({
selector: 'app-single-event-booking-list',
imports: [
Pagination,
Heading,
Button,
],
templateUrl: './single-event-booking-list.html',
styleUrl: './single-event-booking-list.css',
@@ -24,7 +28,8 @@ export class SingleEventBookingList {
// bookings = toSignal(of(['a','b']));
pageSize = input<number>(10);
pageCount = computed(() => {
return this.bookings.value()?.pageCount || 1;
// return this.bookings.value()?.pageCount || 1;
return 1;
})
bookings = rxResource(
@@ -34,22 +39,30 @@ export class SingleEventBookingList {
}),
stream: ({params}) => {
console.info("loading resource", params);
const allData = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"]
let pageCount = Math.floor( allData.length / this.pageSize());
if ( (allData.length % this.pageSize()) > 0){
pageCount += 1;
// console.info("loading resource", params);
//
// const allData = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"]
//
// let pageCount = Math.floor( allData.length / this.pageSize());
// if ( (allData.length % this.pageSize()) > 0){
// pageCount += 1;
// }
// pageCount = Math.max(pageCount ,1);
//
// const pageData = allData.slice( ((this.activePage()-1) * this.pageSize()),this.activePage()*this.pageSize());
// console.info("booking page data",pageData);
// return of({
// items: pageData,
// pageCount
// }).pipe( delay(1000))
if ( !this.event()){
return throwError( () => new Error("no event"))
}
pageCount = Math.max(pageCount ,1);
const pageData = allData.slice( ((this.activePage()-1) * this.pageSize()),this.activePage()*this.pageSize());
console.info("booking page data",pageData);
return of({
items: pageData,
pageCount
}).pipe( delay(1000))
const event = this.event()!;
return this.calendarService.calendarControllerGetBookings(
event.id,
new Date(event.startTime).toISOString()
)
},
}
@@ -61,6 +74,10 @@ export class SingleEventBookingList {
this.activePage.set($event);
}
formatDateTime( dateStr: string|Date){
return format(new Date(dateStr),'yyyy-MM-dd HH:mm');
}
protected readonly format = format;
}