diff --git a/bizmatch-server/src/models/db.model.ts b/bizmatch-server/src/models/db.model.ts index 970571f..37afe5e 100644 --- a/bizmatch-server/src/models/db.model.ts +++ b/bizmatch-server/src/models/db.model.ts @@ -43,9 +43,6 @@ export interface UserData { updated?: Date; } export interface BusinessListing { - icon?: string; - iconColor?: string; - logo?: string; id: string; userId?: string; type?: number; diff --git a/bizmatch/package.json b/bizmatch/package.json index eeb7bbb..cbd53eb 100644 --- a/bizmatch/package.json +++ b/bizmatch/package.json @@ -29,6 +29,7 @@ "@fortawesome/free-brands-svg-icons": "^6.5.1", "@fortawesome/free-regular-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@ng-select/ng-select": "^12.0.7", "@types/uuid": "^9.0.8", "angular-cropperjs": "^14.0.1", "angular-mixed-cdk-drag-drop": "^2.2.3", @@ -41,11 +42,11 @@ "keycloak-angular": "^15.2.1", "keycloak-js": "^24.0.4", "memoize-one": "^6.0.0", + "ngx-quill": "^25.3.2", "on-change": "^5.0.1", "primeflex": "^3.3.1", "primeicons": "^6.0.1", "primeng": "^17.16.1", - "quill": "^1.3.7", "rxjs": "~7.8.1", "tslib": "^2.3.0", "urlcat": "^3.1.0", @@ -69,6 +70,6 @@ "karma-jasmine-html-reporter": "~2.1.0", "postcss": "^8.4.39", "tailwindcss": "^3.4.4", - "typescript": "~5.3.3" + "typescript": "~5.4.5" } -} +} \ No newline at end of file diff --git a/bizmatch/src/app/app.config.ts b/bizmatch/src/app/app.config.ts index 40519b3..14ea129 100644 --- a/bizmatch/src/app/app.config.ts +++ b/bizmatch/src/app/app.config.ts @@ -4,6 +4,7 @@ import { provideRouter, withEnabledBlockingInitialNavigation, withInMemoryScroll import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; import { provideAnimations } from '@angular/platform-browser/animations'; import { KeycloakBearerInterceptor, KeycloakService } from 'keycloak-angular'; +import { provideQuillConfig } from 'ngx-quill'; import { environment } from '../environments/environment'; import { customKeycloakAdapter } from '../keycloak'; import { routes } from './app.routes'; @@ -51,6 +52,12 @@ export const appConfig: ApplicationConfig = { }), ), provideAnimations(), + provideQuillConfig({ + modules: { + syntax: true, + toolbar: [['bold', 'italic', 'underline', 'strike'], [{ list: 'ordered' }, { list: 'bullet' }], [{ header: [1, 2, 3, 4, 5, 6, false] }], [{ color: [] }, { background: [] }], ['clean']], + }, + }), ], }; function initServices(selectOptions: SelectOptionsService) { diff --git a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html index 7324ef1..7e74e89 100644 --- a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html +++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html @@ -1,14 +1,12 @@ -
+ @if(historyService.canGoBack){ }
- @if(listing){
@@ -91,7 +89,6 @@
-
@@ -119,4 +116,110 @@ }
+ --> + +
+
+ +
+ +
+

{{ listing.title }}

+

+ +
+
+
{{ item.label }}
+ @if(item.label==='Category'){ + {{ item.value }} + } @else { +
{{ item.value }}
+ } +
+
+ @if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){ + + } +
+ + +
+

Contact the Author of this Listing

+

Please include your contact info below

+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ + +
+ @if(listingUser){ +
+

Listing by

+ + {{ listingUser.firstname }} {{ listingUser.lastname }} + + @if(listingUser.hasCompanyLogo){ + + } +
+ } + +
+
+
+
diff --git a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.scss b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.scss index e69de29..2bc0dfe 100644 --- a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.scss +++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.scss @@ -0,0 +1,36 @@ +::ng-deep p { + display: block; + margin-top: 1em; + margin-bottom: 1em; + margin-left: 0; + margin-right: 0; + font-size: 1rem; /* oder 1rem, abhängig vom Browser und den Standardeinstellungen */ + line-height: 1.5; +} +::ng-deep h1 { + display: block; + font-size: 2em; /* etwa 32px */ + margin-top: 0.67em; + margin-bottom: 0.67em; + margin-left: 0; + margin-right: 0; + font-weight: bold; +} +::ng-deep h2 { + display: block; + font-size: 1.5em; /* etwa 24px */ + margin-top: 0.83em; + margin-bottom: 0.83em; + margin-left: 0; + margin-right: 0; + font-weight: bold; +} +::ng-deep h3 { + display: block; + font-size: 1.17em; /* etwa 18.72px */ + margin-top: 1em; + margin-bottom: 1em; + margin-left: 0; + margin-right: 0; + font-weight: bold; +} diff --git a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts index 7b62618..1e986c3 100644 --- a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts +++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts @@ -99,4 +99,27 @@ export class DetailsBusinessListingComponent { await this.mailService.mail(this.mailinfo); this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Your message has been sent to the creator of the listing', life: 3000 }); } + get listingDetails() { + let typeOfRealEstate = ''; + if (this.listing.realEstateIncluded) { + typeOfRealEstate = 'Real Estate Included'; + } else if (this.listing.leasedLocation) { + typeOfRealEstate = 'Leased Location'; + } else if (this.listing.franchiseResale) { + typeOfRealEstate = 'Franchise Re-Sale'; + } + return [ + { label: 'Category', value: this.selectOptions.getBusiness(this.listing.type) }, + { label: 'Located in', value: `${this.listing.city}, ${this.selectOptions.getState(this.listing.state)}` }, + { label: 'Asking Price', value: `$${this.listing.price?.toLocaleString()}` }, + { label: 'Sales revenue', value: `$${this.listing.salesRevenue?.toLocaleString()}` }, + { label: 'Cash flow', value: `$${this.listing.cashFlow?.toLocaleString()}` }, + { label: 'Type of Real Estate', value: typeOfRealEstate }, + { label: 'Employees', value: this.listing.employees }, + { label: 'Established since', value: this.listing.established }, + { label: 'Support & Training', value: this.listing.supportAndTraining }, + { label: 'Reason for Sale', value: this.listing.reasonForSale }, + { label: 'Broker licensing', value: this.listing.brokerLicencing }, + ]; + } } diff --git a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html index 0571ee7..732cee7 100644 --- a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html +++ b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.html @@ -1,4 +1,4 @@ -
+
@@ -117,7 +116,6 @@
-
@@ -140,10 +138,7 @@
- - - Draft Mode (Will not be shown as public listing)
@@ -160,4 +155,149 @@ - + --> +
+
+

Edit Listing

+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ +
+ + +
+
+
diff --git a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.scss b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.scss index 88018d9..4f41257 100644 --- a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.scss +++ b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.scss @@ -1,57 +1,28 @@ -.translate-y-5 { - transform: translateY(5px); +:host { + display: block; + font-family: 'Inter', sans-serif; } -.image-container { - display: flex; /* Erlaubt ein flexibles Box-Layout */ - flex-wrap: wrap; /* Erlaubt das Umfließen der Elemente auf die nächste Zeile */ - justify-content: flex-start; /* Startet die Anordnung der Elemente am Anfang des Containers */ - align-items: flex-start; /* Ausrichtung der Elemente am Anfang der Querachse */ - padding: 10px; /* Abstand zwischen den Inhalten des Containers und dessen Rand */ - } +// .container { +// max-width: 100%; +// margin: 0 auto; +// } -.image-container span { - flex-flow: row; - display: flex; - width: fit-content; - height: fit-content; +::ng-deep quill-editor { + .ql-container { + min-height: 200px; + } } -.image-container span img { - max-height: 150px; /* Maximale Höhe der Bilder */ - width: auto; /* Die Breite der Bilder passt sich automatisch an die Höhe an */ - cursor: pointer; - margin: 10px; +input[type='checkbox'] { + &:checked + .dot { + transform: translateX(100%); + } + &:checked + .block { + background-color: #4299e1; + } } -// .image-container fa-icon { -// top: 0; /* Positioniert das Icon am oberen Rand des Bildes */ -// right: 0; /* Positioniert das Icon am rechten Rand des Bildes */ -// color: #fff; /* Weiße Farbe für das Icon */ -// background-color: rgba(0,0,0,0.5); /* Halbtransparenter Hintergrund für bessere Sichtbarkeit */ -// padding: 5px; /* Ein wenig Platz um das Icon */ -// cursor: pointer; /* Verwandelt den Cursor in eine Hand, um Interaktivität anzudeuten */ -// } - .image-wrap { - position: relative; /* Ermöglicht die absolute Positionierung des Icons bezogen auf diesen Container */ - display: inline-block; /* Erlaubt die Inline-Anordnung, falls mehrere Bilder vorhanden sind */ - } - - /* Stil für das Bild */ - .image-wrap img { - max-height: 150px; - width: auto; - display: block; /* Verhindert unerwünschten Abstand unter dem Bild */ - } - - /* Stil für das FontAwesome Icon */ - .image-wrap fa-icon { - position: absolute; - top: 15px; /* Positioniert das Icon am oberen Rand des Bildes */ - right: 15px; /* Positioniert das Icon am rechten Rand des Bildes */ - color: #fff; /* Weiße Farbe für das Icon */ - background-color: rgba(0,0,0,0.5); /* Halbtransparenter Hintergrund für bessere Sichtbarkeit */ - padding: 5px; /* Ein wenig Platz um das Icon */ - cursor: pointer; /* Verwandelt den Cursor in eine Hand, um Interaktivität anzudeuten */ - border-radius: 8px; /* Optional: Abrunden der linken unteren Ecke für ästhetische Zwecke */ - } \ No newline at end of file +.dot { + transition: all 0.3s ease-in-out; +} diff --git a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts index 5bd37e5..e421b45 100644 --- a/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts +++ b/bizmatch/src/app/pages/subscription/edit-business-listing/edit-business-listing.component.ts @@ -10,6 +10,7 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { AngularCropperjsModule } from 'angular-cropperjs'; import { MixedCdkDragDropModule } from 'angular-mixed-cdk-drag-drop'; import { KeycloakService } from 'keycloak-angular'; +import { QuillModule } from 'ngx-quill'; import { ConfirmationService, MessageService } from 'primeng/api'; import { CarouselModule } from 'primeng/carousel'; import { ConfirmDialogModule } from 'primeng/confirmdialog'; @@ -44,6 +45,7 @@ import { TOOLBAR_OPTIONS } from '../../utils/defaults'; DragDropModule, ConfirmDialogModule, MixedCdkDragDropModule, + QuillModule, ], providers: [MessageService, DialogService, ConfirmationService], templateUrl: './edit-business-listing.component.html', @@ -85,6 +87,9 @@ export class EditBusinessListingComponent { faTrash = faTrash; data: CommercialPropertyListing; typesOfBusiness = []; + quillModules = { + toolbar: [['bold', 'italic', 'underline', 'strike'], [{ list: 'ordered' }, { list: 'bullet' }], [{ header: [1, 2, 3, 4, 5, 6, false] }], [{ color: [] }, { background: [] }], ['clean']], + }; constructor( public selectOptions: SelectOptionsService, private router: Router,