Skip to content

Commit

Permalink
feat: load event attendees
Browse files Browse the repository at this point in the history
  • Loading branch information
SmallhillCZ committed Feb 7, 2024
1 parent 7aa59be commit db7ceb0
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class EventsAttendeesController {

@Get(":eventId/attendees")
@AcLinks(EventAttendeesListRoute)
@ApiResponse({ type: WithLinks(EventAttendeeResponse) })
@ApiResponse({ type: WithLinks(EventAttendeeResponse), isArray: true })
async listEventAttendees(@Req() req: Request, @Param("eventId") eventId: number): Promise<EventAttendeeResponse[]> {
const event = await this.events.getEvent(eventId);
if (!event) throw new NotFoundException();
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/app/api/sdk/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Bošán - Interní sekce
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: v4.0.0-rc.8
* The version of the OpenAPI document: v4.0.0-rc.11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Expand Down Expand Up @@ -4496,7 +4496,7 @@ export const EventsApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listEventAttendees(eventId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<EventAttendeeResponseWithLinks>> {
async listEventAttendees(eventId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<EventAttendeeResponseWithLinks>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listEventAttendees(eventId, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
Expand Down Expand Up @@ -4767,7 +4767,7 @@ export const EventsApiFactory = function (configuration?: Configuration, basePat
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listEventAttendees(requestParameters: EventsApiListEventAttendeesRequest, options?: AxiosRequestConfig): AxiosPromise<EventAttendeeResponseWithLinks> {
listEventAttendees(requestParameters: EventsApiListEventAttendeesRequest, options?: AxiosRequestConfig): AxiosPromise<Array<EventAttendeeResponseWithLinks>> {
return localVarFp.listEventAttendees(requestParameters.eventId, options).then((request) => request(axios, basePath));
},
/**
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/api/sdk/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Bošán - Interní sekce
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: v4.0.0-rc.8
* The version of the OpenAPI document: v4.0.0-rc.11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/api/sdk/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Bošán - Interní sekce
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: v4.0.0-rc.8
* The version of the OpenAPI document: v4.0.0-rc.11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/api/sdk/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Bošán - Interní sekce
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: v4.0.0-rc.8
* The version of the OpenAPI document: v4.0.0-rc.11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/api/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Bošán - Interní sekce
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: v4.0.0-rc.8
* The version of the OpenAPI document: v4.0.0-rc.11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
<h3>Vedoucí</h3>

<p *ngIf="leaders && !leaders.length"><em>Žádní účastníci</em></p>

<ion-item *ngFor="let leader of leaders">
<ion-label>
<h3>{{ leader | member: "nickname" }}</h3>
<p><bo-member-item-detail *ngIf="leader" [member]="leader"></bo-member-item-detail></p>
</ion-label>

<bo-group-badge [groupId]="leader.groupId"></bo-group-badge>

<ion-button fill="clear" [routerLink]="'/databaze/' + leader.id" slot="end">
<ion-icon name="information-circle-outline"></ion-icon>
</ion-button>

<ion-button fill="clear" color="danger" (click)="removeAttendee(leader)" slot="end">
<ion-icon name="trash-outline"></ion-icon>
</ion-button>
</ion-item>

<div class="text-center">
<bo-add-button (click)="addAttendee()">Přidat účastníka</bo-add-button>
</div>

<h3>Účastníci</h3>

<ion-list>
<!-- ATTENDEES -->
<p *ngIf="attendees && !attendees.length"><em>Žádní účastníci</em></p>
<p *ngIf="attendees && !attendees.length"><em>Žádní účastníci</em></p>

<ion-list>
<ion-item *ngFor="let attendee of attendees">
<ion-label>
<h3>{{ attendee.member | member: "nickname" }}</h3>
<p><bo-member-item-detail *ngIf="attendee.member" [member]="attendee.member"></bo-member-item-detail></p>
<h3>{{ attendee | member: "nickname" }}</h3>
<p><bo-member-item-detail *ngIf="attendee" [member]="attendee"></bo-member-item-detail></p>
</ion-label>
<ion-badge
slot="end"
mode="ios"
[style.background-color]="attendee.member?.groupId | group: 'color'"
class="d-none d-xl-block"
>
{{ attendee.member?.groupId | group: "name" }}
</ion-badge>
<ion-button fill="clear" [routerLink]="'/databaze/' + attendee.memberId" slot="end">

<bo-group-badge [groupId]="attendee.groupId"></bo-group-badge>

<ion-button fill="clear" [routerLink]="'/databaze/' + attendee.id" slot="end">
<ion-icon name="information-circle-outline"></ion-icon>
</ion-button>

<ion-button fill="clear" color="danger" (click)="removeAttendee(attendee)" slot="end">
<ion-icon name="trash-outline"></ion-icon>
</ion-button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from "@angular/core";
import { UntilDestroy } from "@ngneat/until-destroy";
import { EventAttendeeResponse, EventResponseWithLinks } from "src/app/api";
import { EventResponseWithLinks, MemberResponse } from "src/app/api";
import { MemberSelectorModalComponent } from "src/app/modules/events/components/member-selector-modal/member-selector-modal.component";
import { ApiService } from "src/app/services/api.service";
import { ModalService } from "src/app/services/modal.service";
Expand All @@ -13,11 +13,12 @@ import { Action } from "src/app/shared/components/action-buttons/action-buttons.
templateUrl: "./event-attendees.component.html",
styleUrls: ["./event-attendees.component.scss"],
})
export class EventAttendeesComponent implements OnInit, OnDestroy {
@Input() event?: EventResponseWithLinks;
export class EventAttendeesComponent implements OnInit, OnDestroy, OnChanges {
@Input() event?: EventResponseWithLinks | null;
@Output() change = new EventEmitter<void>();

attendees: EventAttendeeResponse[] = [];
attendees: MemberResponse[] = [];
leaders: MemberResponse[] = [];

actions: Action[] = [];

Expand All @@ -35,10 +36,30 @@ export class EventAttendeesComponent implements OnInit, OnDestroy {
this.modal?.dismiss();
}

private sortAttendees() {
this.attendees.sort((a, b) => {
const aString = a.member?.nickname || a.member?.firstName || a.member?.lastName || "";
const bString = b.member?.nickname || b.member?.firstName || b.member?.lastName || "";
ngOnChanges(changes: SimpleChanges): void {
if (changes.event) this.loadAttendees(this.event);
}

private async loadAttendees(event?: EventResponseWithLinks | null) {
if (!event) {
this.attendees = [];
this.leaders = [];
return;
}

const attendees = await this.api.events.listEventAttendees(event.id).then((res) => res.data);

this.attendees = attendees.filter((a) => a.type === "attendee").map((m) => m.member!) || [];
this.sortMembers(this.attendees);

this.leaders = attendees.filter((a) => a.type === "leader").map((m) => m.member!) || [];
this.sortMembers(this.leaders);
}

private sortMembers(members: MemberResponse[]) {
members.sort((a, b) => {
const aString = a.nickname || a.firstName || a.lastName || "";
const bString = b.nickname || b.firstName || b.lastName || "";
return aString.localeCompare(bString);
});
}
Expand All @@ -57,15 +78,9 @@ export class EventAttendeesComponent implements OnInit, OnDestroy {
}

// optimistic update
attendees.push({
memberId: member.id,
member,
eventId: this.event.id,
type: "attendee",
});
this.attendees.push(member);

this.attendees = attendees;
this.sortAttendees();
this.sortMembers(this.attendees);

try {
await this.api.events.addEventAttendee(this.event.id, member.id, {});
Expand All @@ -79,17 +94,20 @@ export class EventAttendeesComponent implements OnInit, OnDestroy {
}
}

async removeAttendee(attendee: EventAttendeeResponse) {
async removeAttendee(member: MemberResponse) {
if (!this.event) return;

let attendees = this.event.attendees || [];
attendees = attendees.filter((item) => item.memberId !== attendee.memberId);

this.attendees = attendees; // optimistic update
try {
// optimistic update
this.attendees.filter((item) => item.id !== member.id);

await this.api.events.deleteEventAttendee(this.event.id, attendee.memberId);
await this.api.events.deleteEventAttendee(this.event.id, member.id);

this.change.emit();
this.change.emit();
} catch (e) {
this.toastService.toast("Nepodařilo se odebrat účastníka.");
this.attendees.push(member); // rollback
}
}

toggleSliding(sliding: any) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<ion-badge [style.background-color]="groupId | group: 'color'">
<ion-badge mode="ios" [style.background-color]="groupId | group: 'color'">
{{ groupId | group: "name" }}
</ion-badge>

0 comments on commit db7ceb0

Please sign in to comment.