From d14530e11e8bb45ee1b48b3b2a1230a1909ba15b Mon Sep 17 00:00:00 2001 From: Wolfgang Roese Date: Sat, 20 Jul 2024 17:34:56 +0200 Subject: [PATCH 1/3] work in progress --- .../edit-appointment.component.html | 12 +++++++++- .../edit-appointment.component.ts | 24 +++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/app/features/appointments/edit-appointment/edit-appointment.component.html b/src/app/features/appointments/edit-appointment/edit-appointment.component.html index 93c35ec8..1d2ce34b 100644 --- a/src/app/features/appointments/edit-appointment/edit-appointment.component.html +++ b/src/app/features/appointments/edit-appointment/edit-appointment.component.html @@ -10,6 +10,16 @@

{{ appointment.name }} - {{ appointment.startTime | date : 'dd.MM.yy' : 'locale(de)' }}

+
@@ -177,7 +187,7 @@

class="p-mr-3" > +
+ +
+
@@ -186,16 +189,6 @@

type="submit" class="p-mr-3" > - + +
+
diff --git a/src/@arpa/components/table/table.component.scss b/src/@arpa/components/table/table.component.scss index d1fc8ff7..3ad424d1 100644 --- a/src/@arpa/components/table/table.component.scss +++ b/src/@arpa/components/table/table.component.scss @@ -60,7 +60,54 @@ background-color: black; text-align: center; } +:host ::ng-deep { + .p-datatable { + padding-left: 4px; + padding-right: 4px; + } + + .p-datatable-header { + padding-left: 0; + padding-right: 0; + } + + td.start { + i.pi { + font-weight: 800; + align-items: center; + color: var(--green-500); + } + } +} +:host ::ng-deep { + .p-datatable { + padding-left: 4px; + padding-right: 4px; + } + + .p-datatable-header { + padding-left: 0; + padding-right: 0; + } + + td.start { + i.pi { + font-weight: 800; + align-items: center; + color: var(--green-500); + } + } +} .download-button { - margin-left: 0.5rem; - margin-bottom: 0.5rem; + display: flex; + justify-content: center; + align-items: center; + margin-top: 2rem; +} +.download-button button { + transition: background-color 0.3s ease, transform 0.3s ease; + &:hover { + background-color: var(--hover-color, #f2f2f2); + transform: scale(1.25); + } } diff --git a/src/@arpa/components/table/table.component.ts b/src/@arpa/components/table/table.component.ts index 0045b905..6d3b2ed7 100644 --- a/src/@arpa/components/table/table.component.ts +++ b/src/@arpa/components/table/table.component.ts @@ -11,6 +11,7 @@ import { Output, QueryList, TemplateRef, + ViewEncapsulation, } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { PrimeTemplate, SelectItem } from 'primeng/api'; @@ -51,6 +52,7 @@ export class ArpaTableColumnDirective { selector: 'arpa-table', templateUrl: './table.component.html', styleUrls: ['./table.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class TableComponent implements OnInit, OnDestroy, AfterContentInit { @Input() diff --git a/src/app/features/appointments/appointments.module.ts b/src/app/features/appointments/appointments.module.ts index db1bb431..8145b04e 100644 --- a/src/app/features/appointments/appointments.module.ts +++ b/src/app/features/appointments/appointments.module.ts @@ -27,6 +27,7 @@ import { InputTextModule } from 'primeng/inputtext'; import { InputNumberModule } from 'primeng/inputnumber'; import { OverlayPanelModule } from 'primeng/overlaypanel'; import { RippleModule } from 'primeng/ripple'; +import { TabViewModule } from 'primeng/tabview'; @NgModule({ declarations: [AppointmentsComponent, EditAppointmentComponent], @@ -52,6 +53,7 @@ import { RippleModule } from 'primeng/ripple'; InputNumberModule, OverlayPanelModule, RippleModule, + TabViewModule, ], providers: [ AppointmentCategoryListResolver, diff --git a/src/app/features/appointments/edit-appointment/edit-appointment.component.html b/src/app/features/appointments/edit-appointment/edit-appointment.component.html index bfa7f104..8333d384 100644 --- a/src/app/features/appointments/edit-appointment/edit-appointment.component.html +++ b/src/app/features/appointments/edit-appointment/edit-appointment.component.html @@ -22,11 +22,9 @@

icon="pi pi-envelope" >

- - -
- -
+ + +
@@ -41,18 +39,51 @@

/>

- +
- +
+ + +
+
+ + +
[showOnFocus]="false" >
- +
+ + +
+
+ + +
+
+ + +
+
+ + +
-
- - -
-
- - -
-
@@ -181,25 +240,26 @@

+

- - -
-
-
-
- + + + + {{ filteredDataCount }} {{ 'appointments.RESULTS' | translate }} + + + + {{ col.header }} + + + + + + + -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - + -
-
-
-
-
- -
- - {{ filteredDataCount }} {{ 'appointments.RESULTS' | translate }} - - - - {{ col.header }} - - - - - - - - - - + > - - - - - - - - {{ 'SURNAME' | translate }} - {{ item.surname }} - - - {{ 'GIVENNAME' | translate }} - {{ item.givenName }} - - - {{ 'appointments.PREDICTION' | translate }} - - - - -

{{ item.commentByPerformerInner }}

-
-
- - - {{ 'appointments.RESULTS' | translate }} - - - - {{ 'SECTIONS' | translate }} - {{ item.sections }} - - - {{ 'appointments.QUALIFICATION' | translate }} - {{ item.qualification }} - - -
- - - {{ 'appointments.NORECORDS' | translate }} - - - - {{ filteredDataCount }} {{ 'appointments.RESULTS' | translate }} - -
-
- -
+ + + + + + + + {{ 'SURNAME' | translate }} + {{ item.surname }} + + + {{ 'GIVENNAME' | translate }} + {{ item.givenName }} + + + {{ 'appointments.PREDICTION' | translate }} + + + + +

{{ item.commentByPerformerInner }}

+
+
+ + + {{ 'appointments.RESULTS' | translate }} + + + + {{ 'SECTIONS' | translate }} + {{ item.sections }} + + + {{ 'appointments.QUALIFICATION' | translate }} + {{ item.qualification }} + + +
+ + + {{ 'appointments.NORECORDS' | translate }} + + + + {{ filteredDataCount }} {{ 'appointments.RESULTS' | translate }} + + +
+
- -
+ +
diff --git a/src/app/features/appointments/edit-appointment/edit-appointment.component.scss b/src/app/features/appointments/edit-appointment/edit-appointment.component.scss index 1df6cad7..f1bf47cb 100644 --- a/src/app/features/appointments/edit-appointment/edit-appointment.component.scss +++ b/src/app/features/appointments/edit-appointment/edit-appointment.component.scss @@ -1,9 +1,34 @@ -:host ::ng-deep #participationTable { - div.p-datatable-wrapper { - overflow-x: scroll; - } - table { - width: 1200px; +label { + font-weight: bolder; + font-size: 0.8rem; + opacity: 0.5; + text-transform: uppercase; +} + +table { + width: 100%; + table-layout: fixed; +} + +th, +td { + text-align: left; + padding: 8px; + box-sizing: border-box; +} + +th { + background-color: #f2f2f2; +} + +.p-column-title { + display: none; +} + +@media (max-width: 600px) { + .p-column-title { + display: block; + font-weight: bold; } } @@ -12,6 +37,12 @@ } .appointment-title { color: var(--primary-color); - font-weight: normal; - font-size: xx-large; + font-weight: bolder; + font-size: xxx-large; +} +.download-button { + display: flex; + justify-content: center; + align-items: center; + margin-top: 2rem; } diff --git a/src/app/features/appointments/edit-appointment/edit-appointment.component.ts b/src/app/features/appointments/edit-appointment/edit-appointment.component.ts index 5858000d..aa7fa3b8 100644 --- a/src/app/features/appointments/edit-appointment/edit-appointment.component.ts +++ b/src/app/features/appointments/edit-appointment/edit-appointment.component.ts @@ -13,7 +13,7 @@ import { } from '@arpa/models'; import { TranslateService } from '@ngx-translate/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; -import { Component, OnInit, ViewChild } from '@angular/core'; +import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { ConfirmationService, MenuItem, SelectItem } from 'primeng/api'; import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; import { sortBy, uniq } from 'lodash-es'; @@ -58,6 +58,7 @@ class ParticipationTableItem { selector: 'arpa-edit-appointment', templateUrl: './edit-appointment.component.html', styleUrls: ['./edit-appointment.component.scss'], + encapsulation: ViewEncapsulation.None, }) export class EditAppointmentComponent implements OnInit { @ViewChild('participationTable') table: Table; @@ -124,9 +125,8 @@ export class EditAppointmentComponent implements OnInit { { field: 'prediction', header: this.translate.instant('appointments.PREDICTION'), width: '20%' }, { field: 'result', header: this.translate.instant('appointments.RESULTS'), width: '20%' }, { field: 'sections', header: this.translate.instant('appointments.SECTIONS'), width: '20%' }, - // { field: 'qualification', header: this.translate.instant('appointments.QUALIFICATION'), width: '20%' }, + { field: 'qualification', header: this.translate.instant('appointments.QUALIFICATION'), width: '20%' }, ]; - this.createStepperMenu(); } private loadData() { @@ -213,11 +213,6 @@ export class EditAppointmentComponent implements OnInit { this.venueOptions = this.venues?.map((v) => this.mapVenueToSelectItem(v)); this.setRooms(this.appointment.venueId); this.ready = true; - - // Check if appointment.participations is loaded - console.log('Appointment Participations:', this.appointment.participations); - - // Calculate totalParticipationCount this.calculateTotalParticipationCount(); }); } @@ -226,35 +221,37 @@ export class EditAppointmentComponent implements OnInit { this.totalParticipationCount = this.appointment.participations?.length || 0; } - onSubmit(continueToNextStep: boolean): void { + onSubmit(): void { if (this.formGroup.invalid || this.formGroup.pristine) { + this.notificationsService.info('No changes to save'); return; } if (this.isNew) { - this.createAppointment({ ...this.appointment, ...this.formGroup.value }, continueToNextStep); + this.createAppointment({ ...this.appointment, ...this.formGroup.value }); } else { - this.updateAppointment( - { - id: this.appointment.id, - categoryId: this.appointment.categoryId, - startTime: this.appointment.startTime, - endTime: this.appointment.endTime, - name: this.appointment.name, - publicDetails: this.appointment.publicDetails, - internalDetails: this.appointment.internalDetails, - status: this.appointment.status, - salaryId: this.appointment.salaryId, - salaryPatternId: this.appointment.salaryPatternId, - expecationId: this.appointment.expectationId, - ...this.formGroup.value, - }, - continueToNextStep - ); + this.updateAppointment({ + id: this.appointment.id, + categoryId: this.appointment.categoryId, + startTime: this.appointment.startTime, + endTime: this.appointment.endTime, + name: this.appointment.name, + publicDetails: this.appointment.publicDetails, + internalDetails: this.appointment.internalDetails, + status: this.appointment.status, + salaryId: this.appointment.salaryId, + salaryPatternId: this.appointment.salaryPatternId, + expecationId: this.appointment.expectationId, + ...this.formGroup.value, + }); } } - onActiveIndexChange(event: number) { - if (event === 2 && !this.areParticipationsAlreadyLoaded) { + cancelAndClose(): void { + this.ref.close(); + } + + onTabChange(event: { index: number }) { + if (event.index === 1 && !this.areParticipationsAlreadyLoaded) { this.ready = false; this.appointmentService.getById(this.appointment.id, true).subscribe( (appointment) => { @@ -283,10 +280,7 @@ export class EditAppointmentComponent implements OnInit { this.mapParticipations(); this.ready = true; - this.calculateTotalParticipationCount(); - // Check if appointment.participations is loaded - console.log('Appointment Participations:', this.appointment.participations); } }, () => (this.ready = true) @@ -298,32 +292,27 @@ export class EditAppointmentComponent implements OnInit { return { label: `${venue?.address?.city} ${venue?.address?.urbanDistrict} | ${venue?.name}`, value: venue?.id }; } - updateAppointment(appointment: AppointmentModifyBodyDto, continueToNextStep: boolean): void { + updateAppointment(appointment: AppointmentModifyBodyDto): void { this.appointmentService .update(appointment) .pipe(first()) .subscribe(() => { this.notificationsService.success('appointments.APPOINTMENT_UPDATED'); - if (continueToNextStep) { - this.appointment = { ...this.appointment, ...appointment }; - this.fillForm(); - this.activeIndex = 1; - } else { - this.ref.close(appointment); - } + this.appointment = { ...this.appointment, ...appointment }; + this.fillForm(); + this.activeIndex = 0; }); } - createAppointment(appointment: AppointmentCreateDto, continueToNextStep: boolean): void { + createAppointment(appointment: AppointmentCreateDto): void { this.appointmentService .create(appointment) .pipe(first()) .subscribe((result) => { this.notificationsService.success('appointments.APPOINTMENT_CREATED'); - if (continueToNextStep) { + if (onsubmit) { this.appointment = result; this.fillForm(); - this.createStepperMenu(); this.activeIndex = 1; } else { this.ref.close(result); @@ -538,6 +527,10 @@ export class EditAppointmentComponent implements OnInit { salaryId: [null], salaryPatternId: [null], expectationId: [null], + venueId: [null], + roomId: [null], + projectIds: [null], + sectionIds: [null], }); } @@ -569,40 +562,12 @@ export class EditAppointmentComponent implements OnInit { }); } - private createStepperMenu(): void { - this.items = [ - { - label: this.translate.instant('appointments.BASICDATA'), - command: () => { - this.activeIndex = 0; - }, - }, - { - label: this.translate.instant('appointments.ADDITIONALDATA'), - disabled: this.isNew, - command: () => { - this.activeIndex = 1; - }, - }, - { - label: this.translate.instant('appointments.RESULTS'), - disabled: this.isNew, - command: () => { - this.activeIndex = 2; - }, - }, - ]; - } - private deleteAppointment(): void { this.appointmentService.delete(this.appointment.id).subscribe(() => { this.notificationsService.success('appointments.APPOINTMENT_DELETED'); this.ref.close(this.appointment.id); }); } - exportCSV() { - this.table.exportCSV(); - } public onSendNotification(event: Event) { this.sendNotification(false, event); @@ -645,7 +610,10 @@ export class EditAppointmentComponent implements OnInit { getSendNotificationLabel(): string { const sendNotificationLabel = this.translate.instant('appointments.SEND_NOTIFICATION'); const recipientsLabel = this.translate.instant('RECEPIENTS'); - - return `${sendNotificationLabel} (${this.totalParticipationCount} ${recipientsLabel})`; + if (this.totalParticipationCount === 0) { + return `${sendNotificationLabel}`; + } else { + return `${sendNotificationLabel} (${this.totalParticipationCount} ${recipientsLabel})`; + } } } diff --git a/src/assets/i18n/appointments/de.json b/src/assets/i18n/appointments/de.json index 7f49c639..71609450 100644 --- a/src/assets/i18n/appointments/de.json +++ b/src/assets/i18n/appointments/de.json @@ -8,6 +8,7 @@ "UPCOMING_APPOINTMENTS": "anstehende(r) Termin(e)", "ARE_YOU_SURE": "Sind Sie sicher, dass Sie den Termin inklusiver aller abhängigen Daten unwiderruflich löschen wollen?", "BASICDATA": "Basisdaten", + "APPOINTMENT_DETAILS": "Termindetails", "CATEGORY": "Kategorie", "CREATE": "Termin erstellen", "DETAILSINTERNAL": "Interne Details", @@ -33,10 +34,12 @@ "RESULTS": "Ergebnisse", "RESULT_SET": "Ergebnis gesetzt", "ROOMS": "Räume", + "ROOM": "Raum", "ROOM_ADDED": "Raum hinzugefügt", "ROOM_REMOVED": "Raum entfernt", "SALARY": "Vergütung", "SALARYPATTERN": "Vergütungsmuster", + "SAVE": "Speichern", "SAVECLOSE": "Speichern und schließen", "SAVECONTINUE": "Speichern und weiter", "SECTIONS": "Register", @@ -47,6 +50,7 @@ "SEND_NOTIFICATION_TOOLTIP": "Eine E-Mail-Benachrichtigung über die Änderung dieses Termins an alle Teilnehmer senden", "START": "Beginn", "STATUS": "Status", + "TARGET_AUDIENCE": "Zielgruppe", "TITLE": "Terminbezeichnung", "VENUE": "Ort", "VENUE_SET": "Veranstaltungsort gesetzt", diff --git a/src/assets/i18n/appointments/en.json b/src/assets/i18n/appointments/en.json index e10e8a9c..f1241f01 100644 --- a/src/assets/i18n/appointments/en.json +++ b/src/assets/i18n/appointments/en.json @@ -8,6 +8,7 @@ "UPCOMING_APPOINTMENTS": "upcoming appointment(s)", "ARE_YOU_SURE": "Are you sure that you want to irrevocably delete this appointment including all dependent data?", "BASICDATA": "Basic data", + "APPOINTMENT_DETAILS": "Appointment details", "CATEGORY": "Category", "CREATE": "Create an appointment", "DETAILSINTERNAL": "Internal Details", @@ -33,10 +34,12 @@ "RESULTS": "Results", "RESULT_SET": "Result set", "ROOMS": "Rooms", + "ROOM": "Room", "ROOM_ADDED": "Room added", "ROOM_REMOVED": "Room removed", "SALARY": "Salary", "SALARYPATTERN": "Salary Pattern", + "SAVE": "Save", "SAVECLOSE": "Save and close", "SAVECONTINUE": "Save and continue", "SECTIONS": "Section", @@ -47,6 +50,7 @@ "SEND_NOTIFICATION_TOOLTIP": "Send an e-mail notification to all participants about the change to this appointment", "START": "Start", "STATUS": "Status", + "TARGET_AUDIENCE": "Target audience", "TITLE": "Appointment description", "VENUE": "Venue", "VENUE_SET": "Venue set", diff --git a/src/assets/i18n/appointments/fr.json b/src/assets/i18n/appointments/fr.json index 7d2ce025..7003b8d3 100644 --- a/src/assets/i18n/appointments/fr.json +++ b/src/assets/i18n/appointments/fr.json @@ -7,6 +7,7 @@ "UPCOMING_APPOINTMENTS": "événements à venir", "ARE_YOU_SURE": "Etes-vous sûr de vouloir supprimer définitivement le rendez-vous ainsi que les informations rattachées à celui-ci?", "BASICDATA": "Informations générales", + "APPOINTMENT_DETAILS": "Détails de l'événement", "CATEGORY": "Catégorie", "CREATE": "Créer un nouvel événement", "DETAILSINTERNAL": "Détails privés", @@ -32,10 +33,12 @@ "RESULTS": "Resultats", "RESULT_SET": "Résultat obtenu", "ROOMS": "Salles", + "ROOM": "Salle", "ROOM_ADDED": "Salle ajoutée", "ROOM_REMOVED": "Salle supprimée", "SALARY": "Rémunération", "SALARYPATTERN": "Modèle de rémunération", + "SAVE": "Sauvegarder", "SAVECLOSE": "Sauvegarder et fermer", "SAVECONTINUE": "Sauvegarder et poursuivre", "SECTIONS": "Registres", diff --git a/src/assets/i18n/appointments/pt.json b/src/assets/i18n/appointments/pt.json index dd37e520..64a8b972 100644 --- a/src/assets/i18n/appointments/pt.json +++ b/src/assets/i18n/appointments/pt.json @@ -7,6 +7,7 @@ "UPCOMING_APPOINTMENTS": "próximos eventos", "ARE_YOU_SURE": "Tem a certeza de que pretende apagar permanentemente o evento, incluindo todos os dados adjacentes?", "BASICDATA": "Informações gerais", + "APPOINTMENT_DETAILS": "Detalhes do evento", "CATEGORY": "Categoria", "CREATE": "Criar evento", "DETAILSINTERNAL": "Detalhes privados", @@ -34,8 +35,10 @@ "ROOM_ADDED": "Sala adicionada", "ROOM_REMOVED": "Sala removida", "ROOMS": "Salas", + "ROOM": "Sala", "SALARY": "Remuneração", "SALARYPATTERN": "Modelo de remuneração", + "SAVE": "Salvar", "SAVECLOSE": "Salvar e fechar", "SEND_NOTIFICATION": "Enviar notificação por correio eletrónico", "SEND_NOTIFICATION_TOOLTIP": "Enviar uma notificação por correio eletrónico a todos os participantes sobre a alteração deste compromisso", diff --git a/src/assets/i18n/appointments/ru.json b/src/assets/i18n/appointments/ru.json index 73c12fec..a979fb42 100644 --- a/src/assets/i18n/appointments/ru.json +++ b/src/assets/i18n/appointments/ru.json @@ -8,6 +8,7 @@ "UPCOMING_APPOINTMENTS": "Предстоящая дата (даты)", "ARE_YOU_SURE": "Вы уверены, что хотите безвозвратно удалить назначение, включая все зависимые данные?", "BASICDATA": "Основные данные", + "APPOINTMENT_DETAILS": "Детали назначения", "CATEGORY": "Категория", "CREATE": "Назначить встречу", "DETAILSINTERNAL": "Внутренние детали", @@ -33,10 +34,12 @@ "RESULTS": "Результаты", "RESULT_SET": "Набор результатов", "ROOMS": "Номера", + "ROOM": "Номер", "ROOM_ADDED": "Номер добавлен", "ROOM_REMOVED": "Убранная комната", "SALARY": "Вознаграждение", "SALARYPATTERN": "Модель вознаграждения", + "SAVE": "Сохранить", "SAVECLOSE": "Сохранить и закрыть", "SAVECONTINUE": "Сохранить и продолжить", "SECTIONS": "Играет", diff --git a/src/assets/i18n/appointments/ua.json b/src/assets/i18n/appointments/ua.json index 9112ad8d..8f512592 100644 --- a/src/assets/i18n/appointments/ua.json +++ b/src/assets/i18n/appointments/ua.json @@ -8,6 +8,7 @@ "UPCOMING_APPOINTMENTS": "Найближча(і) дата(и)", "ARE_YOU_SURE": "Ви впевнені, що хочете безповоротно видалити зустріч з усіма залежними даними?", "BASICDATA": "Основні дані", + "APPOINTMENT_DETAILS": "Деталі зустрічі", "CATEGORY": "Категорія", "CREATE": "Створити зустріч", "DETAILSINTERNAL": "Внутрішні деталі", @@ -33,10 +34,12 @@ "RESULTS": "Результати", "RESULT_SET": "Набір результатів", "ROOMS": "Кімнати", + "ROOM": "Кімната", "ROOM_ADDED": "Додано кімнату", "ROOM_REMOVED": "Номер видалено", "SALARY": "Винагорода", "SALARYPATTERN": "Модель винагороди", + "SAVE": "Зберегти", "SAVECLOSE": "Зберегти та закрити", "SAVECONTINUE": "Зберегти та продовжити", "SECTIONS": "Регістри",