import { HttpEventType } from '@angular/common/http'; import { ChangeDetectorRef, Component, ViewChild } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { AngularCropperjsModule } from 'angular-cropperjs'; import { KeycloakService } from 'keycloak-angular'; import { ConfirmationService, MessageService } from 'primeng/api'; import { ConfirmDialogModule } from 'primeng/confirmdialog'; import { DialogModule } from 'primeng/dialog'; import { DialogService, DynamicDialogModule, DynamicDialogRef } from 'primeng/dynamicdialog'; import { EditorModule } from 'primeng/editor'; import { FileUpload, FileUploadModule } from 'primeng/fileupload'; import { InputMaskModule } from 'primeng/inputmask'; import { SelectButtonModule } from 'primeng/selectbutton'; import { lastValueFrom } from 'rxjs'; import { User } from '../../../../../../bizmatch-server/src/models/db.model'; import { AutoCompleteCompleteEvent, Invoice, Subscription, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model'; import { environment } from '../../../../environments/environment'; import { ImageCropperComponent, stateOptions } from '../../../components/image-cropper/image-cropper.component'; import { GeoService } from '../../../services/geo.service'; import { ImageService } from '../../../services/image.service'; import { LoadingService } from '../../../services/loading.service'; import { SelectOptionsService } from '../../../services/select-options.service'; import { SubscriptionsService } from '../../../services/subscriptions.service'; import { UserService } from '../../../services/user.service'; import { SharedModule } from '../../../shared/shared/shared.module'; import { getDialogWidth, getImageDimensions, map2User } from '../../../utils/utils'; import { TOOLBAR_OPTIONS } from '../../utils/defaults'; @Component({ selector: 'app-account', standalone: true, imports: [SharedModule, FileUploadModule, EditorModule, AngularCropperjsModule, DialogModule, SelectButtonModule, DynamicDialogModule, ConfirmDialogModule, InputMaskModule], providers: [MessageService, DialogService, ConfirmationService], templateUrl: './account.component.html', styleUrl: './account.component.scss', }) export class AccountComponent { @ViewChild('companyUpload') public companyUpload: FileUpload; @ViewChild('profileUpload') public profileUpload: FileUpload; private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined; user: User; subscriptions: Array; userSubscriptions: Array = []; maxFileSize = 15000000; companyLogoUrl: string; profileUrl: string; type: 'company' | 'profile'; dialogRef: DynamicDialogRef | undefined; environment = environment; editorModules = TOOLBAR_OPTIONS; env = environment; faTrash = faTrash; constructor( public userService: UserService, private subscriptionService: SubscriptionsService, private messageService: MessageService, private geoService: GeoService, public selectOptions: SelectOptionsService, private cdref: ChangeDetectorRef, private activatedRoute: ActivatedRoute, private loadingService: LoadingService, private imageUploadService: ImageService, public dialogService: DialogService, private confirmationService: ConfirmationService, private imageService: ImageService, private keycloakService: KeycloakService, ) {} async ngOnInit() { if (this.id) { this.user = await this.userService.getById(this.id); } else { const token = await this.keycloakService.getToken(); const keycloakUser = map2User(token); const email = keycloakUser.email; try { this.user = await this.userService.getByMail(email); } catch (e) { this.user = { email, firstname: keycloakUser.firstName, lastname: keycloakUser.lastName, areasServed: [], licensedIn: [], companyOverview: '', offeredServices: '', customerType: 'broker' }; this.user = await this.userService.save(this.user); } } this.userSubscriptions = await lastValueFrom(this.subscriptionService.getAllSubscriptions(this.user.id)); this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`; this.companyLogoUrl = this.user.hasCompanyLogo ? `${this.env.imageBaseUrl}/pictures/logo/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`; } printInvoice(invoice: Invoice) {} async updateProfile(user: User) { await this.userService.save(this.user); this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Account changes have been persisted', life: 3000 }); } onUploadCompanyLogo(event: any) { const uniqueSuffix = '?_ts=' + new Date().getTime(); this.companyLogoUrl = `${this.env.imageBaseUrl}/pictures/logo/${emailToDirName(this.user.email)}${uniqueSuffix}`; } onUploadProfilePicture(event: any) { const uniqueSuffix = '?_ts=' + new Date().getTime(); this.profileUrl = `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}${uniqueSuffix}`; } setImageToFallback(event: Event) { (event.target as HTMLImageElement).src = `/assets/images/placeholder.png`; // Pfad zum Platzhalterbild } suggestions: string[] | undefined; async search(event: AutoCompleteCompleteEvent) { const result = await lastValueFrom(this.geoService.findCitiesStartingWith(event.query)); this.suggestions = result.map(r => `${r.city} - ${r.state_code}`).slice(0, 5); } addLicence() { this.user.licensedIn.push({ registerNo: '', state: '' }); } removeLicence() { this.user.licensedIn.splice(this.user.licensedIn.length - 1, 1); } addArea() { this.user.areasServed.push({ county: '', state: '' }); } removeArea() { this.user.areasServed.splice(this.user.areasServed.length - 1, 1); } get isProfessional() { return this.user.customerType === 'broker' || this.user.customerType === 'professional'; } select(event: any, type: 'company' | 'profile') { const imageUrl = URL.createObjectURL(event.files[0]); this.type = type; const config = { aspectRatio: type === 'company' ? stateOptions[0].value : stateOptions[2].value }; getImageDimensions(imageUrl).then(dimensions => { const dialogWidth = getDialogWidth(dimensions); this.dialogRef = this.dialogService.open(ImageCropperComponent, { data: { imageUrl: imageUrl, fileUpload: type === 'company' ? this.companyUpload : this.profileUpload, config: config, ratioVariable: type === 'company' ? true : false, }, header: 'Edit Image', width: dialogWidth, modal: true, closeOnEscape: true, keepInViewport: true, closable: false, }); this.dialogRef.onClose.subscribe(cropper => { if (cropper) { this.loadingService.startLoading('uploadImage'); cropper.getCroppedCanvas().toBlob(async blob => { this.imageUploadService.uploadImage(blob, type === 'company' ? 'uploadCompanyLogo' : 'uploadProfile', emailToDirName(this.user.email)).subscribe( async event => { if (event.type === HttpEventType.Response) { this.loadingService.stopLoading('uploadImage'); if (this.type === 'company') { this.user.hasCompanyLogo = true; // this.companyLogoUrl = `${this.env.imageBaseUrl}/pictures/logo/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}`; } else { this.user.hasProfile = true; this.profileUrl = `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}`; } await this.userService.save(this.user); } }, error => console.error('Fehler beim Upload:', error), ); }); } }); }); } deleteConfirm(type: 'profile' | 'logo') { this.confirmationService.confirm({ target: event.target as EventTarget, message: `Do you want to delete your ${type === 'logo' ? 'Logo' : 'Profile'} image`, header: 'Delete Confirmation', icon: 'pi pi-info-circle', acceptButtonStyleClass: 'p-button-danger p-button-text', rejectButtonStyleClass: 'p-button-text p-button-text', acceptIcon: 'none', rejectIcon: 'none', accept: async () => { if (type === 'profile') { this.user.hasProfile = false; await Promise.all([this.imageService.deleteProfileImagesById(this.user.email), this.userService.save(this.user)]); } else { this.user.hasCompanyLogo = false; await Promise.all([this.imageService.deleteLogoImagesById(this.user.email), this.userService.save(this.user)]); } this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Image deleted' }); this.user = await this.userService.getById(this.user.id); }, reject: () => { console.log('deny'); }, }); } }