Validation first Part
This commit is contained in:
parent
55e800009e
commit
2955c034a0
|
|
@ -277,3 +277,7 @@ export function emailToDirName(email: string): string {
|
|||
return normalizedEmail;
|
||||
}
|
||||
export const LISTINGS_PER_PAGE = 12;
|
||||
export interface ValidationMessage {
|
||||
field: string;
|
||||
message: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<p>validated-input works!</p>
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
|
||||
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-validated-input',
|
||||
template: `
|
||||
<div>
|
||||
<label [for]="id" class="block text-sm font-medium text-gray-700">
|
||||
{{ label }}
|
||||
<span class="text-red-500 ml-1">{{ validationMessage }}</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
[ngModel]="value"
|
||||
(input)="onInputChange($event)"
|
||||
(blur)="onTouched()"
|
||||
[attr.name]="name"
|
||||
[required]="required"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
|
||||
/>
|
||||
</div>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule],
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => ValidatedInputComponent),
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class ValidatedInputComponent implements ControlValueAccessor {
|
||||
@Input() label: string = '';
|
||||
@Input() id: string = '';
|
||||
@Input() name: string = '';
|
||||
@Input() type: string = 'text';
|
||||
@Input() required: boolean = false;
|
||||
@Input() validationMessage: string = '';
|
||||
|
||||
@Input() value: any = '';
|
||||
@Output() valueChange = new EventEmitter<any>();
|
||||
|
||||
onChange: any = () => {};
|
||||
onTouched: any = () => {};
|
||||
|
||||
writeValue(value: any): void {
|
||||
if (value !== undefined) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: any): void {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any): void {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
onInputChange(event: Event): void {
|
||||
const value = (event.target as HTMLInputElement).value;
|
||||
this.value = value;
|
||||
this.onChange(value);
|
||||
this.valueChange.emit(value);
|
||||
}
|
||||
|
||||
setDisabledState?(isDisabled: boolean): void {
|
||||
// Implementieren Sie dies, wenn Sie die Deaktivierung des Inputs unterstützen möchten
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<p>validated-select works!</p>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
|
||||
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-validated-select',
|
||||
template: `
|
||||
<div>
|
||||
<label [for]="id" class="block text-sm font-medium text-gray-700">
|
||||
{{ label }}
|
||||
<span class="text-red-500 ml-1">{{ validationMessage }}</span>
|
||||
</label>
|
||||
<select
|
||||
[id]="id"
|
||||
[name]="name"
|
||||
[ngModel]="value"
|
||||
(change)="onSelectChange($event)"
|
||||
(blur)="onTouched()"
|
||||
[required]="required"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
|
||||
>
|
||||
<option value="" disabled selected>Select an option</option>
|
||||
<option *ngFor="let option of options" [value]="option.value">
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule],
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => ValidatedSelectComponent),
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class ValidatedSelectComponent implements ControlValueAccessor {
|
||||
@Input() label: string = '';
|
||||
@Input() id: string = '';
|
||||
@Input() name: string = '';
|
||||
@Input() required: boolean = false;
|
||||
@Input() validationMessage: string = '';
|
||||
@Input() options: Array<{ value: any; label: string }> = [];
|
||||
|
||||
@Input() value: any = '';
|
||||
@Output() valueChange = new EventEmitter<any>();
|
||||
|
||||
onChange: any = () => {};
|
||||
onTouched: any = () => {};
|
||||
|
||||
writeValue(value: any): void {
|
||||
if (value !== undefined) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: any): void {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any): void {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
onSelectChange(event: Event): void {
|
||||
const value = (event.target as HTMLSelectElement).value;
|
||||
this.value = value;
|
||||
this.onChange(value);
|
||||
this.valueChange.emit(value);
|
||||
}
|
||||
|
||||
setDisabledState?(isDisabled: boolean): void {
|
||||
// Implementieren Sie dies, wenn Sie die Deaktivierung des Selects unterstützen möchten
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div class="md:col-span-2">
|
||||
<label for="email" class="block text-sm font-medium text-gray-700">E-mail (required)</label>
|
||||
<input type="email" id="email" name="email" [(ngModel)]="user.email" required class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" />
|
||||
<input type="email" id="email" name="email" [(ngModel)]="user.email" disabled class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" />
|
||||
<p class="text-xs text-gray-500 mt-1">You can only modify your email by contacting us at support@bizwatch.net</p>
|
||||
</div>
|
||||
@if (isProfessional){
|
||||
|
|
@ -60,23 +60,26 @@
|
|||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label for="firstname" class="block text-sm font-medium text-gray-700">First Name</label>
|
||||
<input type="text" id="firstname" name="firstname" [(ngModel)]="user.firstname" required class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="lastname" class="block text-sm font-medium text-gray-700">Last Name</label>
|
||||
<input type="text" id="lastname" name="lastname" [(ngModel)]="user.lastname" required class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500" />
|
||||
</div>
|
||||
<app-validated-input label="First Name" name="firstname" [(ngModel)]="user.firstname" [required]="true" [validationMessage]="getValidationMessage('firstname')"></app-validated-input>
|
||||
<app-validated-input label="Last Name" name="lastname" [(ngModel)]="user.lastname" [required]="true" [validationMessage]="getValidationMessage('lastname')"></app-validated-input>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<!-- <div>
|
||||
<label for="customerType" class="block text-sm font-medium text-gray-700">Customer Type</label>
|
||||
<select id="customerType" name="customerType" [(ngModel)]="user.customerType" required class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
|
||||
<option *ngFor="let type of customerTypes" [value]="type">{{ type | titlecase }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div> -->
|
||||
<app-validated-select
|
||||
label="Customer Type"
|
||||
id="customerType"
|
||||
name="customerType"
|
||||
[(ngModel)]="user.customerType"
|
||||
[required]="true"
|
||||
[validationMessage]="getValidationMessage('customerType')"
|
||||
[options]="customerTypeOptions"
|
||||
></app-validated-select>
|
||||
@if (isProfessional){
|
||||
<div>
|
||||
<label for="customerSubType" class="block text-sm font-medium text-gray-700">Professional Type</label>
|
||||
|
|
@ -223,7 +226,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Responsive version for small screens -->
|
||||
<div class="mt-8 sm:hidden">
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-1">Membership Level</h3>
|
||||
<div class="space-y-2">
|
||||
|
|
@ -264,270 +266,5 @@
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- @if(showModal){ -->
|
||||
<app-image-crop-and-upload [uploadParams]="uploadParams" (uploadFinished)="uploadFinished($event)"></app-image-crop-and-upload>
|
||||
<app-confirmation></app-confirmation>
|
||||
<!-- } -->
|
||||
<!-- <div class="surface-ground px-4 py-8 md:px-6 lg:px-8">
|
||||
<div class="p-fluid flex flex-column lg:flex-row">
|
||||
<menu-account></menu-account>
|
||||
<p-toast></p-toast>
|
||||
<div class="surface-card p-5 shadow-2 border-round flex-auto">
|
||||
<div class="text-900 font-semibold text-lg mt-3">Account Details</div>
|
||||
<p-divider></p-divider>
|
||||
<div class="flex gap-5 flex-column-reverse md:flex-row">
|
||||
<div class="flex-auto p-fluid">
|
||||
@if (user){
|
||||
<div class="grid">
|
||||
<div class="mb-4 col-12 md:col-4">
|
||||
<label for="state" class="block font-medium text-900 mb-2">E-mail (required)</label>
|
||||
<input id="state" type="text" [disabled]="true" pInputText [(ngModel)]="user.email" />
|
||||
<p class="font-italic text-xs line-height-1">You can only modify your email by contacting us at support@bizmatch.net</p>
|
||||
</div>
|
||||
<div class="mb-4 col-12 md:col-4">
|
||||
<label for="customerType" class="block font-medium text-900 mb-2">Customer Type</label>
|
||||
<p-dropdown id="customerType" [options]="selectOptions?.customerTypes" [(ngModel)]="user.customerType" optionLabel="name" optionValue="value" placeholder="State" [style]="{ width: '100%' }"></p-dropdown>
|
||||
</div>
|
||||
<div class="mb-4 col-12 md:col-4">
|
||||
<label for="customerType" class="block font-medium text-900 mb-2">Professional Role</label>
|
||||
<p-dropdown
|
||||
id="customerSubType"
|
||||
[options]="selectOptions?.customerSubTypes"
|
||||
[(ngModel)]="user.customerSubType"
|
||||
optionLabel="name"
|
||||
optionValue="value"
|
||||
placeholder="State"
|
||||
[style]="{ width: '100%' }"
|
||||
></p-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<div class="mb-4 col-12 md:col-6">
|
||||
<label for="firstname" class="block font-medium text-900 mb-2">First Name</label>
|
||||
<input id="firstname" type="text" pInputText [(ngModel)]="user.firstname" />
|
||||
</div>
|
||||
<div class="mb-4 col-12 md:col-6">
|
||||
<label for="lastname" class="block font-medium text-900 mb-2">Last Name</label>
|
||||
<input id="lastname" type="text" pInputText [(ngModel)]="user.lastname" />
|
||||
</div>
|
||||
</div>
|
||||
@if (isProfessional){
|
||||
<div class="grid">
|
||||
<div class="mb-4 col-12 md:col-6">
|
||||
<label for="firstname" class="block font-medium text-900 mb-2">Company Name</label>
|
||||
<input id="firstname" type="text" pInputText [(ngModel)]="user.companyName" />
|
||||
</div>
|
||||
<div class="mb-4 col-12 md:col-6">
|
||||
<label for="lastname" class="block font-medium text-900 mb-2">Describe yourself</label>
|
||||
<input id="lastname" type="text" pInputText [(ngModel)]="user.description" />
|
||||
</div>
|
||||
</div>
|
||||
} @if (isProfessional){
|
||||
<div class="grid">
|
||||
<div class="mb-4 col-12 md:col-4">
|
||||
<label for="phoneNumber" class="block font-medium text-900 mb-2">Your Phone Number</label>
|
||||
<p-inputMask mask="(999) 999-9999" placeholder="(123) 456-7890" [(ngModel)]="user.phoneNumber"></p-inputMask>
|
||||
</div>
|
||||
<div class="mb-4 col-12 md:col-4">
|
||||
<label for="companyWebsite" class="block font-medium text-900 mb-2">Company Website</label>
|
||||
<input id="companyWebsite" type="text" pInputText [(ngModel)]="user.companyWebsite" />
|
||||
</div>
|
||||
<div class="mb-4 col-12 md:col-4">
|
||||
<label for="companyLocation" class="block font-medium text-900 mb-2">Company Location</label>
|
||||
<p-autoComplete [(ngModel)]="user.companyLocation" [suggestions]="suggestions" (completeMethod)="search($event)"></p-autoComplete>
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="grid">
|
||||
<div class="mb-4 col-12 md:col-6">
|
||||
<label for="phoneNumber" class="block font-medium text-900 mb-2">Your Phone Number</label>
|
||||
<p-inputMask mask="(999) 999-9999" placeholder="(123) 456-7890" [(ngModel)]="user.phoneNumber"></p-inputMask>
|
||||
</div>
|
||||
</div>
|
||||
} @if (isProfessional){
|
||||
<div class="mb-4">
|
||||
<label for="companyOverview" class="block font-medium text-900 mb-2">Company Overview</label>
|
||||
<p-editor [(ngModel)]="user.companyOverview" [style]="{ height: '320px' }" [modules]="editorModules">
|
||||
<ng-template pTemplate="header"></ng-template>
|
||||
</p-editor>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="companyOverview" class="block font-medium text-900 mb-2">Services We offer</label>
|
||||
<p-editor [(ngModel)]="user.offeredServices" [style]="{ height: '320px' }" [modules]="editorModules">
|
||||
<ng-template pTemplate="header"></ng-template>
|
||||
</p-editor>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="areasServed" class="block font-medium text-900 mb-2">Areas We Serve</label>
|
||||
@for (areasServed of user.areasServed; track areasServed){
|
||||
<div class="grid">
|
||||
<div class="flex col-12 md:col-6">
|
||||
<p-dropdown
|
||||
[filter]="true"
|
||||
filterBy="name"
|
||||
id="states"
|
||||
[options]="selectOptions?.states"
|
||||
[(ngModel)]="areasServed.state"
|
||||
optionLabel="name"
|
||||
optionValue="value"
|
||||
placeholder="State"
|
||||
[ngStyle]="{ width: '100%' }"
|
||||
></p-dropdown>
|
||||
</div>
|
||||
<div class="flex col-12 md:col-6">
|
||||
<input id="county" type="text" pInputText [(ngModel)]="areasServed.county" placeholder="Area/County Served" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="field mb-5 col-12 md:col-6 flex align-items-center">
|
||||
<p-button class="mr-1" icon="pi pi-plus" severity="success" (click)="addArea()"></p-button>
|
||||
<p-button icon="pi pi-minus" severity="danger" (click)="removeArea()" [disabled]="user.areasServed?.length < 2"></p-button>
|
||||
<span class="text-xs"> (Add more Areas or remove existing ones.)</span>
|
||||
</div>
|
||||
<div>
|
||||
<label for="companyOverview" class="block font-medium text-900 mb-2">Licensed In</label>
|
||||
@for (licensedIn of user.licensedIn; track licensedIn){
|
||||
<div class="grid">
|
||||
<div class="flex col-12 md:col-6">
|
||||
<p-dropdown
|
||||
[filter]="true"
|
||||
filterBy="name"
|
||||
id="states"
|
||||
[options]="selectOptions?.states"
|
||||
[(ngModel)]="licensedIn.state"
|
||||
optionLabel="name"
|
||||
optionValue="value"
|
||||
placeholder="State"
|
||||
[ngStyle]="{ width: '100%' }"
|
||||
></p-dropdown>
|
||||
</div>
|
||||
<div class="flex col-12 md:col-6">
|
||||
<input id="registerNo" type="text" pInputText [(ngModel)]="licensedIn.registerNo" placeholder="Licence Number" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="field mb-5 col-12 md:col-6 flex align-items-center">
|
||||
<p-button class="mr-1" icon="pi pi-plus" severity="success" (click)="addLicence()"></p-button>
|
||||
<p-button icon="pi pi-minus" severity="danger" (click)="removeLicence()" [disabled]="user.licensedIn?.length < 2"></p-button>
|
||||
<span class="text-xs"> (Add more licenses or remove existing ones.)</span>
|
||||
</div>
|
||||
} }
|
||||
<div>
|
||||
<button pButton pRipple label="Update Profile" class="w-auto" (click)="updateProfile(user)"></button>
|
||||
</div>
|
||||
</div>
|
||||
@if (isProfessional){
|
||||
<div>
|
||||
<div class="flex flex-column align-items-center flex-or mb-8">
|
||||
<span class="font-medium text-900 mb-2">Company Logo</span>
|
||||
<span class="font-medium text-xs mb-2">(is shown in every offer)</span>
|
||||
@if(user?.hasCompanyLogo){
|
||||
<div class="image-wrap">
|
||||
<img src="{{ companyLogoUrl }}" class="rounded-profile" />
|
||||
<fa-icon [icon]="faTrash" (click)="deleteConfirm('logo')"></fa-icon>
|
||||
</div>
|
||||
} @else {
|
||||
<img src="assets/images/placeholder.png" class="rounded-profile" />
|
||||
}
|
||||
<p-fileUpload
|
||||
#companyUpload
|
||||
mode="basic"
|
||||
chooseLabel="Upload"
|
||||
name="file"
|
||||
[customUpload]="true"
|
||||
accept="image/*"
|
||||
[maxFileSize]="maxFileSize"
|
||||
(onSelect)="select($event, 'company')"
|
||||
styleClass="p-button-outlined p-button-plain p-button-rounded mt-4"
|
||||
></p-fileUpload>
|
||||
</div>
|
||||
<p-divider></p-divider>
|
||||
<div class="flex flex-column align-items-center flex-or">
|
||||
<span class="font-medium text-900 mb-2">Your Profile Picture</span>
|
||||
@if(user?.hasProfile){
|
||||
<div class="image-wrap">
|
||||
<img src="{{ profileUrl }}" class="rounded-profile" />
|
||||
<fa-icon [icon]="faTrash" (click)="deleteConfirm('profile')"></fa-icon>
|
||||
</div>
|
||||
} @else {
|
||||
<img src="assets/images/person_placeholder.jpg" class="rounded-profile" />
|
||||
}
|
||||
<p-fileUpload
|
||||
#profileUpload
|
||||
mode="basic"
|
||||
chooseLabel="Upload"
|
||||
name="file"
|
||||
[customUpload]="true"
|
||||
accept="image/*"
|
||||
[maxFileSize]="maxFileSize"
|
||||
(onSelect)="select($event, 'profile')"
|
||||
styleClass="p-button-outlined p-button-plain p-button-rounded mt-4"
|
||||
></p-fileUpload>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="text-900 font-semibold text-lg mt-3">Membership Level</div>
|
||||
<p-divider></p-divider>
|
||||
<p-table [value]="userSubscriptions" [tableStyle]="{ 'min-width': '50rem' }" dataKey="id">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th style="width: 5rem"></th>
|
||||
<th>ID</th>
|
||||
<th>Level</th>
|
||||
<th>Start Date</th>
|
||||
<th>Date Modified</th>
|
||||
<th>End Date</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-subscription let-expanded="expanded">
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" pButton pRipple [pRowToggler]="subscription" class="p-button-text p-button-rounded p-button-plain" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
|
||||
</td>
|
||||
<td>{{ subscription.id }}</td>
|
||||
<td>{{ subscription.level }}</td>
|
||||
<td>{{ subscription.start | date }}</td>
|
||||
<td>{{ subscription.modified | date }}</td>
|
||||
<td>{{ subscription.end | date }}</td>
|
||||
<td>{{ subscription.status }}</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="rowexpansion" let-subscription>
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
<div class="p-3">
|
||||
<p-table [value]="subscription.invoices" dataKey="id">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th style="width: 5rem"></th>
|
||||
<th>ID</th>
|
||||
<th>Date</th>
|
||||
<th>Price</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-invoice>
|
||||
<tr>
|
||||
<td>
|
||||
<button pButton pRipple icon="pi pi-print" class="p-button-rounded p-button-success mr-2" (click)="printInvoice(invoice)"></button>
|
||||
</td>
|
||||
<td>{{ invoice.id }}</td>
|
||||
<td>{{ invoice.date | date }}</td>
|
||||
<td>{{ invoice.price | currency }}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p-confirmDialog></p-confirmDialog> -->
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { TitleCasePipe } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { faTrash } from '@fortawesome/free-solid-svg-icons';
|
||||
|
|
@ -8,13 +9,15 @@ import { ImageCropperComponent } from 'ngx-image-cropper';
|
|||
import { QuillModule } from 'ngx-quill';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { AutoCompleteCompleteEvent, Invoice, Subscription, UploadParams, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { AutoCompleteCompleteEvent, Invoice, Subscription, UploadParams, ValidationMessage, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { ConfirmationComponent } from '../../../components/confirmation/confirmation.component';
|
||||
import { ConfirmationService } from '../../../components/confirmation/confirmation.service';
|
||||
import { ImageCropAndUploadComponent, UploadReponse } from '../../../components/image-crop-and-upload/image-crop-and-upload.component';
|
||||
import { MessageComponent } from '../../../components/message/message.component';
|
||||
import { MessageService } from '../../../components/message/message.service';
|
||||
import { ValidatedInputComponent } from '../../../components/validated-input/validated-input.component';
|
||||
import { ValidatedSelectComponent } from '../../../components/validated-select/validated-select.component';
|
||||
import { GeoService } from '../../../services/geo.service';
|
||||
import { ImageService } from '../../../services/image.service';
|
||||
import { LoadingService } from '../../../services/loading.service';
|
||||
|
|
@ -28,8 +31,19 @@ import { TOOLBAR_OPTIONS } from '../../utils/defaults';
|
|||
@Component({
|
||||
selector: 'app-account',
|
||||
standalone: true,
|
||||
imports: [SharedModule, QuillModule, NgxCurrencyDirective, NgSelectModule, ImageCropperComponent, ConfirmationComponent, ImageCropAndUploadComponent, MessageComponent],
|
||||
providers: [],
|
||||
imports: [
|
||||
SharedModule,
|
||||
QuillModule,
|
||||
NgxCurrencyDirective,
|
||||
NgSelectModule,
|
||||
ImageCropperComponent,
|
||||
ConfirmationComponent,
|
||||
ImageCropAndUploadComponent,
|
||||
MessageComponent,
|
||||
ValidatedInputComponent,
|
||||
ValidatedSelectComponent,
|
||||
],
|
||||
providers: [TitleCasePipe],
|
||||
templateUrl: './account.component.html',
|
||||
styleUrl: './account.component.scss',
|
||||
})
|
||||
|
|
@ -51,6 +65,9 @@ export class AccountComponent {
|
|||
toolbar: [['bold', 'italic', 'underline', 'strike'], [{ list: 'ordered' }, { list: 'bullet' }], [{ header: [1, 2, 3, 4, 5, 6, false] }], [{ color: [] }, { background: [] }], ['clean']],
|
||||
};
|
||||
uploadParams: UploadParams;
|
||||
validationMessages: ValidationMessage[] = [];
|
||||
customerTypeOptions: Array<{ value: string; label: string }> = [];
|
||||
customerSubTypeOptions: Array<{ value: string; label: string }> = [];
|
||||
constructor(
|
||||
public userService: UserService,
|
||||
private subscriptionService: SubscriptionsService,
|
||||
|
|
@ -65,6 +82,7 @@ export class AccountComponent {
|
|||
private confirmationService: ConfirmationService,
|
||||
private messageService: MessageService,
|
||||
private sharedService: SharedService,
|
||||
private titleCasePipe: TitleCasePipe,
|
||||
) {}
|
||||
async ngOnInit() {
|
||||
if (this.id) {
|
||||
|
|
@ -95,6 +113,16 @@ export class AccountComponent {
|
|||
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`;
|
||||
|
||||
this.customerTypeOptions = this.customerTypes.map(type => ({
|
||||
value: type,
|
||||
label: this.titleCasePipe.transform(type),
|
||||
}));
|
||||
|
||||
this.customerSubTypeOptions = this.customerSubTypes.map(type => ({
|
||||
value: type,
|
||||
label: this.titleCasePipe.transform(type),
|
||||
}));
|
||||
}
|
||||
printInvoice(invoice: Invoice) {}
|
||||
|
||||
|
|
@ -182,76 +210,8 @@ export class AccountComponent {
|
|||
});
|
||||
}
|
||||
}
|
||||
// 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),
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
// this.confirmationService.showConfirmation({
|
||||
// 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');
|
||||
// },
|
||||
// });
|
||||
getValidationMessage(fieldName: string): string {
|
||||
const message = this.validationMessages.find(msg => msg.field === fieldName);
|
||||
return message ? message.message : '';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ export class EditBusinessListingComponent {
|
|||
}
|
||||
});
|
||||
this.typesOfBusiness = selectOptions.typesOfBusiness.map(e => {
|
||||
return { name: e.name, value: parseInt(e.value) };
|
||||
return { name: e.name, value: e.value };
|
||||
});
|
||||
}
|
||||
async ngOnInit() {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ export class EditCommercialPropertyListingComponent {
|
|||
}
|
||||
});
|
||||
this.typesOfCommercialProperty = selectOptions.typesOfCommercialProperty.map(e => {
|
||||
return { name: e.name, value: parseInt(e.value) };
|
||||
return { name: e.name, value: e.value };
|
||||
});
|
||||
}
|
||||
async ngOnInit() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue