diff --git a/bizmatch-server/src/file/file.service.ts b/bizmatch-server/src/file/file.service.ts index a5e09d9..5f504f6 100644 --- a/bizmatch-server/src/file/file.service.ts +++ b/bizmatch-server/src/file/file.service.ts @@ -53,7 +53,7 @@ export class FileService { // await fs.outputFile(`./pictures/logo/${userId}`, file.buffer); } hasCompanyLogo(userId: string){ - return fs.existsSync(`./pictures/logo/${userId}.avif`) + return fs.existsSync(`./pictures/logo/${userId}.avif`)?true:false } async getPropertyImages(listingId: string): Promise { diff --git a/bizmatch-server/src/listings/commercial-property-listings.controller.ts b/bizmatch-server/src/listings/commercial-property-listings.controller.ts index 612ae66..9bd5113 100644 --- a/bizmatch-server/src/listings/commercial-property-listings.controller.ts +++ b/bizmatch-server/src/listings/commercial-property-listings.controller.ts @@ -21,10 +21,10 @@ export class CommercialPropertyListingsController { // findByUserId(@Param('userid') userid:string): any { // return this.listingsService.findByUserId(userid,commercials); // } - // @Post('search') - // find(@Body() criteria: ListingCriteria): any { - // return this.listingsService.findByState(criteria.state,commercials); - // } + @Post('search') + find(@Body() criteria: ListingCriteria): any { + return this.listingsService.findListingsByCriteria(criteria,commercials); + } @Post() create(@Body() listing: any){ diff --git a/bizmatch-server/src/listings/listings.service.ts b/bizmatch-server/src/listings/listings.service.ts index 39ecf15..e75d777 100644 --- a/bizmatch-server/src/listings/listings.service.ts +++ b/bizmatch-server/src/listings/listings.service.ts @@ -23,25 +23,25 @@ export class ListingsService { constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, @Inject(PG_CONNECTION) private conn: NodePgDatabase,) { } - private getConditions(criteria: ListingCriteria): any[] { + private getConditions(criteria: ListingCriteria,table: typeof businesses | typeof commercials): any[] { const conditions = []; if (criteria.type) { - conditions.push(eq(businesses.type, criteria.type)); + conditions.push(eq(table.type, criteria.type)); } if (criteria.state) { - conditions.push(eq(businesses.state, criteria.state)); + conditions.push(eq(table.state, criteria.state)); } if (criteria.minPrice) { - conditions.push(gte(businesses.price, criteria.minPrice)); + conditions.push(gte(table.price, criteria.minPrice)); } if (criteria.maxPrice) { - conditions.push(lte(businesses.price, criteria.maxPrice)); + conditions.push(lte(table.price, criteria.maxPrice)); } if (criteria.realEstateChecked) { conditions.push(eq(businesses.realEstateIncluded, true)); } if (criteria.title) { - conditions.push(ilike(businesses.title, `%${criteria.title}%`)); + conditions.push(ilike(table.title, `%${criteria.title}%`)); } return conditions; } @@ -54,7 +54,7 @@ export class ListingsService { return await this.findListings(table, criteria, start, length) } private async findListings(table: typeof businesses | typeof commercials, criteria: ListingCriteria, start = 0, length = 12): Promise { - const conditions = this.getConditions(criteria) + const conditions = this.getConditions(criteria,table) const [data, total] = await Promise.all([ this.conn.select().from(table).where(and(...conditions)).offset(start).limit(length), this.conn.select({ count: sql`count(*)` }).from(table).where(and(...conditions)).then((result) => Number(result[0].count)), diff --git a/bizmatch-server/src/models/main.model.ts b/bizmatch-server/src/models/main.model.ts index 3fa2773..9826416 100644 --- a/bizmatch-server/src/models/main.model.ts +++ b/bizmatch-server/src/models/main.model.ts @@ -56,7 +56,6 @@ export interface ListingCriteria { maxPrice:number, realEstateChecked:boolean, title:string, - listingsCategory:'business' | 'commercialProperty', category:'professional|broker' } diff --git a/bizmatch-server/src/user/user.controller.ts b/bizmatch-server/src/user/user.controller.ts index 8166c25..55a233c 100644 --- a/bizmatch-server/src/user/user.controller.ts +++ b/bizmatch-server/src/user/user.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Inject, Param, Post, Put } from '@nestjs/common'; +import { Body, Controller, Get, Inject, Param, Post, Put, Query, Req } from '@nestjs/common'; import { UserService } from './user.service.js'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; @@ -9,6 +9,13 @@ export class UserController { constructor(private userService: UserService, @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {} + @Get() + findByMail(@Query('mail') mail: string): any { + this.logger.info(`Searching for user with EMail: ${mail}`); + const user = this.userService.getUserByMail(mail); + this.logger.info(`Found user: ${JSON.stringify(user)}`); + return user; + } @Get(':id') findById(@Param('id') id: string): any { this.logger.info(`Searching for user with ID: ${id}`); @@ -16,7 +23,6 @@ export class UserController { this.logger.info(`Found user: ${JSON.stringify(user)}`); return user; } - @Post() save(@Body() user: any): Promise { this.logger.info(`Saving user: ${JSON.stringify(user)}`); diff --git a/bizmatch-server/src/user/user.service.ts b/bizmatch-server/src/user/user.service.ts index 0763bf0..156a959 100644 --- a/bizmatch-server/src/user/user.service.ts +++ b/bizmatch-server/src/user/user.service.ts @@ -20,10 +20,17 @@ export class UserService { private getConditions(criteria: ListingCriteria): any[] { const conditions = []; if (criteria.state) { - conditions.push(); + conditions.push(sql`EXISTS (SELECT 1 FROM unnest(users."areasServed") AS area WHERE area LIKE '%' || ${criteria.state} || '%')`); } return conditions; } + async getUserByMail( id:string){ + const users = await this.conn.select().from(schema.users).where(sql`email = ${id}`) as User[] + const user = users[0] + user.hasCompanyLogo=this.fileService.hasCompanyLogo(id); + user.hasProfile=this.fileService.hasProfile(id); + return user; + } async getUserById( id:string){ const users = await this.conn.select().from(schema.users).where(sql`id = ${id}`) as User[] const user = users[0] @@ -41,8 +48,11 @@ export class UserService { } } async findUser(criteria:ListingCriteria){ - const users = await this.conn.execute(sql`SELECT * FROM users WHERE EXISTS (SELECT 1 FROM unnest(users."areasServed") AS area WHERE area LIKE '%' || ${criteria.state} || '%')`) - return users.rows + const start = criteria.start ? criteria.start : 0; + const length = criteria.length ? criteria.length : 12; + const conditions = this.getConditions(criteria) + const users = await this.conn.select().from(schema.users).where(and(...conditions)).offset(start).limit(length) + return users } } \ No newline at end of file diff --git a/bizmatch/.prettierrc.json b/bizmatch/.prettierrc.json new file mode 100644 index 0000000..285ba9d --- /dev/null +++ b/bizmatch/.prettierrc.json @@ -0,0 +1,18 @@ +{ + "arrowParens": "avoid", + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxBracketSameLine": false, + "jsxSingleQuote": false, + "printWidth": 220, + "proseWrap": "always", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": false, + "vueIndentScriptAndStyle": false +} \ No newline at end of file diff --git a/bizmatch/.vscode/settings.json b/bizmatch/.vscode/settings.json new file mode 100644 index 0000000..0fd6e04 --- /dev/null +++ b/bizmatch/.vscode/settings.json @@ -0,0 +1,28 @@ +{ + "editor.suggestSelection": "first", + "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue", + "explorer.confirmDelete": false, + "typescript.updateImportsOnFileMove.enabled": "always", + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features" + }, + "[scss]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + "prettier.printWidth": 240, + "git.autofetch": false, + "git.autorefresh": true +} diff --git a/bizmatch/src/app/app.routes.ts b/bizmatch/src/app/app.routes.ts index ada824c..7daa4d5 100644 --- a/bizmatch/src/app/app.routes.ts +++ b/bizmatch/src/app/app.routes.ts @@ -1,108 +1,101 @@ import { Routes } from '@angular/router'; -import { ListingsComponent } from './pages/listings/listings.component'; -import { HomeComponent } from './pages/home/home.component'; -import { DetailsListingComponent } from './pages/details/details-listing/details-listing.component'; -import { AccountComponent } from './pages/subscription/account/account.component'; -import { EditListingComponent } from './pages/subscription/edit-listing/edit-listing.component'; -import { MyListingComponent } from './pages/subscription/my-listing/my-listing.component'; -import { FavoritesComponent } from './pages/subscription/favorites/favorites.component'; -import { EmailUsComponent } from './pages/subscription/email-us/email-us.component'; -import { authGuard } from './guards/auth.guard'; -import { PricingComponent } from './pages/pricing/pricing.component'; import { LogoutComponent } from './components/logout/logout.component'; +import { authGuard } from './guards/auth.guard'; +import { DetailsBusinessListingComponent } from './pages/details/details-business-listing/details-business-listing.component'; +import { DetailsCommercialPropertyListingComponent } from './pages/details/details-commercial-property-listing/details-commercial-property-listing.component'; import { DetailsUserComponent } from './pages/details/details-user/details-user.component'; +import { HomeComponent } from './pages/home/home.component'; +import { BrokerListingsComponent } from './pages/listings/broker-listings/broker-listings.component'; import { BusinessListingsComponent } from './pages/listings/business-listings/business-listings.component'; import { CommercialPropertyListingsComponent } from './pages/listings/commercial-property-listings/commercial-property-listings.component'; -import { BrokerListingsComponent } from './pages/listings/broker-listings/broker-listings.component'; +import { PricingComponent } from './pages/pricing/pricing.component'; +import { AccountComponent } from './pages/subscription/account/account.component'; import { EditBusinessListingComponent } from './pages/subscription/edit-business-listing/edit-business-listing.component'; import { EditCommercialPropertyListingComponent } from './pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component'; - +import { EmailUsComponent } from './pages/subscription/email-us/email-us.component'; +import { FavoritesComponent } from './pages/subscription/favorites/favorites.component'; +import { MyListingComponent } from './pages/subscription/my-listing/my-listing.component'; export const routes: Routes = [ - // { - // path: 'listings/:type', - // component: ListingsComponent, - // }, - // Umleitung von /listing zu /listing/business - { - path: 'businessListings', - component: BusinessListingsComponent, - runGuardsAndResolvers:'always' - }, - { - path: 'commercialPropertyListings', - component: CommercialPropertyListingsComponent, - runGuardsAndResolvers:'always' - }, - { - path: 'brokerListings', - component: BrokerListingsComponent, - runGuardsAndResolvers:'always' - }, - { - path: 'home', - component: HomeComponent, - }, - { - path: 'details-listing/:type/:id', - component: DetailsListingComponent, - }, - { - path: 'details-listing/:type/:id', - component: DetailsListingComponent, - }, - { - path: 'details-user/:id', - component: DetailsUserComponent, - }, - { - path: 'account/:id', - component: AccountComponent, - canActivate: [authGuard], - }, - { - path: 'editBusinessListing/:id', - component: EditBusinessListingComponent, - canActivate: [authGuard], - }, - { - path: 'createBusinessListing', - component: EditBusinessListingComponent, - canActivate: [authGuard], - }, - { - path: 'editCommercialPropertyListing/:id', - component: EditCommercialPropertyListingComponent, - canActivate: [authGuard], - }, - { - path: 'createCommercialPropertyListing', - component: EditCommercialPropertyListingComponent, - canActivate: [authGuard], - }, - { - path: 'myListings', - component: MyListingComponent, - canActivate: [authGuard], - }, - { - path: 'myFavorites', - component: FavoritesComponent, - canActivate: [authGuard], - }, - { - path: 'emailUs', - component: EmailUsComponent, - canActivate: [authGuard], - }, - { - path: 'logout', - component: LogoutComponent, - canActivate: [authGuard], - }, - { - path: 'pricing', - component: PricingComponent - }, - { path: '**', redirectTo: 'home' }, + { + path: 'businessListings', + component: BusinessListingsComponent, + runGuardsAndResolvers: 'always', + }, + { + path: 'commercialPropertyListings', + component: CommercialPropertyListingsComponent, + runGuardsAndResolvers: 'always', + }, + { + path: 'brokerListings', + component: BrokerListingsComponent, + runGuardsAndResolvers: 'always', + }, + { + path: 'home', + component: HomeComponent, + }, + { + path: 'details-business-listing/:id', + component: DetailsBusinessListingComponent, + }, + { + path: 'details-commercial-property-listing/:id', + component: DetailsCommercialPropertyListingComponent, + }, + { + path: 'details-user/:id', + component: DetailsUserComponent, + }, + { + path: 'account', + component: AccountComponent, + canActivate: [authGuard], + }, + { + path: 'editBusinessListing/:id', + component: EditBusinessListingComponent, + canActivate: [authGuard], + }, + { + path: 'createBusinessListing', + component: EditBusinessListingComponent, + canActivate: [authGuard], + }, + { + path: 'editCommercialPropertyListing/:id', + component: EditCommercialPropertyListingComponent, + canActivate: [authGuard], + }, + { + path: 'createCommercialPropertyListing', + component: EditCommercialPropertyListingComponent, + canActivate: [authGuard], + }, + { + path: 'myListings', + component: MyListingComponent, + canActivate: [authGuard], + }, + { + path: 'myFavorites', + component: FavoritesComponent, + canActivate: [authGuard], + }, + { + path: 'emailUs', + component: EmailUsComponent, + canActivate: [authGuard], + }, + { + path: 'logout', + component: LogoutComponent, + canActivate: [authGuard], + }, + { + path: 'pricing', + component: PricingComponent, + }, + { path: '**', redirectTo: 'home' }, ]; diff --git a/bizmatch/src/app/components/footer/footer.component.html b/bizmatch/src/app/components/footer/footer.component.html index 5c7b0ce..769af81 100644 --- a/bizmatch/src/app/components/footer/footer.component.html +++ b/bizmatch/src/app/components/footer/footer.component.html @@ -1,26 +1,26 @@
-
-
-
- footer sections -
© 2024 Bizmatch All rights reserved.
-
-
-
BizMatch, Inc., 1001 Blucher Street, Corpus Christi, Texas 78401
-
1-800-840-6025
-
bizmatch@biz-match.com
-
- -
-
Actions
- Login - Account - Log Out -
-
+
+
+
+ footer sections +
© 2024 Bizmatch All rights reserved.
+
+
+
BizMatch, Inc., 1001 Blucher Street, Corpus Christi, Texas 78401
+
1-800-840-6025
+
bizmatch@biz-match.com
+
+ +
+
Actions
+ Login + Account + Log Out +
-
\ No newline at end of file +
+
diff --git a/bizmatch/src/app/components/header/header.component.ts b/bizmatch/src/app/components/header/header.component.ts index da240d6..add75b9 100644 --- a/bizmatch/src/app/components/header/header.component.ts +++ b/bizmatch/src/app/components/header/header.component.ts @@ -1,118 +1,115 @@ import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; +import { Router } from '@angular/router'; +import { faUserGear } from '@fortawesome/free-solid-svg-icons'; import { MenuItem } from 'primeng/api'; import { ButtonModule } from 'primeng/button'; import { MenubarModule } from 'primeng/menubar'; import { OverlayPanelModule } from 'primeng/overlaypanel'; -import { environment } from '../../../environments/environment'; -import { UserService } from '../../services/user.service'; import { TabMenuModule } from 'primeng/tabmenu'; import { Observable } from 'rxjs'; -import { faUserGear } from '@fortawesome/free-solid-svg-icons'; -import { Router } from '@angular/router'; -import {User} from '../../../../../bizmatch-server/src/models/db.model' +import { User } from '../../../../../bizmatch-server/src/models/db.model'; +import { environment } from '../../../environments/environment'; +import { UserService } from '../../services/user.service'; @Component({ - selector: 'header', - standalone: true, - imports: [CommonModule, MenubarModule, ButtonModule, OverlayPanelModule, TabMenuModule ], - templateUrl: './header.component.html', - styleUrl: './header.component.scss' + selector: 'header', + standalone: true, + imports: [CommonModule, MenubarModule, ButtonModule, OverlayPanelModule, TabMenuModule], + templateUrl: './header.component.html', + styleUrl: './header.component.scss', }) export class HeaderComponent { - public buildVersion = environment.buildVersion; - user$:Observable - user:User; - public tabItems: MenuItem[]; - public menuItems: MenuItem[]; - activeItem - faUserGear=faUserGear - constructor(public userService: UserService,private router: Router) { - - } + public buildVersion = environment.buildVersion; + user$: Observable; + user: User; + public tabItems: MenuItem[]; + public menuItems: MenuItem[]; + activeItem; + faUserGear = faUserGear; + constructor(public userService: UserService, private router: Router) {} - ngOnInit(){ - this.user$=this.userService.getUserObservable(); - this.user$.subscribe(u=>{ - this.user=u; - this.menuItems = [ - { - label: 'User Actions', - icon: 'fas fa-cog', - items: [ - { - label: 'Account', - icon: 'pi pi-user', - routerLink: `/account/${this.user.id}`, - visible: this.isUserLogedIn() - }, - { - label: 'Create Listing', - icon: 'pi pi-plus-circle', - routerLink: "/createListing", - visible: this.isUserLogedIn() - }, - { - label: 'My Listings', - icon: 'pi pi-list', - routerLink:"/myListings", - visible: this.isUserLogedIn() - }, - { - label: 'My Favorites', - icon: 'pi pi-star', - routerLink:"/myFavorites", - visible: this.isUserLogedIn() - }, - { - label: 'EMail Us', - icon: 'fa-regular fa-envelope', - routerLink:"/emailUs", - visible: this.isUserLogedIn() - }, - { - label: 'Logout', - icon: 'fa-solid fa-right-from-bracket', - routerLink:"/logout", - visible: this.isUserLogedIn() - }, - { - label: 'Login', - icon: 'fa-solid fa-right-from-bracket', - //routerLink:"/account", - command: () => this.login(), - visible: !this.isUserLogedIn() - }, - ] - } - ] - }); - this.tabItems = [ - { - label: 'Businesses for Sale', - routerLink: '/listings/business', - fragment:'' - }, - { - label: 'Professionals/Brokers Directory', - routerLink: '/listings/professionals_brokers', - fragment:'' - }, - { - label: 'Commercial Property', - routerLink: '/listings/commercialProperty', - fragment:'' - } - ]; + ngOnInit() { + this.user$ = this.userService.getUserObservable(); + this.user$.subscribe(u => { + this.user = u; + this.menuItems = [ + { + label: 'User Actions', + icon: 'fas fa-cog', + items: [ + { + label: 'Account', + icon: 'pi pi-user', + routerLink: `/account`, + visible: this.isUserLogedIn(), + }, + { + label: 'Create Listing', + icon: 'pi pi-plus-circle', + routerLink: '/createListing', + visible: this.isUserLogedIn(), + }, + { + label: 'My Listings', + icon: 'pi pi-list', + routerLink: '/myListings', + visible: this.isUserLogedIn(), + }, + { + label: 'My Favorites', + icon: 'pi pi-star', + routerLink: '/myFavorites', + visible: this.isUserLogedIn(), + }, + { + label: 'EMail Us', + icon: 'fa-regular fa-envelope', + routerLink: '/emailUs', + visible: this.isUserLogedIn(), + }, + { + label: 'Logout', + icon: 'fa-solid fa-right-from-bracket', + routerLink: '/logout', + visible: this.isUserLogedIn(), + }, + { + label: 'Login', + icon: 'fa-solid fa-right-from-bracket', + command: () => this.login(), + visible: !this.isUserLogedIn(), + }, + ], + }, + ]; + }); + this.tabItems = [ + { + label: 'Businesses for Sale', + routerLink: '/businessListings', + fragment: '', + }, + { + label: 'Professionals/Brokers Directory', + routerLink: '/brokerListings', + fragment: '', + }, + { + label: 'Commercial Property', + routerLink: '/commercialPropertyListings', + fragment: '', + }, + ]; - this.activeItem=this.tabItems[0]; - } - navigateWithState(dest: string, state: any) { - this.router.navigate([dest], { state: state }); - } - isUserLogedIn(){ - return this.userService?.isLoggedIn(); - } - login(){ - this.userService.login(window.location.href); - } + this.activeItem = this.tabItems[0]; + } + navigateWithState(dest: string, state: any) { + this.router.navigate([dest], { state: state }); + } + isUserLogedIn() { + return this.userService?.isLoggedIn(); + } + login() { + this.userService.login(window.location.href); + } } 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 new file mode 100644 index 0000000..01493e8 --- /dev/null +++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.html @@ -0,0 +1,100 @@ +
+
+
+
+
{{ listing?.title }}
+ + +
+ +
+
+
    +
  • +
    Description
    +
    +
  • +
  • +
    Category
    +
    + +
    +
  • +
  • +
    Located in
    +
    {{ selectOptions.getState(listing.state) }}
    +
  • +
  • +
    Asking Price
    +
    {{ listing.price | currency }}
    +
  • +
  • +
    Real Estate Included
    +
    {{ listing.realEstateIncluded ? 'Yes' : 'No' }}
    +
  • +
  • +
    Sales revenue
    +
    {{ listing.salesRevenue | currency }}
    +
  • +
  • +
    Cash flow
    +
    {{ listing.cashFlow | currency }}
    +
  • +
  • +
    Employees
    +
    {{ listing.employees }}
    +
  • +
  • +
    Broker licensing
    +
    {{ listing.brokerLicencing }}
    +
  • +
+ + + + + + + @if(listing && user && (user.id===listing?.userId || isAdmin())){ + + } +
+
+
+
Contact The Author of This Listing
+
Please Include your contact info below:
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ +
+
+
+
+
+
diff --git a/bizmatch/src/app/pages/details/details-listing/details-listing.component.scss b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.scss similarity index 100% rename from bizmatch/src/app/pages/details/details-listing/details-listing.component.scss rename to bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.scss diff --git a/bizmatch/src/app/pages/details/details-listing/details-listing.component.ts b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts similarity index 53% rename from bizmatch/src/app/pages/details/details-listing/details-listing.component.ts rename to bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts index 6b8b8c5..3247c0a 100644 --- a/bizmatch/src/app/pages/details/details-listing/details-listing.component.ts +++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts @@ -1,89 +1,80 @@ import { Component } from '@angular/core'; -import { ButtonModule } from 'primeng/button'; -import { CheckboxModule } from 'primeng/checkbox'; -import { InputTextModule } from 'primeng/inputtext'; -import { StyleClassModule } from 'primeng/styleclass'; -import { SelectOptionsService } from '../../../services/select-options.service'; -import { DropdownModule } from 'primeng/dropdown'; -import { FormsModule } from '@angular/forms'; -import { CommonModule } from '@angular/common'; -import { ToggleButtonModule } from 'primeng/togglebutton'; -import { TagModule } from 'primeng/tag'; -import data from '../../../../assets/data/listings.json'; -import { ActivatedRoute, Router, RouterModule } from '@angular/router'; -import { InputTextareaModule } from 'primeng/inputtextarea'; -import { ChipModule } from 'primeng/chip'; -import { lastValueFrom } from 'rxjs'; -import { ListingsService } from '../../../services/listings.service'; -import { UserService } from '../../../services/user.service'; -import onChange from 'on-change'; -import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils'; -import { MailService } from '../../../services/mail.service'; -import { MessageService } from 'primeng/api'; -import { SharedModule } from '../../../shared/shared/shared.module'; -import { GalleriaModule } from 'primeng/galleria'; -import { environment } from '../../../../environments/environment'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; -import { ImageProperty, ListingCriteria, ListingType, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model'; -import { User } from '../../../../../../bizmatch-server/src/models/db.model'; +import { ActivatedRoute, Router } from '@angular/router'; +import onChange from 'on-change'; +import { MessageService } from 'primeng/api'; +import { GalleriaModule } from 'primeng/galleria'; +import { lastValueFrom } from 'rxjs'; +import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; +import { ImageProperty, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model'; +import { environment } from '../../../../environments/environment'; +import { ListingsService } from '../../../services/listings.service'; +import { MailService } from '../../../services/mail.service'; +import { SelectOptionsService } from '../../../services/select-options.service'; +import { UserService } from '../../../services/user.service'; +import { SharedModule } from '../../../shared/shared/shared.module'; +import { getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils'; + @Component({ - selector: 'app-details-listing', + selector: 'app-details-business-listing', standalone: true, imports: [SharedModule, GalleriaModule], providers: [MessageService], - templateUrl: './details-listing.component.html', - styleUrl: './details-listing.component.scss' + templateUrl: './details-business-listing.component.html', + styleUrl: './details-business-listing.component.scss', }) -export class DetailsListingComponent { +export class DetailsBusinessListingComponent { // listings: Array; responsiveOptions = [ { breakpoint: '1199px', numVisible: 1, - numScroll: 1 + numScroll: 1, }, { breakpoint: '991px', numVisible: 2, - numScroll: 1 + numScroll: 1, }, { breakpoint: '767px', numVisible: 1, - numScroll: 1 - } + numScroll: 1, + }, ]; private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined; - private type: 'business'|'commercialProperty' | undefined = this.activatedRoute.snapshot.params['type'] as 'business'|'commercialProperty' | undefined; - listing: ListingType; - criteria: ListingCriteria + private type: 'business' | 'commercialProperty' | undefined = this.activatedRoute.snapshot.params['type'] as 'business' | 'commercialProperty' | undefined; + listing: BusinessListing; + criteria: ListingCriteria; mailinfo: MailInfo; - propertyImages: ImageProperty[] = [] + propertyImages: ImageProperty[] = []; environment = environment; - user:User - description:SafeHtml; - constructor(private activatedRoute: ActivatedRoute, + user: User; + description: SafeHtml; + constructor( + private activatedRoute: ActivatedRoute, private listingsService: ListingsService, private router: Router, private userService: UserService, public selectOptions: SelectOptionsService, private mailService: MailService, private messageService: MessageService, - private sanitizer: DomSanitizer) { + private sanitizer: DomSanitizer, + ) { this.userService.getUserObservable().subscribe(user => { - this.user = user + this.user = user; }); this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler); - this.mailinfo = { sender: {}, userId: '' } + this.mailinfo = { sender: {}, userId: '' }; } async ngOnInit() { this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, this.type)); - this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id) - this.description=this.sanitizer.bypassSecurityTrustHtml(this.listing.description); + this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id); + this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); } back() { - this.router.navigate(['listings', this.criteria.listingsCategory]) + this.router.navigate(['businessListings']); } isAdmin() { return this.userService.hasAdminRole(); diff --git a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html new file mode 100644 index 0000000..a53b0dc --- /dev/null +++ b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html @@ -0,0 +1,90 @@ +
+
+
+
+
{{ listing?.title }}
+ + +
+ +
+
+
    +
  • +
    Description
    +
    +
  • +
  • +
    Property Category
    +
    {{ selectOptions.getCommercialProperty(listing.type) }}
    +
  • +
  • +
    Located in
    +
    {{ selectOptions.getState(listing.state) }}
    +
  • +
  • +
    City
    +
    {{ listing.city }}
    +
  • +
  • +
    Zip Code
    +
    {{ listing.zipCode }}
    +
  • +
  • +
    County
    +
    {{ listing.county }}
    +
  • +
  • +
    Asking Price:
    +
    {{ listing.price | currency }}
    +
  • +
+ + + + + + + @if(listing && user && (user.id===listing?.userId || isAdmin())){ + + } +
+
+
+
Contact The Author of This Listing
+
Please Include your contact info below:
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ +
+
+
+
+
+
diff --git a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.scss b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.ts b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.ts new file mode 100644 index 0000000..72cde2d --- /dev/null +++ b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.ts @@ -0,0 +1,87 @@ +import { Component } from '@angular/core'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { ActivatedRoute, Router } from '@angular/router'; +import onChange from 'on-change'; +import { MessageService } from 'primeng/api'; +import { GalleriaModule } from 'primeng/galleria'; +import { lastValueFrom } from 'rxjs'; +import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; +import { ImageProperty, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model'; +import { environment } from '../../../../environments/environment'; +import { ListingsService } from '../../../services/listings.service'; +import { MailService } from '../../../services/mail.service'; +import { SelectOptionsService } from '../../../services/select-options.service'; +import { UserService } from '../../../services/user.service'; +import { SharedModule } from '../../../shared/shared/shared.module'; +import { getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils'; + +@Component({ + selector: 'app-details-commercial-property-listing', + standalone: true, + imports: [SharedModule, GalleriaModule], + providers: [MessageService], + templateUrl: './details-commercial-property-listing.component.html', + styleUrl: './details-commercial-property-listing.component.scss', +}) +export class DetailsCommercialPropertyListingComponent { + // listings: Array; + responsiveOptions = [ + { + breakpoint: '1199px', + numVisible: 1, + numScroll: 1, + }, + { + breakpoint: '991px', + numVisible: 2, + numScroll: 1, + }, + { + breakpoint: '767px', + numVisible: 1, + numScroll: 1, + }, + ]; + private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined; + private type: 'business' | 'commercialProperty' | undefined = this.activatedRoute.snapshot.params['type'] as 'business' | 'commercialProperty' | undefined; + listing: CommercialPropertyListing; + criteria: ListingCriteria; + mailinfo: MailInfo; + propertyImages: ImageProperty[] = []; + environment = environment; + user: User; + description: SafeHtml; + constructor( + private activatedRoute: ActivatedRoute, + private listingsService: ListingsService, + private router: Router, + private userService: UserService, + public selectOptions: SelectOptionsService, + private mailService: MailService, + private messageService: MessageService, + private sanitizer: DomSanitizer, + ) { + this.userService.getUserObservable().subscribe(user => { + this.user = user; + }); + this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler); + this.mailinfo = { sender: {}, userId: '' }; + } + + async ngOnInit() { + this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, this.type)); + this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id); + this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); + } + back() { + this.router.navigate(['commercialPropertyListings']); + } + isAdmin() { + return this.userService.hasAdminRole(); + } + async mail() { + this.mailinfo.userId = this.listing.userId; + 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 }); + } +} diff --git a/bizmatch/src/app/pages/details/details-listing/details-listing.component.html b/bizmatch/src/app/pages/details/details-listing/details-listing.component.html deleted file mode 100644 index b9969e9..0000000 --- a/bizmatch/src/app/pages/details/details-listing/details-listing.component.html +++ /dev/null @@ -1,141 +0,0 @@ -
-
-
-
-
{{listing?.title}}
- - -
- -
-
-
    - -
  • -
    Description
    -
    -
  • - @if (listing && (listing.listingsCategory==='business')){ -
  • -
    Category
    -
    - -
    -
  • -
  • -
    Located in
    -
    {{selectOptions.getState(listing.state)}}
    -
  • -
  • -
    Asking Price
    -
    {{listing.price | currency}}
    -
  • -
  • -
    Real Estate Included
    -
    {{listing.realEstateIncluded?'Yes':'No'}}
    -
  • -
  • -
    Sales revenue
    -
    {{listing.salesRevenue | currency}}
    -
  • -
  • -
    Cash flow
    -
    {{listing.cashFlow | currency}}
    -
  • -
  • -
    Employees
    -
    {{listing.employees}}
    -
  • -
  • -
    Broker licensing
    -
    {{listing.brokerLicencing}}
    -
  • - } - @if (listing && (listing.listingsCategory==='commercialProperty')){ -
  • -
    Property Category
    -
    {{selectOptions.getCommercialProperty(listing.type)}} -
    -
  • -
  • -
    Located in
    -
    {{selectOptions.getState(listing.state)}}
    -
  • -
  • -
    City
    -
    {{listing.city}}
    -
  • -
  • -
    Zip Code
    -
    {{listing.zipCode}}
    -
  • -
  • -
    County
    -
    {{listing.county}}
    -
  • -
  • -
    Asking Price:
    -
    {{listing.price | currency}}
    -
  • - } -
- - - - - - - @if(listing && user && (user.id===listing?.userId || isAdmin())){ - - } -
-
-
-
Contact The Author of This Listing -
-
Please Include your contact info below:
-
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - -
-
-
- -
-
-
- - -
- -
-
\ No newline at end of file diff --git a/bizmatch/src/app/pages/details/details-user/details-user.component.html b/bizmatch/src/app/pages/details/details-user/details-user.component.html index 3a7f3d9..954cfd1 100644 --- a/bizmatch/src/app/pages/details/details-user/details-user.component.html +++ b/bizmatch/src/app/pages/details/details-user/details-user.component.html @@ -1,132 +1,121 @@
-
-
- -
-
-
- @if(user.hasProfile){ - - } @else { - - } -
- {{user.firstname}} {{user.lastname}} - -
-
- Company -
{{user.companyName}}
-
-
- For Sale -
12
-
-
- Sold -
8
-
-
- -
- @if(user.hasCompanyLogo){ - - } - -
- -
-
-
- -
- +
+
+
+ @if(user.hasProfile){ + + } @else { + + } +
+ {{ user.firstname }} {{ user.lastname }} + +
+
+ Company +
{{ user.companyName }}
-

{{user.description}}

+
+ For Sale +
12
+
+
+ Sold +
8
+
+
+ +
+ @if(user.hasCompanyLogo){ + + } + +
+ +
+
-
-
-
Company Profile
-
-
    -
  • -
    Name
    -
    {{user.firstname}} {{user.lastname}}
    -
  • -
  • -
    Phone Number
    -
    {{user.phoneNumber}}
    -
  • -
  • -
    EMail Address
    -
    {{user.email}}
    -
  • -
  • -
    Company Location
    -
    {{user.companyLocation}}
    -
  • -
  • -
    Services we offer
    -
    -
  • -
  • -
    Areas we serve
    -
    - @for (area of user.areasServed; track area) { - - } - -
    -
  • -
  • -
    Licensed In
    -
    - @for (license of userLicensedIn; track license) { -
    {{license.name}} : {{license.value}}
    - } -
    -
  • -
  • -
    My Listings For Sale
    -
    -
    - @for (listing of userListings; track listing) { -
    -
    -
    - - - - {{selectOptions.getBusiness(listing.type)}} -
    -
    {{listing.title}}
    -
    -
    - } -
    -
    -
  • -
+
+ +
  • +
    Licensed In
    +
    + @for (license of userLicensedIn; track license) { +
    {{ license.name }} : {{ license.value }}
    + } +
    +
  • +
  • +
    My Listings For Sale
    +
    +
    + @for (listing of userListings; track listing) { +
    +
    +
    + + + + {{ selectOptions.getBusiness(listing.type) }} +
    +
    {{ listing.title }}
    +
    +
    + }
    -
    - @if( user?.id===(user$| async)?.id || isAdmin()){ - - } +
  • + +
    - +
    + @if( user?.id===(user$| async)?.id || isAdmin()){ + + }
    -
    \ No newline at end of file +
    +
    diff --git a/bizmatch/src/app/pages/details/details-user/details-user.component.ts b/bizmatch/src/app/pages/details/details-user/details-user.component.ts index 63d8b66..e60427a 100644 --- a/bizmatch/src/app/pages/details/details-user/details-user.component.ts +++ b/bizmatch/src/app/pages/details/details-user/details-user.component.ts @@ -1,18 +1,18 @@ import { Component } from '@angular/core'; -import { SharedModule } from '../../../shared/shared/shared.module'; -import { GalleriaModule } from 'primeng/galleria'; import { MessageService } from 'primeng/api'; +import { GalleriaModule } from 'primeng/galleria'; +import { SharedModule } from '../../../shared/shared/shared.module'; -import { environment } from '../../../../environments/environment'; -import { ActivatedRoute, Router } from '@angular/router'; -import { UserService } from '../../../services/user.service'; -import { Observable } from 'rxjs'; -import { ListingsService } from '../../../services/listings.service'; -import { SelectOptionsService } from '../../../services/select-options.service'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; -import { ImageService } from '../../../services/image.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable } from 'rxjs'; import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; import { KeyValue, ListingCriteria } from '../../../../../../bizmatch-server/src/models/main.model'; +import { environment } from '../../../../environments/environment'; +import { ImageService } from '../../../services/image.service'; +import { ListingsService } from '../../../services/listings.service'; +import { SelectOptionsService } from '../../../services/select-options.service'; +import { UserService } from '../../../services/user.service'; @Component({ selector: 'app-details-user', @@ -20,38 +20,41 @@ import { KeyValue, ListingCriteria } from '../../../../../../bizmatch-server/src imports: [SharedModule, GalleriaModule], providers: [MessageService], templateUrl: './details-user.component.html', - styleUrl: './details-user.component.scss' + styleUrl: './details-user.component.scss', }) export class DetailsUserComponent { private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined; user: User; - user$:Observable + user$: Observable; environment = environment; - criteria:ListingCriteria; - userListings:BusinessListing[] - companyOverview:SafeHtml; - offeredServices:SafeHtml; - userLicensedIn :KeyValue[] - constructor(private activatedRoute: ActivatedRoute, + criteria: ListingCriteria; + userListings: BusinessListing[]; + companyOverview: SafeHtml; + offeredServices: SafeHtml; + userLicensedIn: KeyValue[]; + constructor( + private activatedRoute: ActivatedRoute, private router: Router, private userService: UserService, - private listingsService:ListingsService, + private listingsService: ListingsService, private messageService: MessageService, public selectOptions: SelectOptionsService, private sanitizer: DomSanitizer, - private imageService:ImageService) { - } + private imageService: ImageService, + ) {} async ngOnInit() { this.user = await this.userService.getById(this.id); - this.userLicensedIn = this.user.licensedIn.map(l=>{return {name:l.split('|')[0],value:l.split('|')[1]}}) + this.userLicensedIn = this.user.licensedIn.map(l => { + return { name: l.split('|')[0], value: l.split('|')[1] }; + }); this.userListings = await this.listingsService.getListingByUserId(this.id); this.user$ = this.userService.getUserObservable(); - this.companyOverview=this.sanitizer.bypassSecurityTrustHtml(this.user.companyOverview); - this.offeredServices=this.sanitizer.bypassSecurityTrustHtml(this.user.offeredServices); + this.companyOverview = this.sanitizer.bypassSecurityTrustHtml(this.user.companyOverview); + this.offeredServices = this.sanitizer.bypassSecurityTrustHtml(this.user.offeredServices); } back() { - this.router.navigate(['listings', this.criteria.listingsCategory]) + this.router.navigate(['brokerListings']); } isAdmin() { return this.userService.hasAdminRole(); diff --git a/bizmatch/src/app/pages/home/home.component.html b/bizmatch/src/app/pages/home/home.component.html index 41de0c6..28b66ac 100644 --- a/bizmatch/src/app/pages/home/home.component.html +++ b/bizmatch/src/app/pages/home/home.component.html @@ -1,75 +1,68 @@
    -
    -
    - Image - -
    -
    -
    -
    -

    Find businesses for sale

    -

    Arcu cursus euismod quis viverra nibh cras. Amet justo - donec - enim diam vulputate ut.

    -
      -
    • Senectus et netus et malesuada fames.
    • -
    • Orci a scelerisque purus semper eget.
    • -
    • Aenean sed adipiscing diam donec adipiscing - tristique.
    • -
    - -
    -
    -
    -
      -
    • -
    • -
    • -
    • -
    -
    -
    -
    - - - - -
    -
    -
    -
    - -
    -
    +
    +
    + Image +
    -
    \ No newline at end of file +
    +
    +
    +

    Find businesses for sale

    +

    Arcu cursus euismod quis viverra nibh cras. Amet justo donec enim diam vulputate ut.

    +
      +
    • Senectus et netus et malesuada fames.
    • +
    • Orci a scelerisque purus semper eget.
    • +
    • Aenean sed adipiscing diam donec adipiscing tristique.
    • +
    +
    +
    +
    +
      +
    • +
    • + +
    • +
    • + +
    • +
    +
    +
    +
    + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    diff --git a/bizmatch/src/app/pages/home/home.component.ts b/bizmatch/src/app/pages/home/home.component.ts index 9c2c566..04b8cf7 100644 --- a/bizmatch/src/app/pages/home/home.component.ts +++ b/bizmatch/src/app/pages/home/home.component.ts @@ -1,47 +1,45 @@ -import { Component } from '@angular/core'; -import { DropdownModule } from 'primeng/dropdown'; -import { FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; -import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { ActivatedRoute, Router, RouterModule } from '@angular/router'; -import { StyleClassModule } from 'primeng/styleclass'; +import onChange from 'on-change'; import { ButtonModule } from 'primeng/button'; import { CheckboxModule } from 'primeng/checkbox'; +import { DropdownModule } from 'primeng/dropdown'; import { InputTextModule } from 'primeng/inputtext'; +import { StyleClassModule } from 'primeng/styleclass'; +import { Observable } from 'rxjs'; +import { User } from '../../../../../bizmatch-server/src/models/db.model'; +import { ListingCriteria } from '../../../../../bizmatch-server/src/models/main.model'; import { SelectOptionsService } from '../../services/select-options.service'; import { UserService } from '../../services/user.service'; -import onChange from 'on-change'; import { getCriteriaStateObject, getSessionStorageHandler } from '../../utils/utils'; -import { Observable } from 'rxjs'; -import { ListingCriteria } from '../../../../../bizmatch-server/src/models/main.model'; -import { User } from '../../../../../bizmatch-server/src/models/db.model'; @Component({ selector: 'app-home', standalone: true, - imports: [CommonModule, StyleClassModule,ButtonModule, CheckboxModule,InputTextModule,DropdownModule,FormsModule, RouterModule], + imports: [CommonModule, StyleClassModule, ButtonModule, CheckboxModule, InputTextModule, DropdownModule, FormsModule, RouterModule], templateUrl: './home.component.html', - styleUrl: './home.component.scss' + styleUrl: './home.component.scss', }) export class HomeComponent { activeTabAction = 'business'; - type:string; - maxPrice:string; - minPrice:string; - criteria:ListingCriteria - user$:Observable - public constructor(private router: Router,private activatedRoute: ActivatedRoute, public selectOptions:SelectOptionsService, public userService:UserService) { - this.criteria = onChange(getCriteriaStateObject(),getSessionStorageHandler); + type: string; + maxPrice: string; + minPrice: string; + criteria: ListingCriteria; + user$: Observable; + public constructor(private router: Router, private activatedRoute: ActivatedRoute, public selectOptions: SelectOptionsService, public userService: UserService) { + this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler); } - ngOnInit(){ - this.user$=this.userService.getUserObservable(); + ngOnInit() { + this.user$ = this.userService.getUserObservable(); } - search(){ - this.router.navigate([`listings/${this.activeTabAction}`]) + search() { + this.router.navigate([`${this.activeTabAction}Listings`]); } - - login(){ - this.userService.login(window.location.href); - } -} \ No newline at end of file + login() { + this.userService.login(window.location.href); + } +} diff --git a/bizmatch/src/app/pages/listings/broker-listings/broker-listings.component.html b/bizmatch/src/app/pages/listings/broker-listings/broker-listings.component.html index 8d8777d..d39f4f8 100644 --- a/bizmatch/src/app/pages/listings/broker-listings/broker-listings.component.html +++ b/bizmatch/src/app/pages/listings/broker-listings/broker-listings.component.html @@ -1,59 +1,48 @@ -
    -
    +