cleanup + Property images
This commit is contained in:
parent
9121ca1a69
commit
bb5a408cdc
File diff suppressed because it is too large
Load Diff
|
|
@ -23,7 +23,7 @@
|
||||||
"drop": "drizzle-kit drop",
|
"drop": "drizzle-kit drop",
|
||||||
"migrate": "tsx src/drizzle/migrate.ts",
|
"migrate": "tsx src/drizzle/migrate.ts",
|
||||||
"import": "tsx src/drizzle/import.ts",
|
"import": "tsx src/drizzle/import.ts",
|
||||||
"generateTypes":"tsx src/drizzle/generateTypes.ts src/drizzle/schema.ts src/models/db.model.ts"
|
"generateTypes": "tsx src/drizzle/generateTypes.ts src/drizzle/schema.ts src/models/db.model.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs-modules/mailer": "^1.10.3",
|
"@nestjs-modules/mailer": "^1.10.3",
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
"@nestjs/passport": "^10.0.3",
|
"@nestjs/passport": "^10.0.3",
|
||||||
"@nestjs/platform-express": "^10.0.0",
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
"@nestjs/serve-static": "^4.0.1",
|
"@nestjs/serve-static": "^4.0.1",
|
||||||
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"drizzle-orm": "^0.30.8",
|
"drizzle-orm": "^0.30.8",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
|
|
@ -80,6 +81,7 @@
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
"kysely-codegen": "^0.15.0",
|
"kysely-codegen": "^0.15.0",
|
||||||
|
"pg-to-ts": "^4.1.1",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"supertest": "^6.3.3",
|
"supertest": "^6.3.3",
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const __dirname = path.dirname(__filename);
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule.forRoot({isGlobal: true}), MailModule, AuthModule,
|
imports: [ConfigModule.forRoot({isGlobal: true}), MailModule, AuthModule,
|
||||||
ServeStaticModule.forRoot({
|
ServeStaticModule.forRoot({
|
||||||
rootPath: join(__dirname, '..', 'pictures'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen
|
rootPath: join(__dirname, '../..', 'pictures'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen
|
||||||
}),
|
}),
|
||||||
WinstonModule.forRoot({
|
WinstonModule.forRoot({
|
||||||
transports: [
|
transports: [
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ const generatedUserData = []
|
||||||
console.log(userData.length)
|
console.log(userData.length)
|
||||||
for (const user of userData) {
|
for (const user of userData) {
|
||||||
delete user.id
|
delete user.id
|
||||||
|
user.licensedIn=user.licensedIn.map(l=>`${l['name']}|${l['value']}`)
|
||||||
const u = await db.insert(schema.users).values(user).returning({ insertedId: schema.users.id });
|
const u = await db.insert(schema.users).values(user).returning({ insertedId: schema.users.id });
|
||||||
// console.log(`--> ${u[0].insertedId}`)
|
|
||||||
generatedUserData.push(u[0].insertedId);
|
generatedUserData.push(u[0].insertedId);
|
||||||
}
|
}
|
||||||
//Business Listings
|
//Business Listings
|
||||||
|
|
@ -45,7 +45,10 @@ filePath = `./data/commercials.json`
|
||||||
data = readFileSync(filePath, 'utf8');
|
data = readFileSync(filePath, 'utf8');
|
||||||
const commercialJsonData = JSON.parse(data) as CommercialPropertyListing[]; // Erwartet ein Array von Objekten
|
const commercialJsonData = JSON.parse(data) as CommercialPropertyListing[]; // Erwartet ein Array von Objekten
|
||||||
for (const commercial of commercialJsonData) {
|
for (const commercial of commercialJsonData) {
|
||||||
|
const id = commercial.id;
|
||||||
delete commercial.id
|
delete commercial.id
|
||||||
|
commercial.imageOrder=['1.jpg'];
|
||||||
|
commercial.imagePath=id
|
||||||
commercial.created = getRandomDateWithinLastYear();
|
commercial.created = getRandomDateWithinLastYear();
|
||||||
commercial.userId = getRandomItem(generatedUserData);
|
commercial.userId = getRandomItem(generatedUserData);
|
||||||
await db.insert(schema.commercials).values(commercial);
|
await db.insert(schema.commercials).values(commercial);
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ CREATE TABLE IF NOT EXISTS "commercials" (
|
||||||
"website" varchar(255),
|
"website" varchar(255),
|
||||||
"phoneNumber" varchar(255),
|
"phoneNumber" varchar(255),
|
||||||
"imageOrder" varchar(30)[],
|
"imageOrder" varchar(30)[],
|
||||||
"imagePath" varchar(30)[],
|
"imagePath" varchar(50),
|
||||||
"created" timestamp,
|
"created" timestamp,
|
||||||
"updated" timestamp,
|
"updated" timestamp,
|
||||||
"visits" integer,
|
"visits" integer,
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": "e8d0776a-ea8b-4c75-8a3a-e741620c4c4d",
|
"id": "f6d421f9-2394-4a1c-9268-9e46285f0a41",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"version": "5",
|
"version": "5",
|
||||||
"dialect": "pg",
|
"dialect": "pg",
|
||||||
|
|
@ -300,7 +300,7 @@
|
||||||
},
|
},
|
||||||
"imagePath": {
|
"imagePath": {
|
||||||
"name": "imagePath",
|
"name": "imagePath",
|
||||||
"type": "varchar(30)[]",
|
"type": "varchar(50)",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "5",
|
"version": "5",
|
||||||
"when": 1713791559934,
|
"when": 1714913766996,
|
||||||
"tag": "0000_safe_natasha_romanoff",
|
"tag": "0000_third_spacker_dave",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ export const commercials = pgTable('commercials', {
|
||||||
website: varchar('website', { length: 255 }),
|
website: varchar('website', { length: 255 }),
|
||||||
phoneNumber: varchar('phoneNumber', { length: 255 }),
|
phoneNumber: varchar('phoneNumber', { length: 255 }),
|
||||||
imageOrder:varchar('imageOrder',{length:30}).array(),
|
imageOrder:varchar('imageOrder',{length:30}).array(),
|
||||||
imagePath:varchar('imagePath',{length:30}).array(),
|
imagePath:varchar('imagePath',{length:50}),
|
||||||
created: timestamp('created'),
|
created: timestamp('created'),
|
||||||
updated: timestamp('updated'),
|
updated: timestamp('updated'),
|
||||||
visits: integer('visits'),
|
visits: integer('visits'),
|
||||||
|
|
|
||||||
|
|
@ -56,14 +56,13 @@ export class FileService {
|
||||||
return fs.existsSync(`./pictures/logo/${userId}.avif`)?true:false
|
return fs.existsSync(`./pictures/logo/${userId}.avif`)?true:false
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPropertyImages(listingId: string): Promise<ImageProperty[]> {
|
async getPropertyImages(listingId: string): Promise<string[]> {
|
||||||
const result: ImageProperty[] = []
|
const result: string[] = []
|
||||||
const directory = `./pictures/property/${listingId}`
|
const directory = `./pictures/property/${listingId}`
|
||||||
if (fs.existsSync(directory)) {
|
if (fs.existsSync(directory)) {
|
||||||
const files = await fs.readdir(directory);
|
const files = await fs.readdir(directory);
|
||||||
files.forEach(f => {
|
files.forEach(f => {
|
||||||
const image: ImageProperty = { name: f, id: '', code: '' };
|
result.push(f)
|
||||||
result.push(image)
|
|
||||||
})
|
})
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import { SelectOptionsService } from '../select-options/select-options.service.j
|
||||||
import { ListingsService } from '../listings/listings.service.js';
|
import { ListingsService } from '../listings/listings.service.js';
|
||||||
|
|
||||||
import { Entity, EntityData } from 'redis-om';
|
import { Entity, EntityData } from 'redis-om';
|
||||||
|
import { businesses, commercials } from 'src/drizzle/schema.js';
|
||||||
|
import { CommercialPropertyListing } from 'src/models/db.model.js';
|
||||||
|
|
||||||
@Controller('image')
|
@Controller('image')
|
||||||
export class ImageController {
|
export class ImageController {
|
||||||
|
|
@ -38,16 +40,16 @@ export class ImageController {
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
async getPropertyImagesById(@Param('id') id:string): Promise<any> {
|
async getPropertyImagesById(@Param('id') id:string): Promise<any> {
|
||||||
// const result = await this.listingService.getCommercialPropertyListingById(id);
|
const result = await this.listingService.findById(id,commercials);
|
||||||
// const listing = result as CommercialPropertyListing;
|
const listing = result as CommercialPropertyListing;
|
||||||
// if (listing.imageOrder){
|
if (listing.imageOrder){
|
||||||
// return listing.imageOrder
|
return listing.imageOrder
|
||||||
// } else {
|
} else {
|
||||||
// const imageOrder = await this.fileService.getPropertyImages(id);
|
const imageOrder = await this.fileService.getPropertyImages(id);
|
||||||
// listing.imageOrder=imageOrder;
|
listing.imageOrder=imageOrder;
|
||||||
// this.listingService.saveListing(listing);
|
this.listingService.updateListing(listing.id,listing,commercials);
|
||||||
// return imageOrder;
|
return imageOrder;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
@Get('profileImages/:userids')
|
@Get('profileImages/:userids')
|
||||||
async getProfileImagesForUsers(@Param('userids') userids:string): Promise<any> {
|
async getProfileImagesForUsers(@Param('userids') userids:string): Promise<any> {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ export class BusinessListingsController {
|
||||||
deleteById(@Param('id') id:string){
|
deleteById(@Param('id') id:string){
|
||||||
this.listingsService.deleteListing(id,businesses)
|
this.listingsService.deleteListing(id,businesses)
|
||||||
}
|
}
|
||||||
|
@Get('states/all')
|
||||||
|
getStates(): any {
|
||||||
|
return this.listingsService.getStates(businesses);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,9 @@ export class ListingsService {
|
||||||
async deleteListing(id: string, table: typeof businesses | typeof commercials): Promise<void> {
|
async deleteListing(id: string, table: typeof businesses | typeof commercials): Promise<void> {
|
||||||
await this.conn.delete(table).where(eq(table.id, id));
|
await this.conn.delete(table).where(eq(table.id, id));
|
||||||
}
|
}
|
||||||
|
async getStates(table: typeof businesses | typeof commercials): Promise<any[]> {
|
||||||
|
return await this.conn.select({state: table.state,count: sql<number>`count(${table.id})`.mapWith(Number)}).from(table).groupBy(sql`${table.state}`).orderBy(sql`count desc`);
|
||||||
|
}
|
||||||
// ##############################################################
|
// ##############################################################
|
||||||
// Images for commercial Properties
|
// Images for commercial Properties
|
||||||
// ##############################################################
|
// ##############################################################
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { AppModule } from './app.module.js';
|
import { AppModule } from './app.module.js';
|
||||||
|
import * as express from 'express';
|
||||||
|
import path, { join } from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
app.setGlobalPrefix('bizmatch');
|
app.setGlobalPrefix('bizmatch');
|
||||||
|
|
|
||||||
|
|
@ -64,10 +64,9 @@ export interface CommercialPropertyListing {
|
||||||
website?: string;
|
website?: string;
|
||||||
phoneNumber?: string;
|
phoneNumber?: string;
|
||||||
imageOrder?: string[];
|
imageOrder?: string[];
|
||||||
imagePath?: string[];
|
imagePath?: string;
|
||||||
created?: Date;
|
created?: Date;
|
||||||
updated?: Date;
|
updated?: Date;
|
||||||
visits?: number;
|
visits?: number;
|
||||||
lastVisit?: Date;
|
lastVisit?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import { BusinessListing, CommercialPropertyListing } from "./db.model";
|
import { BusinessListing, CommercialPropertyListing, User } from './db.model';
|
||||||
|
|
||||||
|
export interface StatesResult {
|
||||||
|
state: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface KeyValue {
|
export interface KeyValue {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -12,78 +16,82 @@ export interface KeyValueRatio {
|
||||||
export interface KeyValueStyle {
|
export interface KeyValueStyle {
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
icon:string;
|
icon: string;
|
||||||
bgColorClass:string;
|
bgColorClass: string;
|
||||||
textColorClass:string;
|
textColorClass: string;
|
||||||
}
|
}
|
||||||
export type SelectOption<T = number> = {
|
export type SelectOption<T = number> = {
|
||||||
value: T;
|
value: T;
|
||||||
label: string;
|
label: string;
|
||||||
};
|
};
|
||||||
export type ImageType = {
|
export type ImageType = {
|
||||||
name:'propertyPicture'|'companyLogo'|'profile',upload:string,delete:string,
|
name: 'propertyPicture' | 'companyLogo' | 'profile';
|
||||||
}
|
upload: string;
|
||||||
|
delete: string;
|
||||||
|
};
|
||||||
export type ListingCategory = {
|
export type ListingCategory = {
|
||||||
name: 'business' | 'commercialProperty'
|
name: 'business' | 'commercialProperty';
|
||||||
}
|
};
|
||||||
|
|
||||||
export type ListingType =
|
export type ListingType = BusinessListing | CommercialPropertyListing;
|
||||||
| BusinessListing
|
|
||||||
| CommercialPropertyListing;
|
|
||||||
|
|
||||||
export type ResponseBusinessListingArray = {
|
export type ResponseBusinessListingArray = {
|
||||||
data:BusinessListing[],
|
data: BusinessListing[];
|
||||||
total:number
|
total: number;
|
||||||
}
|
};
|
||||||
export type ResponseBusinessListing = {
|
export type ResponseBusinessListing = {
|
||||||
data:BusinessListing
|
data: BusinessListing;
|
||||||
}
|
};
|
||||||
export type ResponseCommercialPropertyListingArray = {
|
export type ResponseCommercialPropertyListingArray = {
|
||||||
data:CommercialPropertyListing[],
|
data: CommercialPropertyListing[];
|
||||||
total:number
|
total: number;
|
||||||
}
|
};
|
||||||
export type ResponseCommercialPropertyListing = {
|
export type ResponseCommercialPropertyListing = {
|
||||||
data:CommercialPropertyListing
|
data: CommercialPropertyListing;
|
||||||
}
|
};
|
||||||
|
export type ResponseUsersArray = {
|
||||||
|
data: User[];
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
export interface ListingCriteria {
|
export interface ListingCriteria {
|
||||||
start:number,
|
start: number;
|
||||||
length:number,
|
length: number;
|
||||||
page:number,
|
page: number;
|
||||||
pageCount:number,
|
pageCount: number;
|
||||||
type:number,
|
type: number;
|
||||||
state:string,
|
state: string;
|
||||||
minPrice:number,
|
minPrice: number;
|
||||||
maxPrice:number,
|
maxPrice: number;
|
||||||
realEstateChecked:boolean,
|
realEstateChecked: boolean;
|
||||||
title:string,
|
title: string;
|
||||||
category:'professional|broker'
|
category: 'professional|broker';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KeycloakUser {
|
export interface KeycloakUser {
|
||||||
id: string
|
id: string;
|
||||||
createdTimestamp: number
|
createdTimestamp: number;
|
||||||
username: string
|
username: string;
|
||||||
enabled: boolean
|
enabled: boolean;
|
||||||
totp: boolean
|
totp: boolean;
|
||||||
emailVerified: boolean
|
emailVerified: boolean;
|
||||||
firstName: string
|
firstName: string;
|
||||||
lastName: string
|
lastName: string;
|
||||||
email: string
|
email: string;
|
||||||
disableableCredentialTypes: any[]
|
disableableCredentialTypes: any[];
|
||||||
requiredActions: any[]
|
requiredActions: any[];
|
||||||
notBefore: number
|
notBefore: number;
|
||||||
access: Access
|
access: Access;
|
||||||
}
|
}
|
||||||
export interface Access {
|
export interface Access {
|
||||||
manageGroupMembership: boolean
|
manageGroupMembership: boolean;
|
||||||
view: boolean
|
view: boolean;
|
||||||
mapRoles: boolean
|
mapRoles: boolean;
|
||||||
impersonate: boolean
|
impersonate: boolean;
|
||||||
manage: boolean
|
manage: boolean;
|
||||||
}
|
}
|
||||||
export interface Subscription {
|
export interface Subscription {
|
||||||
id: string;
|
id: string;
|
||||||
userId:string
|
userId: string;
|
||||||
level: string;
|
level: string;
|
||||||
start: Date;
|
start: Date;
|
||||||
modified: Date;
|
modified: Date;
|
||||||
|
|
@ -92,9 +100,9 @@ export interface Subscription {
|
||||||
invoices: Array<Invoice>;
|
invoices: Array<Invoice>;
|
||||||
}
|
}
|
||||||
export interface Invoice {
|
export interface Invoice {
|
||||||
id: string,
|
id: string;
|
||||||
date: Date,
|
date: Date;
|
||||||
price: number
|
price: number;
|
||||||
}
|
}
|
||||||
export interface JwtToken {
|
export interface JwtToken {
|
||||||
exp: number;
|
exp: number;
|
||||||
|
|
@ -140,16 +148,16 @@ export interface AutoCompleteCompleteEvent {
|
||||||
export interface MailInfo {
|
export interface MailInfo {
|
||||||
sender: Sender;
|
sender: Sender;
|
||||||
userId: string;
|
userId: string;
|
||||||
}
|
}
|
||||||
export interface Sender {
|
export interface Sender {
|
||||||
name?: string;
|
name?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
phoneNumber?: string;
|
phoneNumber?: string;
|
||||||
state?: string;
|
state?: string;
|
||||||
comments?: string;
|
comments?: string;
|
||||||
}
|
}
|
||||||
export interface ImageProperty {
|
export interface ImageProperty {
|
||||||
id:string;
|
id: string;
|
||||||
code:string;
|
code: string;
|
||||||
name:string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,11 @@ export class UserService {
|
||||||
const start = criteria.start ? criteria.start : 0;
|
const start = criteria.start ? criteria.start : 0;
|
||||||
const length = criteria.length ? criteria.length : 12;
|
const length = criteria.length ? criteria.length : 12;
|
||||||
const conditions = this.getConditions(criteria)
|
const conditions = this.getConditions(criteria)
|
||||||
const users = await this.conn.select().from(schema.users).where(and(...conditions)).offset(start).limit(length)
|
const [data, total] = await Promise.all([
|
||||||
return users
|
this.conn.select().from(schema.users).where(and(...conditions)).offset(start).limit(length),
|
||||||
|
this.conn.select({ count: sql`count(*)` }).from(schema.users).where(and(...conditions)).then((result) => Number(result[0].count)),
|
||||||
|
]);
|
||||||
|
return { total, data };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AUTO-GENERATED FILE - DO NOT EDIT!
|
||||||
|
*
|
||||||
|
* This file was automatically generated by pg-to-ts v.4.1.1
|
||||||
|
* $ pg-to-ts generate -c postgresql://username:password@localhost:5432/bizmatch -t businesses -s public
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export type Json = unknown;
|
||||||
|
|
||||||
|
// Table businesses
|
||||||
|
export interface Businesses {
|
||||||
|
id: string;
|
||||||
|
userId: string | null;
|
||||||
|
type: number | null;
|
||||||
|
title: string | null;
|
||||||
|
description: string | null;
|
||||||
|
city: string | null;
|
||||||
|
state: string | null;
|
||||||
|
price: number | null;
|
||||||
|
favoritesForUser: string[] | null;
|
||||||
|
draft: boolean | null;
|
||||||
|
listingsCategory: string | null;
|
||||||
|
realEstateIncluded: boolean | null;
|
||||||
|
leasedLocation: boolean | null;
|
||||||
|
franchiseResale: boolean | null;
|
||||||
|
salesRevenue: number | null;
|
||||||
|
cashFlow: number | null;
|
||||||
|
supportAndTraining: string | null;
|
||||||
|
employees: number | null;
|
||||||
|
established: number | null;
|
||||||
|
internalListingNumber: number | null;
|
||||||
|
reasonForSale: string | null;
|
||||||
|
brokerLicencing: string | null;
|
||||||
|
internals: string | null;
|
||||||
|
created: Date | null;
|
||||||
|
updated: Date | null;
|
||||||
|
visits: number | null;
|
||||||
|
lastVisit: Date | null;
|
||||||
|
}
|
||||||
|
export interface BusinessesInput {
|
||||||
|
id?: string;
|
||||||
|
userId?: string | null;
|
||||||
|
type?: number | null;
|
||||||
|
title?: string | null;
|
||||||
|
description?: string | null;
|
||||||
|
city?: string | null;
|
||||||
|
state?: string | null;
|
||||||
|
price?: number | null;
|
||||||
|
favoritesForUser?: string[] | null;
|
||||||
|
draft?: boolean | null;
|
||||||
|
listingsCategory?: string | null;
|
||||||
|
realEstateIncluded?: boolean | null;
|
||||||
|
leasedLocation?: boolean | null;
|
||||||
|
franchiseResale?: boolean | null;
|
||||||
|
salesRevenue?: number | null;
|
||||||
|
cashFlow?: number | null;
|
||||||
|
supportAndTraining?: string | null;
|
||||||
|
employees?: number | null;
|
||||||
|
established?: number | null;
|
||||||
|
internalListingNumber?: number | null;
|
||||||
|
reasonForSale?: string | null;
|
||||||
|
brokerLicencing?: string | null;
|
||||||
|
internals?: string | null;
|
||||||
|
created?: Date | null;
|
||||||
|
updated?: Date | null;
|
||||||
|
visits?: number | null;
|
||||||
|
lastVisit?: Date | null;
|
||||||
|
}
|
||||||
|
const businesses = {
|
||||||
|
tableName: 'businesses',
|
||||||
|
columns: ['id', 'userId', 'type', 'title', 'description', 'city', 'state', 'price', 'favoritesForUser', 'draft', 'listingsCategory', 'realEstateIncluded', 'leasedLocation', 'franchiseResale', 'salesRevenue', 'cashFlow', 'supportAndTraining', 'employees', 'established', 'internalListingNumber', 'reasonForSale', 'brokerLicencing', 'internals', 'created', 'updated', 'visits', 'lastVisit'],
|
||||||
|
requiredForInsert: [],
|
||||||
|
primaryKey: 'id',
|
||||||
|
foreignKeys: { userId: { table: 'users', column: 'id', $type: null as unknown /* users */ }, },
|
||||||
|
$type: null as unknown as Businesses,
|
||||||
|
$input: null as unknown as BusinessesInput
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
|
||||||
|
export interface TableTypes {
|
||||||
|
businesses: {
|
||||||
|
select: Businesses;
|
||||||
|
input: BusinessesInput;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const tables = {
|
||||||
|
businesses,
|
||||||
|
}
|
||||||
|
|
@ -2,5 +2,10 @@
|
||||||
"/api": {
|
"/api": {
|
||||||
"target": "http://localhost:3000",
|
"target": "http://localhost:3000",
|
||||||
"secure": false
|
"secure": false
|
||||||
|
},
|
||||||
|
"/property": {
|
||||||
|
"target": "http://localhost:3000",
|
||||||
|
"secure": false,
|
||||||
|
"changeOrigin": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
|
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> -->
|
<!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> -->
|
||||||
|
@if(listing){
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-12 md:col-6">
|
<div class="col-12 md:col-6">
|
||||||
<ul class="list-none p-0 m-0 border-top-1 border-300">
|
<ul class="list-none p-0 m-0 border-top-1 border-300">
|
||||||
|
|
@ -95,6 +96,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { MessageService } from 'primeng/api';
|
||||||
import { GalleriaModule } from 'primeng/galleria';
|
import { GalleriaModule } from 'primeng/galleria';
|
||||||
import { lastValueFrom } from 'rxjs';
|
import { lastValueFrom } from 'rxjs';
|
||||||
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { ImageProperty, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { ListingsService } from '../../../services/listings.service';
|
import { ListingsService } from '../../../services/listings.service';
|
||||||
import { MailService } from '../../../services/mail.service';
|
import { MailService } from '../../../services/mail.service';
|
||||||
|
|
@ -43,11 +43,10 @@ export class DetailsBusinessListingComponent {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined;
|
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: BusinessListing;
|
listing: BusinessListing;
|
||||||
criteria: ListingCriteria;
|
criteria: ListingCriteria;
|
||||||
mailinfo: MailInfo;
|
mailinfo: MailInfo;
|
||||||
propertyImages: ImageProperty[] = [];
|
propertyImages: string[] = [];
|
||||||
environment = environment;
|
environment = environment;
|
||||||
user: User;
|
user: User;
|
||||||
description: SafeHtml;
|
description: SafeHtml;
|
||||||
|
|
@ -69,7 +68,7 @@ export class DetailsBusinessListingComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, this.type));
|
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'business'));
|
||||||
this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
|
this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
|
||||||
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
|
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
|
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> -->
|
<!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> -->
|
||||||
|
@if(listing){
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-12 md:col-6">
|
<div class="col-12 md:col-6">
|
||||||
<ul class="list-none p-0 m-0 border-top-1 border-300">
|
<ul class="list-none p-0 m-0 border-top-1 border-300">
|
||||||
|
|
@ -41,7 +42,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
<p-galleria [value]="propertyImages" [showIndicators]="true" [showThumbnails]="false" [responsiveOptions]="responsiveOptions" [containerStyle]="{ 'max-width': '640px' }" [numVisible]="5">
|
<p-galleria [value]="propertyImages" [showIndicators]="true" [showThumbnails]="false" [responsiveOptions]="responsiveOptions" [containerStyle]="{ 'max-width': '640px' }" [numVisible]="5">
|
||||||
<ng-template pTemplate="item" let-item>
|
<ng-template pTemplate="item" let-item>
|
||||||
<img src="{{ environment.apiBaseUrl }}/property/{{ listing.id }}/{{ item.name }}" style="width: 100%" />
|
<img src="property/{{ listing.imagePath }}/{{ item }}" style="width: 100%" />
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<!-- <ng-template pTemplate="thumbnail" let-item>
|
<!-- <ng-template pTemplate="thumbnail" let-item>
|
||||||
<div class="grid grid-nogutter justify-content-center">
|
<div class="grid grid-nogutter justify-content-center">
|
||||||
|
|
@ -85,6 +86,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { MessageService } from 'primeng/api';
|
||||||
import { GalleriaModule } from 'primeng/galleria';
|
import { GalleriaModule } from 'primeng/galleria';
|
||||||
import { lastValueFrom } from 'rxjs';
|
import { lastValueFrom } from 'rxjs';
|
||||||
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { ImageProperty, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { ListingsService } from '../../../services/listings.service';
|
import { ListingsService } from '../../../services/listings.service';
|
||||||
import { MailService } from '../../../services/mail.service';
|
import { MailService } from '../../../services/mail.service';
|
||||||
|
|
@ -43,11 +43,10 @@ export class DetailsCommercialPropertyListingComponent {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined;
|
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;
|
listing: CommercialPropertyListing;
|
||||||
criteria: ListingCriteria;
|
criteria: ListingCriteria;
|
||||||
mailinfo: MailInfo;
|
mailinfo: MailInfo;
|
||||||
propertyImages: ImageProperty[] = [];
|
propertyImages: string[] = [];
|
||||||
environment = environment;
|
environment = environment;
|
||||||
user: User;
|
user: User;
|
||||||
description: SafeHtml;
|
description: SafeHtml;
|
||||||
|
|
@ -69,7 +68,7 @@ export class DetailsCommercialPropertyListingComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, this.type));
|
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'commercialProperty'));
|
||||||
this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
|
this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
|
||||||
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
|
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-2 text-700 line-height-3 text-l font-semibold">{{ user.description }}</p>
|
<p class="mt-2 text-700 line-height-3 text-l font-semibold">{{ user.description }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
//background-image: url(../../../assets/images/index-bg.webp);
|
background-image: url(../../../assets/images/index-bg.webp);
|
||||||
// background-image: url(../../../assets/images/1_Version.jpg);
|
// background-image: url(../../../assets/images/1_Version.jpg);
|
||||||
background-image: url(../../../assets/images/2_1_Version.jpg);
|
//background-image: url(../../../assets/images/2_1_Version.jpg);
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
<div class="search">
|
<div class="search">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="grid p-4 align-items-center">
|
<div class="grid p-4 align-items-center">
|
||||||
<div class="col-1 col-offset-7">
|
<div class="col-2">
|
||||||
|
<p-dropdown [options]="states" [(ngModel)]="criteria.state" optionLabel="name" optionValue="value" [showClear]="true" placeholder="Location" [style]="{ width: '100%' }"></p-dropdown>
|
||||||
|
</div>
|
||||||
|
<div class="col-1 col-offset-9">
|
||||||
<p-button label="Refine" (click)="search()"></p-button>
|
<p-button label="Refine" (click)="search()"></p-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -41,7 +44,7 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-2 surface-200 flex align-items-center justify-content-center">
|
<div class="mb-2 surface-200 flex align-items-center justify-content-center">
|
||||||
<div class="mx-1 text-color">Total number of Listings: {{ totalRecords }}</div>
|
<div class="mx-1 text-color">Total number of Professionals/Brokers: {{ totalRecords }}</div>
|
||||||
<p-paginator (onPageChange)="onPageChange($event)" [first]="first" [rows]="rows" [totalRecords]="totalRecords" [rowsPerPageOptions]="[12, 24, 48]"></p-paginator>
|
<p-paginator (onPageChange)="onPageChange($event)" [first]="first" [rows]="rows" [totalRecords]="totalRecords" [rowsPerPageOptions]="[12, 24, 48]"></p-paginator>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,17 @@ export class BrokerListingsComponent {
|
||||||
this.init();
|
this.init();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async ngOnInit() {}
|
async ngOnInit() {
|
||||||
|
const statesResult = await this.listingsService.getAllStates('business');
|
||||||
|
this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
|
||||||
|
}
|
||||||
async init() {
|
async init() {
|
||||||
this.listings = [];
|
this.search();
|
||||||
this.filteredListings = [];
|
}
|
||||||
this.users = await this.userService.search(this.criteria);
|
async search() {
|
||||||
|
const usersReponse = await this.userService.search(this.criteria);
|
||||||
|
this.users = usersReponse.data;
|
||||||
|
this.totalRecords = usersReponse.total;
|
||||||
const profiles = await this.imageService.getProfileImagesForUsers(this.users.map(u => u.id));
|
const profiles = await this.imageService.getProfileImagesForUsers(this.users.map(u => u.id));
|
||||||
const logos = await this.imageService.getCompanyLogosForUsers(this.users.map(u => u.id));
|
const logos = await this.imageService.getCompanyLogosForUsers(this.users.map(u => u.id));
|
||||||
this.users.forEach(u => {
|
this.users.forEach(u => {
|
||||||
|
|
@ -80,28 +86,12 @@ export class BrokerListingsComponent {
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
}
|
}
|
||||||
setStates() {
|
|
||||||
this.statesSet = new Set();
|
|
||||||
this.listings.forEach(l => {
|
|
||||||
if (l.state) {
|
|
||||||
this.statesSet.add(l.state);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.states = [...this.statesSet].map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
|
|
||||||
}
|
|
||||||
async search() {
|
|
||||||
this.listings = await this.listingsService.getListings(this.criteria, 'professionals_brokers');
|
|
||||||
this.setStates();
|
|
||||||
this.totalRecords = this.listings.length;
|
|
||||||
this.filteredListings = [...this.listings].splice(this.first, this.rows);
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
this.cdRef.detectChanges();
|
|
||||||
}
|
|
||||||
onPageChange(event: any) {
|
onPageChange(event: any) {
|
||||||
this.criteria.start = event.first;
|
this.criteria.start = event.first;
|
||||||
this.criteria.length = event.rows;
|
this.criteria.length = event.rows;
|
||||||
this.criteria.page = event.page;
|
this.criteria.page = event.page;
|
||||||
this.criteria.pageCount = event.pageCount;
|
this.criteria.pageCount = event.pageCount;
|
||||||
|
this.search();
|
||||||
}
|
}
|
||||||
imageErrorHandler(listing: ListingType) {
|
imageErrorHandler(listing: ListingType) {
|
||||||
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,12 @@ import { InputTextModule } from 'primeng/inputtext';
|
||||||
import { PaginatorModule } from 'primeng/paginator';
|
import { PaginatorModule } from 'primeng/paginator';
|
||||||
import { StyleClassModule } from 'primeng/styleclass';
|
import { StyleClassModule } from 'primeng/styleclass';
|
||||||
import { ToggleButtonModule } from 'primeng/togglebutton';
|
import { ToggleButtonModule } from 'primeng/togglebutton';
|
||||||
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { ImageService } from '../../../services/image.service';
|
import { ImageService } from '../../../services/image.service';
|
||||||
import { ListingsService } from '../../../services/listings.service';
|
import { ListingsService } from '../../../services/listings.service';
|
||||||
import { SelectOptionsService } from '../../../services/select-options.service';
|
import { SelectOptionsService } from '../../../services/select-options.service';
|
||||||
import { UserService } from '../../../services/user.service';
|
|
||||||
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
|
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -29,7 +28,6 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
|
||||||
export class BusinessListingsComponent {
|
export class BusinessListingsComponent {
|
||||||
environment = environment;
|
environment = environment;
|
||||||
listings: Array<BusinessListing>;
|
listings: Array<BusinessListing>;
|
||||||
users: Array<User>;
|
|
||||||
filteredListings: Array<BusinessListing>;
|
filteredListings: Array<BusinessListing>;
|
||||||
criteria: ListingCriteria;
|
criteria: ListingCriteria;
|
||||||
realEstateChecked: boolean;
|
realEstateChecked: boolean;
|
||||||
|
|
@ -37,7 +35,6 @@ export class BusinessListingsComponent {
|
||||||
minPrice: string;
|
minPrice: string;
|
||||||
type: string;
|
type: string;
|
||||||
states = [];
|
states = [];
|
||||||
statesSet = new Set();
|
|
||||||
state: string;
|
state: string;
|
||||||
first: number = 0;
|
first: number = 0;
|
||||||
rows: number = 12;
|
rows: number = 12;
|
||||||
|
|
@ -48,7 +45,6 @@ export class BusinessListingsComponent {
|
||||||
constructor(
|
constructor(
|
||||||
public selectOptions: SelectOptionsService,
|
public selectOptions: SelectOptionsService,
|
||||||
private listingsService: ListingsService,
|
private listingsService: ListingsService,
|
||||||
private userService: UserService,
|
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private cdRef: ChangeDetectorRef,
|
private cdRef: ChangeDetectorRef,
|
||||||
|
|
@ -68,30 +64,14 @@ export class BusinessListingsComponent {
|
||||||
}
|
}
|
||||||
async ngOnInit() {}
|
async ngOnInit() {}
|
||||||
async init() {
|
async init() {
|
||||||
this.users = [];
|
const statesResult = await this.listingsService.getAllStates('business');
|
||||||
this.listings = await this.listingsService.getListings(this.criteria, 'business');
|
this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
|
||||||
|
this.search();
|
||||||
this.setStates();
|
|
||||||
//this.filteredListings=[...this.listings];
|
|
||||||
this.totalRecords = this.listings.length;
|
|
||||||
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
this.cdRef.detectChanges();
|
|
||||||
}
|
|
||||||
setStates() {
|
|
||||||
this.statesSet = new Set();
|
|
||||||
this.listings.forEach(l => {
|
|
||||||
if (l.state) {
|
|
||||||
this.statesSet.add(l.state);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.states = [...this.statesSet].map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
|
|
||||||
}
|
}
|
||||||
async search() {
|
async search() {
|
||||||
this.listings = await this.listingsService.getListings(this.criteria, 'business');
|
const listingReponse = await this.listingsService.getListings(this.criteria, 'business');
|
||||||
this.setStates();
|
this.listings = listingReponse.data;
|
||||||
this.totalRecords = this.listings.length;
|
this.totalRecords = listingReponse.total;
|
||||||
this.filteredListings = [...this.listings].splice(this.first, this.rows);
|
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
@ -100,6 +80,7 @@ export class BusinessListingsComponent {
|
||||||
this.criteria.length = event.rows;
|
this.criteria.length = event.rows;
|
||||||
this.criteria.page = event.page;
|
this.criteria.page = event.page;
|
||||||
this.criteria.pageCount = event.pageCount;
|
this.criteria.pageCount = event.pageCount;
|
||||||
|
this.search();
|
||||||
}
|
}
|
||||||
imageErrorHandler(listing: ListingType) {
|
imageErrorHandler(listing: ListingType) {
|
||||||
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<article class="flex flex-column md:flex-row w-full gap-3 p-3 surface-card">
|
<article class="flex flex-column md:flex-row w-full gap-3 p-3 surface-card">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
@if (listing.imageOrder.length>0){
|
@if (listing.imageOrder.length>0){
|
||||||
<img src="{{ environment.apiBaseUrl }}/property/{{ listing.id }}/{{ listing.imageOrder[0] }}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" />
|
<img src="property/{{ listing.imagePath }}/{{ listing.imageOrder[0] }}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" />
|
||||||
} @else {
|
} @else {
|
||||||
<!-- <img src="{{environment.apiBaseUrl}}/property/{{listing.id}}/{{listing.imageOrder[0].name}}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem"> -->
|
<!-- <img src="{{environment.apiBaseUrl}}/property/{{listing.id}}/{{listing.imageOrder[0].name}}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem"> -->
|
||||||
<img src="assets/images/placeholder_properties.jpg" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" />
|
<img src="assets/images/placeholder_properties.jpg" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" />
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,12 @@ import { InputTextModule } from 'primeng/inputtext';
|
||||||
import { PaginatorModule } from 'primeng/paginator';
|
import { PaginatorModule } from 'primeng/paginator';
|
||||||
import { StyleClassModule } from 'primeng/styleclass';
|
import { StyleClassModule } from 'primeng/styleclass';
|
||||||
import { ToggleButtonModule } from 'primeng/togglebutton';
|
import { ToggleButtonModule } from 'primeng/togglebutton';
|
||||||
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { ImageService } from '../../../services/image.service';
|
import { ImageService } from '../../../services/image.service';
|
||||||
import { ListingsService } from '../../../services/listings.service';
|
import { ListingsService } from '../../../services/listings.service';
|
||||||
import { SelectOptionsService } from '../../../services/select-options.service';
|
import { SelectOptionsService } from '../../../services/select-options.service';
|
||||||
import { UserService } from '../../../services/user.service';
|
|
||||||
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
|
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -29,7 +28,6 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
|
||||||
export class CommercialPropertyListingsComponent {
|
export class CommercialPropertyListingsComponent {
|
||||||
environment = environment;
|
environment = environment;
|
||||||
listings: Array<CommercialPropertyListing>;
|
listings: Array<CommercialPropertyListing>;
|
||||||
users: Array<User>;
|
|
||||||
filteredListings: Array<CommercialPropertyListing>;
|
filteredListings: Array<CommercialPropertyListing>;
|
||||||
criteria: ListingCriteria;
|
criteria: ListingCriteria;
|
||||||
realEstateChecked: boolean;
|
realEstateChecked: boolean;
|
||||||
|
|
@ -48,7 +46,6 @@ export class CommercialPropertyListingsComponent {
|
||||||
constructor(
|
constructor(
|
||||||
public selectOptions: SelectOptionsService,
|
public selectOptions: SelectOptionsService,
|
||||||
private listingsService: ListingsService,
|
private listingsService: ListingsService,
|
||||||
private userService: UserService,
|
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private cdRef: ChangeDetectorRef,
|
private cdRef: ChangeDetectorRef,
|
||||||
|
|
@ -67,41 +64,24 @@ export class CommercialPropertyListingsComponent {
|
||||||
}
|
}
|
||||||
async ngOnInit() {}
|
async ngOnInit() {}
|
||||||
async init() {
|
async init() {
|
||||||
this.users = [];
|
const statesResult = await this.listingsService.getAllStates('business');
|
||||||
this.listings = await this.listingsService.getListings(this.criteria, 'commercialProperty');
|
this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
|
||||||
|
this.search();
|
||||||
|
}
|
||||||
|
|
||||||
this.setStates();
|
|
||||||
//this.filteredListings=[...this.listings];
|
|
||||||
this.totalRecords = this.listings.length;
|
|
||||||
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
this.cdRef.detectChanges();
|
|
||||||
}
|
|
||||||
setStates() {
|
|
||||||
this.statesSet = new Set();
|
|
||||||
this.listings.forEach(l => {
|
|
||||||
if (l.state) {
|
|
||||||
this.statesSet.add(l.state);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.states = [...this.statesSet].map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
|
|
||||||
}
|
|
||||||
async search() {
|
async search() {
|
||||||
this.listings = await this.listingsService.getListings(this.criteria, 'commercialProperty');
|
const listingReponse = await this.listingsService.getListings(this.criteria, 'commercialProperty');
|
||||||
this.setStates();
|
this.listings = listingReponse.data;
|
||||||
this.totalRecords = this.listings.length;
|
this.totalRecords = listingReponse.total;
|
||||||
this.filteredListings = [...this.listings].splice(this.first, this.rows);
|
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
}
|
}
|
||||||
onPageChange(event: any) {
|
onPageChange(event: any) {
|
||||||
//this.first = event.first;
|
|
||||||
//this.rows = event.rows;
|
|
||||||
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
|
|
||||||
this.criteria.start = event.first;
|
this.criteria.start = event.first;
|
||||||
this.criteria.length = event.rows;
|
this.criteria.length = event.rows;
|
||||||
this.criteria.page = event.page;
|
this.criteria.page = event.page;
|
||||||
this.criteria.pageCount = event.pageCount;
|
this.criteria.pageCount = event.pageCount;
|
||||||
|
this.search();
|
||||||
}
|
}
|
||||||
imageErrorHandler(listing: ListingType) {
|
imageErrorHandler(listing: ListingType) {
|
||||||
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export class EditBusinessListingComponent {
|
||||||
maxFileSize = 3000000;
|
maxFileSize = 3000000;
|
||||||
uploadUrl: string;
|
uploadUrl: string;
|
||||||
environment = environment;
|
environment = environment;
|
||||||
propertyImages: ImageProperty[];
|
propertyImages: string[];
|
||||||
responsiveOptions = [
|
responsiveOptions = [
|
||||||
{
|
{
|
||||||
breakpoint: '1199px',
|
breakpoint: '1199px',
|
||||||
|
|
|
||||||
|
|
@ -103,8 +103,8 @@
|
||||||
@for (image of propertyImages; track image) {
|
@for (image of propertyImages; track image) {
|
||||||
<span cdkDropList mixedCdkDropList>
|
<span cdkDropList mixedCdkDropList>
|
||||||
<div cdkDrag mixedCdkDragSizeHelper class="image-wrap">
|
<div cdkDrag mixedCdkDragSizeHelper class="image-wrap">
|
||||||
<img src="{{ environment.apiBaseUrl }}/property/{{ listing.id }}/{{ image.name }}" [alt]="image.name" class="shadow-2" cdkDrag />
|
<img src="property/{{ listing.id }}/{{ image }}" [alt]="image" class="shadow-2" cdkDrag />
|
||||||
<fa-icon [icon]="faTrash" (click)="deleteConfirm(image.name)"></fa-icon>
|
<fa-icon [icon]="faTrash" (click)="deleteConfirm(image)"></fa-icon>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ export class EditCommercialPropertyListingComponent {
|
||||||
maxFileSize = 3000000;
|
maxFileSize = 3000000;
|
||||||
uploadUrl: string;
|
uploadUrl: string;
|
||||||
environment = environment;
|
environment = environment;
|
||||||
propertyImages: ImageProperty[];
|
propertyImages: string[];
|
||||||
responsiveOptions = [
|
responsiveOptions = [
|
||||||
{
|
{
|
||||||
breakpoint: '1199px',
|
breakpoint: '1199px',
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable, lastValueFrom } from 'rxjs';
|
import { Observable, lastValueFrom } from 'rxjs';
|
||||||
import { BusinessListing } from '../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing } from '../../../../bizmatch-server/src/models/db.model';
|
||||||
import { ImageProperty, ListingCriteria, ListingType, ResponseBusinessListingArray } from '../../../../bizmatch-server/src/models/main.model';
|
import { ListingCriteria, ListingType, ResponseBusinessListingArray, ResponseCommercialPropertyListingArray, StatesResult } from '../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
|
|
@ -15,9 +15,9 @@ export class ListingsService {
|
||||||
// getAllListings():Observable<ListingType[]>{
|
// getAllListings():Observable<ListingType[]>{
|
||||||
// return this.http.get<ListingType[]>(`${this.apiBaseUrl}/bizmatch/business-listings`);
|
// return this.http.get<ListingType[]>(`${this.apiBaseUrl}/bizmatch/business-listings`);
|
||||||
// }
|
// }
|
||||||
async getListings(criteria: ListingCriteria, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ListingType[]> {
|
async getListings(criteria: ListingCriteria, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
|
||||||
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/search`, criteria));
|
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/search`, criteria));
|
||||||
return result.data;
|
return result;
|
||||||
}
|
}
|
||||||
getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> {
|
getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> {
|
||||||
const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
|
const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
|
||||||
|
|
@ -33,13 +33,17 @@ export class ListingsService {
|
||||||
return await lastValueFrom(this.http.post<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}`, listing));
|
return await lastValueFrom(this.http.post<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}`, listing));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async getAllStates(listingsCategory?: 'business' | 'commercialProperty'): Promise<StatesResult[]> {
|
||||||
|
const result = lastValueFrom(this.http.get<StatesResult[]>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/states/all`));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
async deleteListing(id: string, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
|
async deleteListing(id: string, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
|
||||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`));
|
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`));
|
||||||
}
|
}
|
||||||
async getPropertyImages(id: string): Promise<ImageProperty[]> {
|
async getPropertyImages(id: string): Promise<string[]> {
|
||||||
return await lastValueFrom(this.http.get<ImageProperty[]>(`${this.apiBaseUrl}/bizmatch/image/${id}`));
|
return await lastValueFrom(this.http.get<string[]>(`${this.apiBaseUrl}/bizmatch/image/${id}`));
|
||||||
}
|
}
|
||||||
async changeImageOrder(id: string, propertyImages: ImageProperty[]): Promise<ImageProperty[]> {
|
async changeImageOrder(id: string, propertyImages: string[]): Promise<string[]> {
|
||||||
return await lastValueFrom(this.http.put<ImageProperty[]>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/imageOrder/${id}`, propertyImages));
|
return await lastValueFrom(this.http.put<string[]>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/imageOrder/${id}`, propertyImages));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { jwtDecode } from 'jwt-decode';
|
||||||
import { Observable, distinctUntilChanged, filter, from, lastValueFrom, map } from 'rxjs';
|
import { Observable, distinctUntilChanged, filter, from, lastValueFrom, map } from 'rxjs';
|
||||||
import urlcat from 'urlcat';
|
import urlcat from 'urlcat';
|
||||||
import { User } from '../../../../bizmatch-server/src/models/db.model';
|
import { User } from '../../../../bizmatch-server/src/models/db.model';
|
||||||
import { JwtToken, ListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
import { JwtToken, ListingCriteria, ResponseUsersArray } from '../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { KeycloakService } from './keycloak.service';
|
import { KeycloakService } from './keycloak.service';
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ export class UserService {
|
||||||
const url = urlcat(`${this.apiBaseUrl}/bizmatch/user`, { mail });
|
const url = urlcat(`${this.apiBaseUrl}/bizmatch/user`, { mail });
|
||||||
return await lastValueFrom(this.http.get<User>(url));
|
return await lastValueFrom(this.http.get<User>(url));
|
||||||
}
|
}
|
||||||
async search(criteria?: ListingCriteria) {
|
async search(criteria?: ListingCriteria): Promise<ResponseUsersArray> {
|
||||||
return await lastValueFrom(this.http.post<User[]>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria));
|
return await lastValueFrom(this.http.post<ResponseUsersArray>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue