Einbau klassische Filter als Overlay ...
This commit is contained in:
parent
af982d19d8
commit
bdafb03165
|
|
@ -12,7 +12,6 @@ import winston from 'winston';
|
|||
import { BusinessListing, CommercialPropertyListing, User, UserData } from '../models/db.model.js';
|
||||
import { emailToDirName, KeyValueStyle } from '../models/main.model.js';
|
||||
import * as schema from './schema.js';
|
||||
import { users } from './schema.js';
|
||||
const typesOfBusiness: Array<KeyValueStyle> = [
|
||||
{ name: 'Automotive', value: '1', icon: 'fa-solid fa-car', textColorClass: 'text-green-400' },
|
||||
{ name: 'Industrial Services', value: '2', icon: 'fa-solid fa-industry', textColorClass: 'text-yellow-400' },
|
||||
|
|
@ -65,9 +64,9 @@ deleteFilesOfDir(targetPathProperty);
|
|||
fs.ensureDirSync(`./pictures/logo`);
|
||||
fs.ensureDirSync(`./pictures/profile`);
|
||||
fs.ensureDirSync(`./pictures/property`);
|
||||
type UserProfile = Omit<User, 'created' | 'updated' | 'hasCompanyLogo' | 'hasProfile' | 'id'>;
|
||||
// type UserProfile = Omit<User, 'created' | 'updated' | 'hasCompanyLogo' | 'hasProfile' | 'id'>;
|
||||
|
||||
type NewUser = typeof users.$inferInsert;
|
||||
// type NewUser = typeof users.$inferInsert;
|
||||
//for (const userData of usersData) {
|
||||
for (let index = 0; index < usersData.length; index++) {
|
||||
const userData = usersData[index];
|
||||
|
|
@ -98,20 +97,17 @@ for (let index = 0; index < usersData.length; index++) {
|
|||
user.customerSubType = 'broker';
|
||||
user.created = new Date();
|
||||
user.updated = new Date();
|
||||
const createUserProfile = (user: User): UserProfile => {
|
||||
const { id, created, updated, hasCompanyLogo, hasProfile, ...userProfile } = user;
|
||||
return userProfile;
|
||||
};
|
||||
const userProfile = createUserProfile(user);
|
||||
logger.info(`${index} - ${JSON.stringify(userProfile)}`);
|
||||
const embedding = await createEmbedding(JSON.stringify(userProfile));
|
||||
sleep(200);
|
||||
// const createUserProfile = (user: User): UserProfile => {
|
||||
// const { id, created, updated, hasCompanyLogo, hasProfile, ...userProfile } = user;
|
||||
// return userProfile;
|
||||
// };
|
||||
// const userProfile = createUserProfile(user);
|
||||
// logger.info(`${index} - ${JSON.stringify(userProfile)}`);
|
||||
// const embedding = await createEmbedding(JSON.stringify(userProfile));
|
||||
//sleep(200);
|
||||
const u = await db
|
||||
.insert(schema.users)
|
||||
.values({
|
||||
...user,
|
||||
embedding: embedding,
|
||||
} as NewUser)
|
||||
.values(user)
|
||||
.returning({ insertedId: schema.users.id, gender: schema.users.gender, email: schema.users.email, firstname: schema.users.firstname, lastname: schema.users.lastname });
|
||||
generatedUserData.push(u[0]);
|
||||
i++;
|
||||
|
|
@ -145,25 +141,20 @@ for (let index = 0; index < commercialJsonData.length; index++) {
|
|||
commercial.updated = insertionDate;
|
||||
commercial.email = user.email;
|
||||
commercial.draft = false;
|
||||
const reducedCommercial = {
|
||||
city: commercial.city,
|
||||
description: commercial.description,
|
||||
email: commercial.email,
|
||||
price: commercial.price,
|
||||
state: sso.locations.find(l => l.value === commercial.state)?.name,
|
||||
title: commercial.title,
|
||||
name: `${user.firstname} ${user.lastname}`,
|
||||
};
|
||||
const embedding = await createEmbedding(JSON.stringify(reducedCommercial));
|
||||
sleep(200);
|
||||
const result = await db
|
||||
.insert(schema.commercials)
|
||||
.values({
|
||||
...commercial,
|
||||
embedding: embedding,
|
||||
})
|
||||
.returning();
|
||||
logger.info(`commercial_${index} inserted`);
|
||||
commercial.type = sso.typesOfCommercialProperty.find(e => e.oldValue === String(commercial.type)).value;
|
||||
// const reducedCommercial = {
|
||||
// city: commercial.city,
|
||||
// description: commercial.description,
|
||||
// email: commercial.email,
|
||||
// price: commercial.price,
|
||||
// state: sso.locations.find(l => l.value === commercial.state)?.name,
|
||||
// title: commercial.title,
|
||||
// name: `${user.firstname} ${user.lastname}`,
|
||||
// };
|
||||
// const embedding = await createEmbedding(JSON.stringify(reducedCommercial));
|
||||
// sleep(200);
|
||||
const result = await db.insert(schema.commercials).values(commercial).returning();
|
||||
// logger.info(`commercial_${index} inserted`);
|
||||
try {
|
||||
fs.copySync(`./pictures_base/property/${id}`, `./pictures/property/${result[0].imagePath}/${result[0].serialId}`);
|
||||
} catch (err) {
|
||||
|
|
@ -178,37 +169,34 @@ const businessJsonData = JSON.parse(data) as BusinessListing[]; // Erwartet ein
|
|||
for (let index = 0; index < businessJsonData.length; index++) {
|
||||
const business = businessJsonData[index];
|
||||
delete business.id;
|
||||
business.type = sso.typesOfBusiness.find(e => e.oldValue === String(business.type)).value;
|
||||
business.created = new Date(business.created);
|
||||
business.updated = new Date(business.created);
|
||||
const user = getRandomItem(generatedUserData);
|
||||
business.email = user.email;
|
||||
business.imageName = emailToDirName(user.email);
|
||||
const embeddingText = JSON.stringify({
|
||||
type: typesOfBusiness.find(b => b.value === String(business.type))?.name,
|
||||
title: business.title,
|
||||
description: business.description,
|
||||
email: business.email,
|
||||
city: business.city,
|
||||
state: sso.locations.find(l => l.value === business.state)?.name,
|
||||
price: business.price,
|
||||
realEstateIncluded: business.realEstateIncluded,
|
||||
leasedLocation: business.leasedLocation,
|
||||
franchiseResale: business.franchiseResale,
|
||||
salesRevenue: business.salesRevenue,
|
||||
cashFlow: business.cashFlow,
|
||||
supportAndTraining: business.supportAndTraining,
|
||||
employees: business.employees,
|
||||
established: business.established,
|
||||
reasonForSale: business.reasonForSale,
|
||||
name: `${user.firstname} ${user.lastname}`,
|
||||
});
|
||||
const embedding = await createEmbedding(embeddingText);
|
||||
// const embeddingText = JSON.stringify({
|
||||
// type: typesOfBusiness.find(b => b.value === String(business.type))?.name,
|
||||
// title: business.title,
|
||||
// description: business.description,
|
||||
// email: business.email,
|
||||
// city: business.city,
|
||||
// state: sso.locations.find(l => l.value === business.state)?.name,
|
||||
// price: business.price,
|
||||
// realEstateIncluded: business.realEstateIncluded,
|
||||
// leasedLocation: business.leasedLocation,
|
||||
// franchiseResale: business.franchiseResale,
|
||||
// salesRevenue: business.salesRevenue,
|
||||
// cashFlow: business.cashFlow,
|
||||
// supportAndTraining: business.supportAndTraining,
|
||||
// employees: business.employees,
|
||||
// established: business.established,
|
||||
// reasonForSale: business.reasonForSale,
|
||||
// name: `${user.firstname} ${user.lastname}`,
|
||||
// });
|
||||
// const embedding = await createEmbedding(embeddingText);
|
||||
sleep(200);
|
||||
await db.insert(schema.businesses).values({
|
||||
...business,
|
||||
embedding: embedding,
|
||||
});
|
||||
logger.info(`business_${index} inserted`);
|
||||
await db.insert(schema.businesses).values(business);
|
||||
}
|
||||
|
||||
//End
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE "businesses" ALTER COLUMN "type" SET DATA TYPE varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE "commercials" ALTER COLUMN "type" SET DATA TYPE varchar(255);
|
||||
|
|
@ -0,0 +1,549 @@
|
|||
{
|
||||
"id": "93be31d4-beec-4ba8-8d4a-a52763342335",
|
||||
"prevId": "2d8edad3-5544-4cb1-a543-84c07737ea9f",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.businesses": {
|
||||
"name": "businesses",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"city": {
|
||||
"name": "city",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"state": {
|
||||
"name": "state",
|
||||
"type": "char(2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"price": {
|
||||
"name": "price",
|
||||
"type": "double precision",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"favoritesForUser": {
|
||||
"name": "favoritesForUser",
|
||||
"type": "varchar(30)[]",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"draft": {
|
||||
"name": "draft",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"listingsCategory": {
|
||||
"name": "listingsCategory",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"realEstateIncluded": {
|
||||
"name": "realEstateIncluded",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"leasedLocation": {
|
||||
"name": "leasedLocation",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"franchiseResale": {
|
||||
"name": "franchiseResale",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"salesRevenue": {
|
||||
"name": "salesRevenue",
|
||||
"type": "double precision",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"cashFlow": {
|
||||
"name": "cashFlow",
|
||||
"type": "double precision",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"supportAndTraining": {
|
||||
"name": "supportAndTraining",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"employees": {
|
||||
"name": "employees",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"established": {
|
||||
"name": "established",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"internalListingNumber": {
|
||||
"name": "internalListingNumber",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"reasonForSale": {
|
||||
"name": "reasonForSale",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"brokerLicencing": {
|
||||
"name": "brokerLicencing",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"internals": {
|
||||
"name": "internals",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"imagePath": {
|
||||
"name": "imagePath",
|
||||
"type": "varchar(200)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created": {
|
||||
"name": "created",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"updated": {
|
||||
"name": "updated",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"visits": {
|
||||
"name": "visits",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"lastVisit": {
|
||||
"name": "lastVisit",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"embedding": {
|
||||
"name": "embedding",
|
||||
"type": "vector(1536)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"businesses_email_users_email_fk": {
|
||||
"name": "businesses_email_users_email_fk",
|
||||
"tableFrom": "businesses",
|
||||
"tableTo": "users",
|
||||
"columnsFrom": [
|
||||
"email"
|
||||
],
|
||||
"columnsTo": [
|
||||
"email"
|
||||
],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"public.commercials": {
|
||||
"name": "commercials",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"serial_id": {
|
||||
"name": "serial_id",
|
||||
"type": "serial",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"title": {
|
||||
"name": "title",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"city": {
|
||||
"name": "city",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"state": {
|
||||
"name": "state",
|
||||
"type": "char(2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"price": {
|
||||
"name": "price",
|
||||
"type": "double precision",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"favoritesForUser": {
|
||||
"name": "favoritesForUser",
|
||||
"type": "varchar(30)[]",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"listingsCategory": {
|
||||
"name": "listingsCategory",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"hideImage": {
|
||||
"name": "hideImage",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"draft": {
|
||||
"name": "draft",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"zipCode": {
|
||||
"name": "zipCode",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"county": {
|
||||
"name": "county",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"imageOrder": {
|
||||
"name": "imageOrder",
|
||||
"type": "varchar(200)[]",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"imagePath": {
|
||||
"name": "imagePath",
|
||||
"type": "varchar(200)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created": {
|
||||
"name": "created",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"updated": {
|
||||
"name": "updated",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"visits": {
|
||||
"name": "visits",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"lastVisit": {
|
||||
"name": "lastVisit",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"embedding": {
|
||||
"name": "embedding",
|
||||
"type": "vector(1536)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"commercials_email_users_email_fk": {
|
||||
"name": "commercials_email_users_email_fk",
|
||||
"tableFrom": "commercials",
|
||||
"tableTo": "users",
|
||||
"columnsFrom": [
|
||||
"email"
|
||||
],
|
||||
"columnsTo": [
|
||||
"email"
|
||||
],
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"public.users": {
|
||||
"name": "users",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"firstname": {
|
||||
"name": "firstname",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"lastname": {
|
||||
"name": "lastname",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"phoneNumber": {
|
||||
"name": "phoneNumber",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"description": {
|
||||
"name": "description",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"companyName": {
|
||||
"name": "companyName",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"companyOverview": {
|
||||
"name": "companyOverview",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"companyWebsite": {
|
||||
"name": "companyWebsite",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"companyLocation": {
|
||||
"name": "companyLocation",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"offeredServices": {
|
||||
"name": "offeredServices",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"areasServed": {
|
||||
"name": "areasServed",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"hasProfile": {
|
||||
"name": "hasProfile",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"hasCompanyLogo": {
|
||||
"name": "hasCompanyLogo",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"licensedIn": {
|
||||
"name": "licensedIn",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"gender": {
|
||||
"name": "gender",
|
||||
"type": "gender",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"customerType": {
|
||||
"name": "customerType",
|
||||
"type": "customerType",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"customerSubType": {
|
||||
"name": "customerSubType",
|
||||
"type": "customerSubType",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created": {
|
||||
"name": "created",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"updated": {
|
||||
"name": "updated",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"embedding": {
|
||||
"name": "embedding",
|
||||
"type": "vector(1536)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"users_email_unique": {
|
||||
"name": "users_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"email"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"public.customerSubType": {
|
||||
"name": "customerSubType",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"broker",
|
||||
"cpa",
|
||||
"attorney",
|
||||
"titleCompany",
|
||||
"surveyor",
|
||||
"appraiser"
|
||||
]
|
||||
},
|
||||
"public.customerType": {
|
||||
"name": "customerType",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"buyer",
|
||||
"professional"
|
||||
]
|
||||
},
|
||||
"public.gender": {
|
||||
"name": "gender",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"male",
|
||||
"female"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,13 @@
|
|||
"when": 1720872296432,
|
||||
"tag": "0000_slim_nova",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "7",
|
||||
"when": 1721134224160,
|
||||
"tag": "0001_heavy_bloodscream",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ export const users = pgTable('users', {
|
|||
export const businesses = pgTable('businesses', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
email: varchar('email', { length: 255 }).references(() => users.email),
|
||||
type: integer('type'),
|
||||
type: varchar('type', { length: 255 }),
|
||||
title: varchar('title', { length: 255 }),
|
||||
description: text('description'),
|
||||
city: varchar('city', { length: 255 }),
|
||||
|
|
@ -66,7 +66,7 @@ export const commercials = pgTable('commercials', {
|
|||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
serialId: serial('serial_id'),
|
||||
email: varchar('email', { length: 255 }).references(() => users.email),
|
||||
type: integer('type'),
|
||||
type: varchar('type', { length: 255 }),
|
||||
title: varchar('title', { length: 255 }),
|
||||
description: text('description'),
|
||||
city: varchar('city', { length: 255 }),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
|||
import { Logger } from 'winston';
|
||||
import { businesses } from '../drizzle/schema.js';
|
||||
import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js';
|
||||
import { JwtUser, ListingCriteria } from '../models/main.model.js';
|
||||
import { BusinessListingCriteria, JwtUser } from '../models/main.model.js';
|
||||
import { ListingsService } from './listings.service.js';
|
||||
|
||||
@Controller('listings/business')
|
||||
|
|
@ -27,13 +27,13 @@ export class BusinessListingsController {
|
|||
|
||||
@UseGuards(OptionalJwtAuthGuard)
|
||||
@Post('find')
|
||||
find(@Request() req, @Body() criteria: ListingCriteria): any {
|
||||
find(@Request() req, @Body() criteria: BusinessListingCriteria): any {
|
||||
return this.listingsService.findBusinessListings(criteria, req.user as JwtUser);
|
||||
}
|
||||
|
||||
@UseGuards(OptionalJwtAuthGuard)
|
||||
@Post('search')
|
||||
search(@Request() req, @Body() criteria: ListingCriteria): any {
|
||||
search(@Request() req, @Body() criteria: BusinessListingCriteria): any {
|
||||
return this.listingsService.searchBusinessListings(criteria.prompt);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { commercials } from '../drizzle/schema.js';
|
|||
import { FileService } from '../file/file.service.js';
|
||||
import { OptionalJwtAuthGuard } from '../jwt-auth/optional-jwt-auth.guard.js';
|
||||
import { CommercialPropertyListing } from '../models/db.model';
|
||||
import { JwtUser, ListingCriteria } from '../models/main.model.js';
|
||||
import { CommercialPropertyListingCriteria, JwtUser } from '../models/main.model.js';
|
||||
import { ListingsService } from './listings.service.js';
|
||||
|
||||
@Controller('listings/commercialProperty')
|
||||
|
|
@ -29,7 +29,7 @@ export class CommercialPropertyListingsController {
|
|||
}
|
||||
@UseGuards(OptionalJwtAuthGuard)
|
||||
@Post('find')
|
||||
async find(@Request() req, @Body() criteria: ListingCriteria): Promise<any> {
|
||||
async find(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<any> {
|
||||
return await this.listingsService.findCommercialPropertyListings(criteria, req.user as JwtUser);
|
||||
}
|
||||
@Get('states/all')
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { and, eq, gte, ilike, lte, ne, or, sql } from 'drizzle-orm';
|
||||
import { and, eq, gte, ilike, inArray, lte, ne, or, sql } from 'drizzle-orm';
|
||||
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||
import OpenAI from 'openai';
|
||||
import { Logger } from 'winston';
|
||||
import * as schema from '../drizzle/schema.js';
|
||||
import { PG_CONNECTION, businesses, commercials } from '../drizzle/schema.js';
|
||||
import { businesses, commercials, PG_CONNECTION } from '../drizzle/schema.js';
|
||||
import { FileService } from '../file/file.service.js';
|
||||
import { BusinessListing, CommercialPropertyListing } from '../models/db.model';
|
||||
import { JwtUser, ListingCriteria, emailToDirName } from '../models/main.model.js';
|
||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, emailToDirName, JwtUser } from '../models/main.model.js';
|
||||
|
||||
@Injectable()
|
||||
export class ListingsService {
|
||||
|
|
@ -22,10 +22,10 @@ export class ListingsService {
|
|||
apiKey: process.env.OPENAI_API_KEY, // Stellen Sie sicher, dass Sie Ihren API-Key als Umgebungsvariable setzen
|
||||
});
|
||||
}
|
||||
private getConditions(criteria: ListingCriteria, table: typeof businesses | typeof commercials, user: JwtUser): any[] {
|
||||
private getConditions(criteria: BusinessListingCriteria | CommercialPropertyListingCriteria, table: typeof businesses | typeof commercials, user: JwtUser): any[] {
|
||||
const conditions = [];
|
||||
if (criteria.type) {
|
||||
conditions.push(eq(table.type, criteria.type));
|
||||
if (criteria.types?.length > 0) {
|
||||
conditions.push(inArray(table.type, criteria.types));
|
||||
}
|
||||
if (criteria.state) {
|
||||
conditions.push(eq(table.state, criteria.state));
|
||||
|
|
@ -36,9 +36,6 @@ export class ListingsService {
|
|||
if (criteria.maxPrice) {
|
||||
conditions.push(lte(table.price, criteria.maxPrice));
|
||||
}
|
||||
if (criteria.realEstateChecked) {
|
||||
conditions.push(eq(businesses.realEstateIncluded, true));
|
||||
}
|
||||
if (criteria.title) {
|
||||
conditions.push(ilike(table.title, `%${criteria.title}%`));
|
||||
}
|
||||
|
|
@ -61,7 +58,7 @@ export class ListingsService {
|
|||
return results as BusinessListing[];
|
||||
}
|
||||
// #### Find by criteria ########################################
|
||||
async findCommercialPropertyListings(criteria: ListingCriteria, user: JwtUser): Promise<any> {
|
||||
async findCommercialPropertyListings(criteria: CommercialPropertyListingCriteria, user: JwtUser): Promise<any> {
|
||||
const start = criteria.start ? criteria.start : 0;
|
||||
const length = criteria.length ? criteria.length : 12;
|
||||
const conditions = this.getConditions(criteria, commercials, user);
|
||||
|
|
@ -83,7 +80,7 @@ export class ListingsService {
|
|||
]);
|
||||
return { total, data };
|
||||
}
|
||||
async findBusinessListings(criteria: ListingCriteria, user: JwtUser): Promise<any> {
|
||||
async findBusinessListings(criteria: BusinessListingCriteria, user: JwtUser): Promise<any> {
|
||||
const start = criteria.start ? criteria.start : 0;
|
||||
const length = criteria.length ? criteria.length : 12;
|
||||
const conditions = this.getConditions(criteria, businesses, user);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export interface UserData {
|
|||
export interface BusinessListing {
|
||||
id: string;
|
||||
email?: string;
|
||||
type?: number;
|
||||
type?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
city?: string;
|
||||
|
|
@ -77,7 +77,7 @@ export interface CommercialPropertyListing {
|
|||
id: string;
|
||||
serialId?: number;
|
||||
email?: string;
|
||||
type?: number;
|
||||
type?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
city?: string;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export interface KeyValueRatio {
|
|||
export interface KeyValueStyle {
|
||||
name: string;
|
||||
value: string;
|
||||
oldValue?: string;
|
||||
icon: string;
|
||||
textColorClass: string;
|
||||
}
|
||||
|
|
@ -52,20 +53,51 @@ export type ResponseUsersArray = {
|
|||
data: User[];
|
||||
total: number;
|
||||
};
|
||||
export interface ListingCriteria {
|
||||
export interface ListCriteria {
|
||||
start: number;
|
||||
length: number;
|
||||
page: number;
|
||||
pageCount: number;
|
||||
type: number;
|
||||
city: string;
|
||||
types: string[];
|
||||
prompt: string;
|
||||
criteriaType: 'business' | 'commercialProperty' | 'user';
|
||||
}
|
||||
export interface BusinessListingCriteria extends ListCriteria {
|
||||
state: string;
|
||||
county: string;
|
||||
minPrice: number;
|
||||
maxPrice: number;
|
||||
minRevenue: number;
|
||||
maxRevenue: number;
|
||||
minCashFlow: number;
|
||||
maxCashFlow: number;
|
||||
minNumberEmployees: number;
|
||||
maxNumberEmployees: number;
|
||||
establishedSince: number;
|
||||
establishedUntil: number;
|
||||
realEstateChecked: boolean;
|
||||
leasedLocation: boolean;
|
||||
franchiseResale: boolean;
|
||||
title: string;
|
||||
category: 'professional' | 'broker';
|
||||
name: string;
|
||||
prompt: string;
|
||||
brokerName: string;
|
||||
criteriaType: 'business';
|
||||
}
|
||||
export interface CommercialPropertyListingCriteria extends ListCriteria {
|
||||
state: string;
|
||||
county: string;
|
||||
minPrice: number;
|
||||
maxPrice: number;
|
||||
title: string;
|
||||
criteriaType: 'commercialProperty';
|
||||
}
|
||||
export interface UserListingCriteria extends ListCriteria {
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
companyName: string;
|
||||
counties: string[];
|
||||
states: string[];
|
||||
criteriaType: 'user';
|
||||
}
|
||||
|
||||
export interface KeycloakUser {
|
||||
|
|
|
|||
|
|
@ -5,28 +5,28 @@ import { ImageType, KeyValue, KeyValueStyle } from '../models/main.model.js';
|
|||
export class SelectOptionsService {
|
||||
constructor() {}
|
||||
public typesOfBusiness: Array<KeyValueStyle> = [
|
||||
{ name: 'Automotive', value: '1', icon: 'fa-solid fa-car', textColorClass: 'text-green-400' },
|
||||
{ name: 'Industrial Services', value: '2', icon: 'fa-solid fa-industry', textColorClass: 'text-yellow-400' },
|
||||
{ name: 'Real Estate', value: '3', icon: 'fa-solid fa-building', textColorClass: 'text-blue-400' },
|
||||
{ name: 'Uncategorized', value: '4', icon: 'fa-solid fa-question', textColorClass: 'text-cyan-400' },
|
||||
{ name: 'Retail', value: '5', icon: 'fa-solid fa-money-bill-wave', textColorClass: 'text-pink-400' },
|
||||
{ name: 'Oilfield SVE and MFG.', value: '6', icon: 'fa-solid fa-oil-well', textColorClass: 'text-indigo-400' },
|
||||
{ name: 'Service', value: '7', icon: 'fa-solid fa-umbrella', textColorClass: 'text-teal-400' },
|
||||
{ name: 'Advertising', value: '8', icon: 'fa-solid fa-rectangle-ad', textColorClass: 'text-orange-400' },
|
||||
{ name: 'Agriculture', value: '9', icon: 'fa-solid fa-wheat-awn', textColorClass: 'text-sky-400' },
|
||||
{ name: 'Franchise', value: '10', icon: 'fa-solid fa-star', textColorClass: 'text-purple-400' },
|
||||
{ name: 'Professional', value: '11', icon: 'fa-solid fa-user-gear', textColorClass: 'text-gray-400' },
|
||||
{ name: 'Manufacturing', value: '12', icon: 'fa-solid fa-industry', textColorClass: 'text-red-400' },
|
||||
{ name: 'Food and Restaurant', value: '13', icon: 'fa-solid fa-utensils', textColorClass: 'text-amber-700' },
|
||||
{ name: 'Automotive', value: 'automotive', oldValue: '1', icon: 'fa-solid fa-car', textColorClass: 'text-green-400' },
|
||||
{ name: 'Industrial Services', value: 'industrialServices', oldValue: '2', icon: 'fa-solid fa-industry', textColorClass: 'text-yellow-400' },
|
||||
{ name: 'Food and Restaurant', value: 'foodAndRestaurant', oldValue: '13', icon: 'fa-solid fa-utensils', textColorClass: 'text-amber-700' },
|
||||
{ name: 'Real Estate', value: 'realEstate', oldValue: '3', icon: 'fa-solid fa-building', textColorClass: 'text-blue-400' },
|
||||
{ name: 'Retail', value: 'retail', oldValue: '5', icon: 'fa-solid fa-money-bill-wave', textColorClass: 'text-pink-400' },
|
||||
{ name: 'Oilfield SVE and MFG.', value: 'oilfield', oldValue: '6', icon: 'fa-solid fa-oil-well', textColorClass: 'text-indigo-400' },
|
||||
{ name: 'Service', value: 'service', oldValue: '7', icon: 'fa-solid fa-umbrella', textColorClass: 'text-teal-400' },
|
||||
{ name: 'Advertising', value: 'advertising', oldValue: '8', icon: 'fa-solid fa-rectangle-ad', textColorClass: 'text-orange-400' },
|
||||
{ name: 'Agriculture', value: 'agriculture', oldValue: '9', icon: 'fa-solid fa-wheat-awn', textColorClass: 'text-sky-400' },
|
||||
{ name: 'Franchise', value: 'franchise', oldValue: '10', icon: 'fa-solid fa-star', textColorClass: 'text-purple-400' },
|
||||
{ name: 'Professional', value: 'professional', oldValue: '11', icon: 'fa-solid fa-user-gear', textColorClass: 'text-gray-400' },
|
||||
{ name: 'Manufacturing', value: 'manufacturing', oldValue: '12', icon: 'fa-solid fa-industry', textColorClass: 'text-red-400' },
|
||||
{ name: 'Uncategorized', value: 'uncategorized', oldValue: '4', icon: 'fa-solid fa-question', textColorClass: 'text-cyan-400' },
|
||||
];
|
||||
public typesOfCommercialProperty: Array<KeyValueStyle> = [
|
||||
{ name: 'Retail', value: '100', icon: 'fa-solid fa-money-bill-wave', textColorClass: 'text-pink-400' },
|
||||
{ name: 'Land', value: '101', icon: 'fa-solid fa-building', textColorClass: 'text-blue-400' },
|
||||
{ name: 'Industrial', value: '102', icon: 'fa-solid fa-industry', textColorClass: 'text-yellow-400' },
|
||||
{ name: 'Office', value: '103', icon: 'fa-solid fa-umbrella', textColorClass: 'text-teal-400' },
|
||||
{ name: 'Mixed Use', value: '104', icon: 'fa-solid fa-rectangle-ad', textColorClass: 'text-orange-400' },
|
||||
{ name: 'Multifamily', value: '105', icon: 'fa-solid fa-star', textColorClass: 'text-purple-400' },
|
||||
{ name: 'Uncategorized', value: '106', icon: 'fa-solid fa-question', textColorClass: 'text-cyan-400' },
|
||||
{ name: 'Retail', value: 'retail', oldValue: '100', icon: 'fa-solid fa-money-bill-wave', textColorClass: 'text-pink-400' },
|
||||
{ name: 'Land', value: 'land', oldValue: '101', icon: 'fa-solid fa-building', textColorClass: 'text-blue-400' },
|
||||
{ name: 'Industrial', value: 'industrial', oldValue: '102', icon: 'fa-solid fa-industry', textColorClass: 'text-yellow-400' },
|
||||
{ name: 'Office', value: 'office', oldValue: '103', icon: 'fa-solid fa-umbrella', textColorClass: 'text-teal-400' },
|
||||
{ name: 'Mixed Use', value: 'mixedUse', oldValue: '104', icon: 'fa-solid fa-rectangle-ad', textColorClass: 'text-orange-400' },
|
||||
{ name: 'Multifamily', value: 'multifamily', oldValue: '105', icon: 'fa-solid fa-star', textColorClass: 'text-purple-400' },
|
||||
{ name: 'Uncategorized', value: 'uncategorized', oldValue: '106', icon: 'fa-solid fa-question', textColorClass: 'text-cyan-400' },
|
||||
];
|
||||
public prices: Array<KeyValue> = [
|
||||
{ name: '$100K', value: '100000' },
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import * as schema from '../drizzle/schema.js';
|
|||
import { PG_CONNECTION } from '../drizzle/schema.js';
|
||||
import { FileService } from '../file/file.service.js';
|
||||
import { User } from '../models/db.model.js';
|
||||
import { ListingCriteria, emailToDirName } from '../models/main.model.js';
|
||||
import { UserListingCriteria, emailToDirName } from '../models/main.model.js';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
|
|
@ -16,14 +16,14 @@ export class UserService {
|
|||
@Inject(PG_CONNECTION) private conn: NodePgDatabase<typeof schema>,
|
||||
private fileService: FileService,
|
||||
) {}
|
||||
private getConditions(criteria: ListingCriteria): any[] {
|
||||
private getConditions(criteria: UserListingCriteria): any[] {
|
||||
const conditions = [];
|
||||
if (criteria.state) {
|
||||
//conditions.push(sql`EXISTS (SELECT 1 FROM unnest(users."areasServed") AS area WHERE area LIKE '%' || ${criteria.state} || '%')`);
|
||||
conditions.push(sql`${schema.users.areasServed} @> ${JSON.stringify([{ state: criteria.state }])}`);
|
||||
}
|
||||
if (criteria.name) {
|
||||
conditions.push(or(ilike(schema.users.firstname, `%${criteria.name}%`), ilike(schema.users.lastname, `%${criteria.name}%`)));
|
||||
if (criteria.firstname || criteria.lastname) {
|
||||
conditions.push(or(ilike(schema.users.firstname, `%${criteria.lastname}%`), ilike(schema.users.lastname, `%${criteria.lastname}%`)));
|
||||
}
|
||||
return conditions;
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ export class UserService {
|
|||
return newUser as User;
|
||||
}
|
||||
}
|
||||
async findUser(criteria: ListingCriteria) {
|
||||
async findUser(criteria: UserListingCriteria) {
|
||||
const start = criteria.start ? criteria.start : 0;
|
||||
const length = criteria.length ? criteria.length : 12;
|
||||
const conditions = this.getConditions(criteria);
|
||||
|
|
|
|||
|
|
@ -31,3 +31,4 @@
|
|||
</div>
|
||||
}
|
||||
<app-message-container></app-message-container>
|
||||
<app-search-modal></app-search-modal>
|
||||
|
|
|
|||
|
|
@ -2,21 +2,20 @@ import { CommonModule } from '@angular/common';
|
|||
import { Component, HostListener } from '@angular/core';
|
||||
import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from '@angular/router';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import onChange from 'on-change';
|
||||
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { ListingCriteria } from '../../../bizmatch-server/src/models/main.model';
|
||||
import build from '../build';
|
||||
import { FooterComponent } from './components/footer/footer.component';
|
||||
import { HeaderComponent } from './components/header/header.component';
|
||||
import { MessageContainerComponent } from './components/message/message-container.component';
|
||||
import { SearchModalComponent } from './components/search-modal/search-modal.component';
|
||||
import { LoadingService } from './services/loading.service';
|
||||
import { UserService } from './services/user.service';
|
||||
import { createDefaultListingCriteria } from './utils/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterOutlet, HeaderComponent, FooterComponent, MessageContainerComponent],
|
||||
imports: [CommonModule, RouterOutlet, HeaderComponent, FooterComponent, MessageContainerComponent, SearchModalComponent],
|
||||
providers: [],
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.scss',
|
||||
|
|
@ -25,9 +24,7 @@ export class AppComponent {
|
|||
build = build;
|
||||
title = 'bizmatch';
|
||||
actualRoute = '';
|
||||
listingCriteria: ListingCriteria = onChange(createDefaultListingCriteria(), (path, value, previousValue, applyData) => {
|
||||
sessionStorage.setItem('criteria', JSON.stringify(value));
|
||||
});
|
||||
|
||||
public constructor(public loadingService: LoadingService, private router: Router, private activatedRoute: ActivatedRoute, private keycloakService: KeycloakService, private userService: UserService) {
|
||||
this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
|
||||
let currentRoute = this.activatedRoute.root;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { createPopper, Instance as PopperInstance } from '@popperjs/core';
|
|||
@Component({
|
||||
selector: 'app-dropdown',
|
||||
template: `
|
||||
<div #targetEl [class.hidden]="!isVisible" class="z-10">
|
||||
<div #targetEl [class.hidden]="!isVisible" class="z-50">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
`,
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@
|
|||
<button
|
||||
type="button"
|
||||
#triggerButton
|
||||
(click)="openModal()"
|
||||
id="filterDropdownButton"
|
||||
class="max-sm:hidden px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 md:me-2"
|
||||
>
|
||||
|
|
@ -243,24 +244,14 @@
|
|||
</button>
|
||||
</div> -->
|
||||
</nav>
|
||||
|
||||
<!-- ############################### -->
|
||||
<!-- Filter Dropdown -->
|
||||
<!-- ############################### -->
|
||||
<app-dropdown [triggerEl]="triggerButton" [triggerType]="'click'">
|
||||
<div id="filterDropdown" class="z-10 w-80 p-3 bg-slate-200 rounded-lg shadow-lg dark:bg-gray-700">
|
||||
<h3 class="mb-3 text-sm font-medium text-gray-900 dark:text-white">Filter</h3>
|
||||
|
||||
<!-- Price Range -->
|
||||
<!-- <app-dropdown [triggerEl]="triggerButton" [triggerType]="'click'">
|
||||
<div id="filterDropdown" class="z-[50] w-80 p-3 bg-slate-200 rounded-lg shadow-lg dark:bg-gray-700">
|
||||
<div class="mb-4">
|
||||
<div class="flex items-center space-x-4">
|
||||
<input
|
||||
type="text"
|
||||
[ngModel]="prompt"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
value="300"
|
||||
/>
|
||||
</div>
|
||||
<!-- <label for="price-range" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Price Range</label>
|
||||
<label for="price-range" class="block text-sm font-medium text-gray-900 dark:text-white">Price Range</label>
|
||||
<div class="flex items-center space-x-4">
|
||||
<input
|
||||
type="number"
|
||||
|
|
@ -276,12 +267,10 @@
|
|||
placeholder="To"
|
||||
value="3500"
|
||||
/>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- Sales -->
|
||||
<!-- <div class="mb-4">
|
||||
<label for="sales-range" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Sales</label>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="sales-range" class="block text-sm font-medium text-gray-900 dark:text-white">Sales Revenue</label>
|
||||
<div class="flex items-center space-x-4">
|
||||
<input
|
||||
type="number"
|
||||
|
|
@ -298,10 +287,8 @@
|
|||
value="100"
|
||||
/>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Category -->
|
||||
<!-- <div class="mb-4">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Category</label>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button
|
||||
|
|
@ -335,10 +322,8 @@
|
|||
Watch
|
||||
</button>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- State -->
|
||||
<!-- <div class="mb-4">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">State</label>
|
||||
<ul class="w-48 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg dark:bg-gray-700 dark:border-gray-600 dark:text-white">
|
||||
<li class="w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600">
|
||||
|
|
@ -379,9 +364,8 @@
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex justify-between">
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -397,4 +381,4 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</app-dropdown>
|
||||
</app-dropdown> -->
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
|
||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
|
@ -6,14 +6,15 @@ import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
|||
import { faUserGear } from '@fortawesome/free-solid-svg-icons';
|
||||
import { Collapse, Dropdown, initFlowbite } from 'flowbite';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { Observable, Subject, takeUntil } from 'rxjs';
|
||||
import { Observable, Subject, Subscription } from 'rxjs';
|
||||
import { User } from '../../../../../bizmatch-server/src/models/db.model';
|
||||
import { emailToDirName, KeycloakUser } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { SharedService } from '../../services/shared.service';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { map2User } from '../../utils/utils';
|
||||
import { createEmptyBusinessListingCriteria, createEmptyCommercialPropertyListingCriteria, createEmptyUserListingCriteria, map2User } from '../../utils/utils';
|
||||
import { DropdownComponent } from '../dropdown/dropdown.component';
|
||||
import { ModalService } from '../search-modal/modal.service';
|
||||
@Component({
|
||||
selector: 'header',
|
||||
standalone: true,
|
||||
|
|
@ -34,7 +35,15 @@ export class HeaderComponent {
|
|||
isMobile: boolean = false;
|
||||
private destroy$ = new Subject<void>();
|
||||
prompt: string;
|
||||
constructor(public keycloakService: KeycloakService, private router: Router, private userService: UserService, private sharedService: SharedService, private breakpointObserver: BreakpointObserver) {}
|
||||
private subscription: Subscription;
|
||||
constructor(
|
||||
public keycloakService: KeycloakService,
|
||||
private router: Router,
|
||||
private userService: UserService,
|
||||
private sharedService: SharedService,
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
private modalService: ModalService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
const token = await this.keycloakService.getToken();
|
||||
|
|
@ -52,30 +61,40 @@ export class HeaderComponent {
|
|||
initFlowbite();
|
||||
}
|
||||
});
|
||||
this.breakpointObserver
|
||||
.observe([Breakpoints.Handset])
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(result => {
|
||||
this.isMobile = result.matches;
|
||||
const targetEl = document.getElementById('filterDropdown');
|
||||
const triggerEl = this.isMobile ? document.getElementById('filterDropdownMobileButton') : document.getElementById('filterDropdownButton');
|
||||
if (targetEl && triggerEl) {
|
||||
this.filterDropdown = new Dropdown(targetEl, triggerEl);
|
||||
}
|
||||
});
|
||||
|
||||
// this.breakpointObserver
|
||||
// .observe([Breakpoints.Handset])
|
||||
// .pipe(takeUntil(this.destroy$))
|
||||
// .subscribe(result => {
|
||||
// this.isMobile = result.matches;
|
||||
// const targetEl = document.getElementById('filterDropdown');
|
||||
// const triggerEl = this.isMobile ? document.getElementById('filterDropdownMobileButton') : document.getElementById('filterDropdownButton');
|
||||
// if (targetEl && triggerEl) {
|
||||
// this.filterDropdown = new Dropdown(targetEl, triggerEl);
|
||||
// }
|
||||
// });
|
||||
this.sharedService.currentProfilePhoto.subscribe(photoUrl => {
|
||||
if (photoUrl) {
|
||||
this.profileUrl = photoUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
toggleFilterDropdown() {
|
||||
if (this.filterDropdown) {
|
||||
this.filterDropdown.toggle();
|
||||
}
|
||||
}
|
||||
ngAfterViewInit() {}
|
||||
|
||||
// toggleFilterDropdown() {
|
||||
// if (this.filterDropdown) {
|
||||
// this.filterDropdown.toggle();
|
||||
// }
|
||||
// }
|
||||
ngAfterViewInit() {}
|
||||
openModal() {
|
||||
if (this.isActive('/businessListings')) {
|
||||
this.modalService.showModal(createEmptyBusinessListingCriteria());
|
||||
} else if (this.isActive('/commercialPropertyListings')) {
|
||||
this.modalService.showModal(createEmptyCommercialPropertyListingCriteria());
|
||||
} else if (this.isActive('/brokerListings')) {
|
||||
this.modalService.showModal(createEmptyUserListingCriteria());
|
||||
}
|
||||
}
|
||||
navigateWithState(dest: string, state: any) {
|
||||
this.router.navigate([dest], { state: state });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
// 1. Shared Service (modal.service.ts)
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ModalService {
|
||||
private modalVisibleSubject = new BehaviorSubject<boolean>(false);
|
||||
private messageSubject = new BehaviorSubject<BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria>(null);
|
||||
private resolvePromise!: (value: boolean) => void;
|
||||
|
||||
modalVisible$: Observable<boolean> = this.modalVisibleSubject.asObservable();
|
||||
message$: Observable<BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria> = this.messageSubject.asObservable();
|
||||
|
||||
showModal(message: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria): Promise<boolean> {
|
||||
this.messageSubject.next(message);
|
||||
this.modalVisibleSubject.next(true);
|
||||
return new Promise<boolean>(resolve => {
|
||||
this.resolvePromise = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
accept(): void {
|
||||
this.modalVisibleSubject.next(false);
|
||||
this.resolvePromise(true);
|
||||
}
|
||||
|
||||
reject(): void {
|
||||
this.modalVisibleSubject.next(false);
|
||||
this.resolvePromise(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
<!-- <div class="fixed top-0 left-0 right-0 z-50 hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full"> -->
|
||||
<div *ngIf="modalService.modalVisible$ | async" class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full flex items-center justify-center">
|
||||
<div class="relative w-full max-w-4xl max-h-full">
|
||||
<div class="relative bg-white rounded-lg shadow">
|
||||
<div class="flex items-start justify-between p-4 border-b rounded-t">
|
||||
<h3 class="text-xl font-semibold text-gray-900">Business Listing Search</h3>
|
||||
<button (click)="modalService.reject()" type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ml-auto inline-flex justify-center items-center">
|
||||
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
|
||||
</svg>
|
||||
<span class="sr-only">Close Modal</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="p-6 space-y-6">
|
||||
<div class="flex space-x-4 mb-4">
|
||||
<button class="text-blue-600 font-medium border-b-2 border-blue-600 pb-2">Classic Search</button>
|
||||
<button class="text-gray-500">AI Search <span class="bg-gray-200 text-xs font-semibold px-2 py-1 rounded">BETA</span></button>
|
||||
</div>
|
||||
@if(criteria.criteriaType==='business'){
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label for="state" class="block mb-2 text-sm font-medium text-gray-900">Location - State</label>
|
||||
<select id="state" [(ngModel)]="criteria.state" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
|
||||
<option selected>Arkansas</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="city" class="block mb-2 text-sm font-medium text-gray-900">Location - City</label>
|
||||
<input
|
||||
type="text"
|
||||
id="city"
|
||||
[(ngModel)]="criteria.city"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
placeholder="e.g. Houston"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
id="price-from"
|
||||
[(ngModel)]="criteria.minPrice"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="From"
|
||||
/>
|
||||
<span>-</span>
|
||||
<input
|
||||
type="number"
|
||||
id="price-to"
|
||||
[(ngModel)]="criteria.maxPrice"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="To"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="salesRevenue" class="block mb-2 text-sm font-medium text-gray-900">Sales Revenue</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
id="salesRevenue-from"
|
||||
[(ngModel)]="criteria.minRevenue"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="From"
|
||||
/>
|
||||
<span>-</span>
|
||||
<input
|
||||
type="number"
|
||||
id="salesRevenue-to"
|
||||
[(ngModel)]="criteria.maxRevenue"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="To"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="cashflow" class="block mb-2 text-sm font-medium text-gray-900">Cashflow</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
id="cashflow-from"
|
||||
[(ngModel)]="criteria.minCashFlow"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="From"
|
||||
/>
|
||||
<span>-</span>
|
||||
<input
|
||||
type="number"
|
||||
id="cashflow-to"
|
||||
[(ngModel)]="criteria.maxCashFlow"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="To"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="title" class="block mb-2 text-sm font-medium text-gray-900">Title / Description (Free Search)</label>
|
||||
<input
|
||||
type="text"
|
||||
id="title"
|
||||
[(ngModel)]="criteria.title"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
placeholder="e.g. Restaurant"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="brokername" class="block mb-2 text-sm font-medium text-gray-900">Broker Name / Company Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="brokername"
|
||||
[(ngModel)]="criteria.brokerName"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
placeholder="e.g. Brokers Invest"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900">Category</label>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
@for(tob of selectOptions.typesOfBusiness; track tob){
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="automotive"
|
||||
[ngModel]="isTypeOfBusinessClicked(tob)"
|
||||
(ngModelChange)="categoryClicked($event, tob.value)"
|
||||
value="{{ tob.value }}"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"
|
||||
/>
|
||||
<label for="automotive" class="ml-2 text-sm font-medium text-gray-900">{{ tob.name }}</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900">Type of Property</label>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center">
|
||||
<input [(ngModel)]="criteria.realEstateChecked" type="radio" id="realEstateChecked" name="wbs" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500" checked />
|
||||
<label for="realEstateChecked" class="ml-2 text-sm font-medium text-gray-900">Real Estate</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input [(ngModel)]="criteria.leasedLocation" type="radio" id="leasedLocation" name="wbs" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500" />
|
||||
<label for="leasedLocation" class="ml-2 text-sm font-medium text-gray-900">Leased Location</label>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<input [(ngModel)]="criteria.franchiseResale" type="radio" id="franchiseResale" name="wbs" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500" />
|
||||
<label for="franchiseResale" class="ml-2 text-sm font-medium text-gray-900">Franchise</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="numberEmployees" class="block mb-2 text-sm font-medium text-gray-900">Number of Employees</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
id="numberEmployees-from"
|
||||
[(ngModel)]="criteria.minNumberEmployees"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="From"
|
||||
/>
|
||||
<span>-</span>
|
||||
<input
|
||||
type="number"
|
||||
id="numberEmployees-to"
|
||||
[(ngModel)]="criteria.maxNumberEmployees"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="To"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="establishedSince" class="block mb-2 text-sm font-medium text-gray-900">Established Since</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
id="establishedSince-From"
|
||||
[(ngModel)]="criteria.establishedSince"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="YYYY"
|
||||
/>
|
||||
<span>-</span>
|
||||
<input
|
||||
type="number"
|
||||
id="establishedSince-To"
|
||||
[(ngModel)]="criteria.establishedUntil"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="YYYY"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
} @if(criteria.criteriaType==='commercialProperty'){
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label for="state" class="block mb-2 text-sm font-medium text-gray-900">Location - State</label>
|
||||
<select id="state" [(ngModel)]="criteria.state" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
|
||||
<option selected>Arkansas</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="city" class="block mb-2 text-sm font-medium text-gray-900">Location - City</label>
|
||||
<input
|
||||
type="text"
|
||||
id="city"
|
||||
[(ngModel)]="criteria.city"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
placeholder="e.g. Houston"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
type="number"
|
||||
id="price-from"
|
||||
[(ngModel)]="criteria.minPrice"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="From"
|
||||
/>
|
||||
<span>-</span>
|
||||
<input
|
||||
type="number"
|
||||
id="price-to"
|
||||
[(ngModel)]="criteria.maxPrice"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
||||
placeholder="To"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="title" class="block mb-2 text-sm font-medium text-gray-900">Title / Description (Free Search)</label>
|
||||
<input
|
||||
type="text"
|
||||
id="title"
|
||||
[(ngModel)]="criteria.title"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
placeholder="e.g. Restaurant"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900">Category</label>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
@for(tob of selectOptions.typesOfCommercialProperty; track tob){
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="automotive"
|
||||
[ngModel]="isTypeOfBusinessClicked(tob)"
|
||||
(ngModelChange)="categoryClicked($event, tob.value)"
|
||||
value="{{ tob.value }}"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"
|
||||
/>
|
||||
<label for="automotive" class="ml-2 text-sm font-medium text-gray-900">{{ tob.name }}</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
} @if(criteria.criteriaType==='user'){
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label for="states" class="block mb-2 text-sm font-medium text-gray-900">Locations served - States</label>
|
||||
<select id="states" [(ngModel)]="criteria.states" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
|
||||
<option selected>Arkansas</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="counties" class="block mb-2 text-sm font-medium text-gray-900">Locations served - Counties</label>
|
||||
<select id="counties" [(ngModel)]="criteria.counties" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
|
||||
<option selected>Arkansas</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="city" class="block mb-2 text-sm font-medium text-gray-900">Location - City</label>
|
||||
<input
|
||||
type="text"
|
||||
id="city"
|
||||
[(ngModel)]="criteria.city"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
placeholder="e.g. Houston"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900">Category</label>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
@for(tob of selectOptions.customerSubTypes; track tob){
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="automotive"
|
||||
[ngModel]="isTypeOfProfessionalClicked(tob)"
|
||||
(ngModelChange)="categoryClicked($event, tob.value)"
|
||||
value="{{ tob.value }}"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500"
|
||||
/>
|
||||
<label for="automotive" class="ml-2 text-sm font-medium text-gray-900">{{ tob.name }}</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="flex items-center p-6 space-x-2 border-t border-gray-200 rounded-b">
|
||||
<button type="button" (click)="modalService.accept()" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center">
|
||||
Search
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
(click)="modalService.reject()"
|
||||
class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { AsyncPipe, NgIf } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, KeyValue, KeyValueStyle, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { SelectOptionsService } from '../../services/select-options.service';
|
||||
import { SharedModule } from '../../shared/shared/shared.module';
|
||||
import { ModalService } from './modal.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-search-modal',
|
||||
standalone: true,
|
||||
imports: [SharedModule, AsyncPipe, NgIf],
|
||||
templateUrl: './search-modal.component.html',
|
||||
})
|
||||
export class SearchModalComponent {
|
||||
constructor(public selectOptions: SelectOptionsService, public modalService: ModalService) {}
|
||||
ngOnInit() {
|
||||
this.modalService.message$.subscribe(msg => {
|
||||
this.criteria = msg;
|
||||
});
|
||||
}
|
||||
public criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
|
||||
|
||||
categoryClicked(checked: boolean, value: string) {
|
||||
if (checked) {
|
||||
this.criteria.types.push(value);
|
||||
} else {
|
||||
const index = this.criteria.types.findIndex(t => t === value);
|
||||
if (index > -1) {
|
||||
this.criteria.types.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
search() {
|
||||
console.log('Search criteria:', this.criteria);
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
console.log('Closing modal');
|
||||
}
|
||||
isTypeOfBusinessClicked(v: KeyValueStyle) {
|
||||
return this.criteria.types.find(t => t === v.value);
|
||||
}
|
||||
isTypeOfProfessionalClicked(v: KeyValue) {
|
||||
return this.criteria.types.find(t => t === v.value);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import { KeycloakService } from 'keycloak-angular';
|
|||
import onChange from 'on-change';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { KeycloakUser, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { BusinessListingCriteria, KeycloakUser, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { HistoryService } from '../../../services/history.service';
|
||||
import { ListingsService } from '../../../services/listings.service';
|
||||
|
|
@ -43,7 +43,7 @@ export class DetailsBusinessListingComponent {
|
|||
];
|
||||
private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined;
|
||||
listing: BusinessListing;
|
||||
criteria: ListingCriteria;
|
||||
criteria: BusinessListingCriteria;
|
||||
mailinfo: MailInfo;
|
||||
environment = environment;
|
||||
keycloakUser: KeycloakUser;
|
||||
|
|
@ -70,7 +70,7 @@ export class DetailsBusinessListingComponent {
|
|||
}
|
||||
});
|
||||
this.mailinfo = { sender: {}, email: '', url: environment.mailinfoUrl };
|
||||
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
|
||||
this.criteria = onChange(getCriteriaStateObject('business'), getSessionStorageHandler);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { KeycloakService } from 'keycloak-angular';
|
|||
import onChange from 'on-change';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { ErrorResponse, KeycloakUser, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { CommercialPropertyListingCriteria, ErrorResponse, KeycloakUser, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { HistoryService } from '../../../services/history.service';
|
||||
import { ImageService } from '../../../services/image.service';
|
||||
|
|
@ -45,7 +45,7 @@ export class DetailsCommercialPropertyListingComponent {
|
|||
];
|
||||
private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined;
|
||||
listing: CommercialPropertyListing;
|
||||
criteria: ListingCriteria;
|
||||
criteria: CommercialPropertyListingCriteria;
|
||||
mailinfo: MailInfo;
|
||||
environment = environment;
|
||||
keycloakUser: KeycloakUser;
|
||||
|
|
@ -73,7 +73,7 @@ export class DetailsCommercialPropertyListingComponent {
|
|||
) {
|
||||
this.mailinfo = { sender: {}, email: '', url: environment.mailinfoUrl };
|
||||
|
||||
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
|
||||
this.criteria = onChange(getCriteriaStateObject('commercialProperty'), getSessionStorageHandler);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { Observable } from 'rxjs';
|
||||
import { BusinessListing, CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { KeycloakUser, ListingCriteria, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { KeycloakUser, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { HistoryService } from '../../../services/history.service';
|
||||
import { ImageService } from '../../../services/image.service';
|
||||
|
|
@ -27,7 +27,6 @@ export class DetailsUserComponent {
|
|||
user$: Observable<KeycloakUser>;
|
||||
keycloakUser: KeycloakUser;
|
||||
environment = environment;
|
||||
criteria: ListingCriteria;
|
||||
businessListings: BusinessListing[];
|
||||
commercialPropListings: CommercialPropertyListing[];
|
||||
companyOverview: SafeHtml;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import { FormsModule } from '@angular/forms';
|
|||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import onChange from 'on-change';
|
||||
import { KeycloakUser, ListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, KeycloakUser, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { ListingsService } from '../../services/listings.service';
|
||||
import { SelectOptionsService } from '../../services/select-options.service';
|
||||
import { getCriteriaStateObject, getSessionStorageHandler, map2User, resetCriteria } from '../../utils/utils';
|
||||
import { getCriteriaStateObject, getSessionStorageHandler, map2User } from '../../utils/utils';
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
standalone: true,
|
||||
|
|
@ -20,14 +20,13 @@ export class HomeComponent {
|
|||
type: string;
|
||||
maxPrice: string;
|
||||
minPrice: string;
|
||||
criteria: ListingCriteria;
|
||||
criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
|
||||
states = [];
|
||||
isMenuOpen = false;
|
||||
user: KeycloakUser;
|
||||
prompt: string;
|
||||
public constructor(private router: Router, private activatedRoute: ActivatedRoute, public selectOptions: SelectOptionsService, public keycloakService: KeycloakService, private listingsService: ListingsService) {
|
||||
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
|
||||
resetCriteria(this.criteria);
|
||||
this.criteria = onChange(getCriteriaStateObject('business'), getSessionStorageHandler);
|
||||
}
|
||||
async ngOnInit() {
|
||||
const token = await this.keycloakService.getToken();
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import { FormsModule } from '@angular/forms';
|
|||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import onChange from 'on-change';
|
||||
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { ListingCriteria, ListingType, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { ListingType, UserListingCriteria, emailToDirName } 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';
|
||||
import { getCriteriaStateObject, getSessionStorageHandler, resetCriteria } from '../../../utils/utils';
|
||||
import { getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-broker-listings',
|
||||
|
|
@ -24,7 +24,7 @@ export class BrokerListingsComponent {
|
|||
listings: Array<BusinessListing>;
|
||||
users: Array<User>;
|
||||
filteredListings: Array<ListingType>;
|
||||
criteria: ListingCriteria;
|
||||
criteria: UserListingCriteria;
|
||||
realEstateChecked: boolean;
|
||||
maxPrice: string;
|
||||
minPrice: string;
|
||||
|
|
@ -49,10 +49,9 @@ export class BrokerListingsComponent {
|
|||
private imageService: ImageService,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
|
||||
this.criteria = onChange(getCriteriaStateObject('user'), getSessionStorageHandler);
|
||||
this.route.data.subscribe(async () => {
|
||||
if (this.router.getCurrentNavigation().extras.state) {
|
||||
resetCriteria(this.criteria);
|
||||
} else {
|
||||
this.first = this.criteria.page * this.criteria.length;
|
||||
this.rows = this.criteria.length;
|
||||
|
|
@ -86,7 +85,5 @@ export class BrokerListingsComponent {
|
|||
this.criteria.pageCount = event.pageCount;
|
||||
this.search();
|
||||
}
|
||||
reset() {
|
||||
this.criteria.name = '';
|
||||
}
|
||||
reset() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import { FormsModule } from '@angular/forms';
|
|||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import onChange from 'on-change';
|
||||
import { BusinessListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { ListingCriteria, ListingType, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { BusinessListingCriteria, ListingType, emailToDirName } 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 { getCriteriaStateObject, getSessionStorageHandler, resetCriteria } from '../../../utils/utils';
|
||||
import { getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-business-listings',
|
||||
|
|
@ -22,7 +22,7 @@ export class BusinessListingsComponent {
|
|||
environment = environment;
|
||||
listings: Array<BusinessListing>;
|
||||
filteredListings: Array<BusinessListing>;
|
||||
criteria: ListingCriteria;
|
||||
criteria: BusinessListingCriteria;
|
||||
realEstateChecked: boolean;
|
||||
maxPrice: string;
|
||||
minPrice: string;
|
||||
|
|
@ -45,10 +45,9 @@ export class BusinessListingsComponent {
|
|||
private imageService: ImageService,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
|
||||
this.criteria = onChange(getCriteriaStateObject('business'), getSessionStorageHandler);
|
||||
this.route.data.subscribe(async () => {
|
||||
if (this.router.getCurrentNavigation().extras.state) {
|
||||
resetCriteria(this.criteria);
|
||||
} else {
|
||||
this.first = this.criteria.page * this.criteria.length;
|
||||
this.rows = this.criteria.length;
|
||||
|
|
@ -70,12 +69,12 @@ export class BusinessListingsComponent {
|
|||
this.search();
|
||||
}
|
||||
async search() {
|
||||
this.listings = await this.listingsService.getListingsByPrompt(this.criteria);
|
||||
// const listingReponse = await this.listingsService.getListings(this.criteria, 'business');
|
||||
// this.listings = listingReponse.data;
|
||||
// this.totalRecords = listingReponse.total;
|
||||
// this.cdRef.markForCheck();
|
||||
// this.cdRef.detectChanges();
|
||||
//this.listings = await this.listingsService.getListingsByPrompt(this.criteria);
|
||||
const listingReponse = await this.listingsService.getListings(this.criteria, 'business');
|
||||
this.listings = listingReponse.data;
|
||||
this.totalRecords = listingReponse.total;
|
||||
this.cdRef.markForCheck();
|
||||
this.cdRef.detectChanges();
|
||||
}
|
||||
onPageChange(event: any) {
|
||||
this.criteria.start = event.first;
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import { FormsModule } from '@angular/forms';
|
|||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import onChange from 'on-change';
|
||||
import { CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { ListingCriteria } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { CommercialPropertyListingCriteria } 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 { getCriteriaStateObject, getSessionStorageHandler, resetCriteria } from '../../../utils/utils';
|
||||
import { getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-commercial-property-listings',
|
||||
|
|
@ -22,7 +22,7 @@ export class CommercialPropertyListingsComponent {
|
|||
environment = environment;
|
||||
listings: Array<CommercialPropertyListing>;
|
||||
filteredListings: Array<CommercialPropertyListing>;
|
||||
criteria: ListingCriteria;
|
||||
criteria: CommercialPropertyListingCriteria;
|
||||
realEstateChecked: boolean;
|
||||
first: number = 0;
|
||||
rows: number = 12;
|
||||
|
|
@ -44,10 +44,9 @@ export class CommercialPropertyListingsComponent {
|
|||
private imageService: ImageService,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
this.criteria = onChange(getCriteriaStateObject(), getSessionStorageHandler);
|
||||
this.criteria = onChange(getCriteriaStateObject('commercialProperty'), getSessionStorageHandler);
|
||||
this.route.data.subscribe(async () => {
|
||||
if (this.router.getCurrentNavigation().extras.state) {
|
||||
resetCriteria(this.criteria);
|
||||
} else {
|
||||
this.first = this.criteria.page * this.criteria.length;
|
||||
this.rows = this.criteria.length;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,14 @@ import { HttpClient } from '@angular/common/http';
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Observable, lastValueFrom } from 'rxjs';
|
||||
import { BusinessListing } from '../../../../bizmatch-server/src/models/db.model';
|
||||
import { ListingCriteria, ListingType, ResponseBusinessListingArray, ResponseCommercialPropertyListingArray, StatesResult } from '../../../../bizmatch-server/src/models/main.model';
|
||||
import {
|
||||
BusinessListingCriteria,
|
||||
CommercialPropertyListingCriteria,
|
||||
ListingType,
|
||||
ResponseBusinessListingArray,
|
||||
ResponseCommercialPropertyListingArray,
|
||||
StatesResult,
|
||||
} from '../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Injectable({
|
||||
|
|
@ -12,11 +19,14 @@ export class ListingsService {
|
|||
private apiBaseUrl = environment.apiBaseUrl;
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
async getListings(criteria: ListingCriteria, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
|
||||
async getListings(
|
||||
criteria: BusinessListingCriteria | CommercialPropertyListingCriteria,
|
||||
listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty',
|
||||
): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
|
||||
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/find`, criteria));
|
||||
return result;
|
||||
}
|
||||
async getListingsByPrompt(criteria: ListingCriteria): Promise<BusinessListing[]> {
|
||||
async getListingsByPrompt(criteria: BusinessListingCriteria | CommercialPropertyListingCriteria): Promise<BusinessListing[]> {
|
||||
const result = await lastValueFrom(this.http.post<BusinessListing[]>(`${this.apiBaseUrl}/bizmatch/listings/business/search`, criteria));
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ export class SelectOptionsService {
|
|||
getState(value: string): string {
|
||||
return this.states.find(l => l.value === value)?.name;
|
||||
}
|
||||
getBusiness(value: number): string {
|
||||
return this.typesOfBusiness.find(t => t.value === String(value))?.name;
|
||||
getBusiness(value: string): string {
|
||||
return this.typesOfBusiness.find(t => t.value === value)?.name;
|
||||
}
|
||||
getCommercialProperty(value: number): string {
|
||||
return this.typesOfCommercialProperty.find(t => t.value === String(value))?.name;
|
||||
getCommercialProperty(value: string): string {
|
||||
return this.typesOfCommercialProperty.find(t => t.value === value)?.name;
|
||||
}
|
||||
getListingsCategory(value: string): string {
|
||||
return this.listingCategories.find(l => l.value === value)?.name;
|
||||
|
|
@ -57,14 +57,14 @@ export class SelectOptionsService {
|
|||
getIconType(value: string): string {
|
||||
return this.typesOfBusiness.find(c => c.value === value)?.icon;
|
||||
}
|
||||
getTextColorType(value: number): string {
|
||||
return this.typesOfBusiness.find(c => c.value === String(value))?.textColorClass;
|
||||
getTextColorType(value: string): string {
|
||||
return this.typesOfBusiness.find(c => c.value === value)?.textColorClass;
|
||||
}
|
||||
getIconAndTextColorType(value: number): string {
|
||||
const category = this.typesOfBusiness.find(c => c.value === String(value));
|
||||
getIconAndTextColorType(value: string): string {
|
||||
const category = this.typesOfBusiness.find(c => c.value === value);
|
||||
return `${category?.icon} ${category?.textColorClass}`;
|
||||
}
|
||||
getIconTypeOfCommercials(value: number): string {
|
||||
return this.typesOfCommercialProperty.find(c => c.value === String(value))?.icon;
|
||||
getIconTypeOfCommercials(value: string): string {
|
||||
return this.typesOfCommercialProperty.find(c => c.value === value)?.icon;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
|
|||
import { lastValueFrom } from 'rxjs';
|
||||
import urlcat from 'urlcat';
|
||||
import { User } from '../../../../bizmatch-server/src/models/db.model';
|
||||
import { ListingCriteria, ResponseUsersArray, StatesResult } from '../../../../bizmatch-server/src/models/main.model';
|
||||
import { ResponseUsersArray, StatesResult, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Injectable({
|
||||
|
|
@ -27,7 +27,7 @@ export class UserService {
|
|||
const url = urlcat(`${this.apiBaseUrl}/bizmatch/user`, { mail });
|
||||
return await lastValueFrom(this.http.get<User>(url));
|
||||
}
|
||||
async search(criteria?: ListingCriteria): Promise<ResponseUsersArray> {
|
||||
async search(criteria?: UserListingCriteria): Promise<ResponseUsersArray> {
|
||||
return await lastValueFrom(this.http.post<ResponseUsersArray>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria));
|
||||
}
|
||||
async getAllStates(): Promise<any> {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Router } from '@angular/router';
|
|||
import { ConsoleFormattedStream, INFO, createLogger as _createLogger, stdSerializers } from 'browser-bunyan';
|
||||
import { jwtDecode } from 'jwt-decode';
|
||||
import { BusinessListing, CommercialPropertyListing, User } from '../../../../bizmatch-server/src/models/db.model';
|
||||
import { JwtToken, KeycloakUser, ListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, JwtToken, KeycloakUser, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
||||
|
||||
export function createDefaultUser(email: string, firstname: string, lastname: string): User {
|
||||
return {
|
||||
|
|
@ -82,21 +82,69 @@ export function createDefaultBusinessListing(): BusinessListing {
|
|||
listingsCategory: 'business',
|
||||
};
|
||||
}
|
||||
export function createDefaultListingCriteria(): ListingCriteria {
|
||||
export function createEmptyBusinessListingCriteria(): BusinessListingCriteria {
|
||||
return {
|
||||
start: 0,
|
||||
length: 12,
|
||||
length: 0,
|
||||
page: 0,
|
||||
pageCount: 0,
|
||||
type: 0,
|
||||
state: '',
|
||||
city: '',
|
||||
types: [],
|
||||
prompt: '',
|
||||
criteriaType: 'business',
|
||||
county: '',
|
||||
minPrice: null,
|
||||
maxPrice: null,
|
||||
minRevenue: null,
|
||||
maxRevenue: null,
|
||||
minCashFlow: null,
|
||||
maxCashFlow: null,
|
||||
minNumberEmployees: null,
|
||||
maxNumberEmployees: null,
|
||||
establishedSince: null,
|
||||
establishedUntil: null,
|
||||
realEstateChecked: false,
|
||||
leasedLocation: false,
|
||||
franchiseResale: false,
|
||||
title: '',
|
||||
brokerName: '',
|
||||
};
|
||||
}
|
||||
|
||||
export function createEmptyCommercialPropertyListingCriteria(): CommercialPropertyListingCriteria {
|
||||
return {
|
||||
start: 0,
|
||||
length: 0,
|
||||
page: 0,
|
||||
pageCount: 0,
|
||||
state: '',
|
||||
city: '',
|
||||
types: [],
|
||||
prompt: '',
|
||||
criteriaType: 'commercialProperty',
|
||||
county: '',
|
||||
minPrice: 0,
|
||||
maxPrice: 0,
|
||||
realEstateChecked: false,
|
||||
title: '',
|
||||
category: 'broker',
|
||||
name: '',
|
||||
};
|
||||
}
|
||||
|
||||
export function createEmptyUserListingCriteria(): UserListingCriteria {
|
||||
return {
|
||||
start: 0,
|
||||
length: 0,
|
||||
page: 0,
|
||||
pageCount: 0,
|
||||
city: '',
|
||||
types: [],
|
||||
prompt: '',
|
||||
criteriaType: 'user',
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
companyName: '',
|
||||
counties: [],
|
||||
states: [],
|
||||
};
|
||||
}
|
||||
export function createLogger(name: string, level: number = INFO, options: any = {}) {
|
||||
|
|
@ -120,8 +168,15 @@ export const getSessionStorageHandler = function (path, value, previous, applyDa
|
|||
sessionStorage.setItem('criteria', JSON.stringify(this));
|
||||
};
|
||||
|
||||
export function getCriteriaStateObject() {
|
||||
const initialState = createDefaultListingCriteria();
|
||||
export function getCriteriaStateObject(criteriaType: 'business' | 'commercialProperty' | 'user') {
|
||||
let initialState;
|
||||
if (criteriaType === 'business') {
|
||||
initialState = createEmptyBusinessListingCriteria();
|
||||
} else if (criteriaType === 'commercialProperty') {
|
||||
initialState = createEmptyCommercialPropertyListingCriteria();
|
||||
} else {
|
||||
initialState = createEmptyUserListingCriteria();
|
||||
}
|
||||
const storedState = sessionStorage.getItem('criteria');
|
||||
return storedState ? JSON.parse(storedState) : initialState;
|
||||
}
|
||||
|
|
@ -134,17 +189,6 @@ export function routeListingWithState(router: Router, value: string, data: any)
|
|||
}
|
||||
}
|
||||
|
||||
export function resetCriteria(criteria: ListingCriteria) {
|
||||
criteria.type = null;
|
||||
criteria.state = null;
|
||||
criteria.minPrice = null;
|
||||
criteria.maxPrice = null;
|
||||
criteria.start = 0;
|
||||
criteria.length = 12;
|
||||
criteria.realEstateChecked = null;
|
||||
criteria.title = null;
|
||||
criteria.name = null;
|
||||
}
|
||||
export function map2User(jwt: string): KeycloakUser {
|
||||
if (jwt) {
|
||||
const token = jwtDecode<JwtToken>(jwt);
|
||||
|
|
|
|||
Loading…
Reference in New Issue